fix: standardize slash command help and error messages (#999)
This commit is contained in:
167
src/cli/App.tsx
167
src/cli/App.tsx
@@ -102,7 +102,6 @@ import type { ToolsetName, ToolsetPreference } from "../tools/toolset";
|
||||
import { debugLog, debugWarn } from "../utils/debug";
|
||||
import {
|
||||
handleMcpAdd,
|
||||
handleMcpUsage,
|
||||
type McpCommandContext,
|
||||
setActiveCommandId as setActiveMcpCommandId,
|
||||
} from "./commands/mcp";
|
||||
@@ -5990,15 +5989,33 @@ export default function App({
|
||||
return { submitted: true };
|
||||
}
|
||||
|
||||
// /mcp help - show usage
|
||||
if (firstWord === "help") {
|
||||
const cmd = commandRunner.start(msg, "Showing MCP help...");
|
||||
const output = [
|
||||
"/mcp help",
|
||||
"",
|
||||
"Manage MCP servers.",
|
||||
"",
|
||||
"USAGE",
|
||||
" /mcp — open MCP server manager",
|
||||
" /mcp add ... — add a new server (without OAuth)",
|
||||
" /mcp connect — interactive wizard with OAuth support",
|
||||
" /mcp help — show this help",
|
||||
"",
|
||||
"EXAMPLES",
|
||||
" /mcp add --transport http notion https://mcp.notion.com/mcp",
|
||||
].join("\n");
|
||||
cmd.finish(output, true);
|
||||
return { submitted: true };
|
||||
}
|
||||
|
||||
// Unknown subcommand
|
||||
{
|
||||
const cmd = commandRunner.start(msg, "Checking MCP usage...");
|
||||
setActiveMcpCommandId(cmd.id);
|
||||
try {
|
||||
handleMcpUsage(mcpCtx, msg);
|
||||
} finally {
|
||||
setActiveMcpCommandId(null);
|
||||
}
|
||||
cmd.fail(
|
||||
`Unknown subcommand: "${firstWord}". Run /mcp help for usage.`,
|
||||
);
|
||||
}
|
||||
return { submitted: true };
|
||||
}
|
||||
@@ -6716,18 +6733,38 @@ export default function App({
|
||||
// Supports: /compact, /compact all, /compact sliding_window
|
||||
if (msg.trim().startsWith("/compact")) {
|
||||
const parts = msg.trim().split(/\s+/);
|
||||
const modeArg = parts[1] as "all" | "sliding_window" | undefined;
|
||||
const rawModeArg = parts[1];
|
||||
const validModes = ["all", "sliding_window"];
|
||||
|
||||
if (rawModeArg === "help") {
|
||||
const cmd = commandRunner.start(
|
||||
msg.trim(),
|
||||
"Showing compact help...",
|
||||
);
|
||||
const output = [
|
||||
"/compact help",
|
||||
"",
|
||||
"Summarize conversation history (compaction).",
|
||||
"",
|
||||
"USAGE",
|
||||
" /compact — compact with default mode",
|
||||
" /compact all — compact all messages",
|
||||
" /compact sliding_window — compact with sliding window",
|
||||
" /compact help — show this help",
|
||||
].join("\n");
|
||||
cmd.finish(output, true);
|
||||
return { submitted: true };
|
||||
}
|
||||
|
||||
const modeArg = rawModeArg as "all" | "sliding_window" | undefined;
|
||||
|
||||
// Validate mode if provided
|
||||
if (modeArg && !validModes.includes(modeArg)) {
|
||||
const cmd = commandRunner.start(
|
||||
msg.trim(),
|
||||
`Invalid mode "${modeArg}". Valid modes: ${validModes.join(", ")}`,
|
||||
);
|
||||
cmd.fail(
|
||||
`Invalid mode "${modeArg}". Valid modes: ${validModes.join(", ")}`,
|
||||
`Invalid mode "${modeArg}".`,
|
||||
);
|
||||
cmd.fail(`Invalid mode "${modeArg}". Run /compact help for usage.`);
|
||||
return { submitted: true };
|
||||
}
|
||||
|
||||
@@ -6839,6 +6876,21 @@ export default function App({
|
||||
const subcommand = parts[1]?.toLowerCase();
|
||||
const cmd = commandRunner.start(msg.trim(), "Processing rename...");
|
||||
|
||||
if (subcommand === "help") {
|
||||
const output = [
|
||||
"/rename help",
|
||||
"",
|
||||
"Rename the current agent or conversation.",
|
||||
"",
|
||||
"USAGE",
|
||||
" /rename agent <name> — rename the agent",
|
||||
" /rename convo <summary> — rename the conversation",
|
||||
" /rename help — show this help",
|
||||
].join("\n");
|
||||
cmd.finish(output, true);
|
||||
return { submitted: true };
|
||||
}
|
||||
|
||||
if (
|
||||
!subcommand ||
|
||||
(subcommand !== "agent" && subcommand !== "convo")
|
||||
@@ -6919,8 +6971,22 @@ export default function App({
|
||||
"Updating description...",
|
||||
);
|
||||
|
||||
if (newDescription === "help") {
|
||||
const output = [
|
||||
"/description help",
|
||||
"",
|
||||
"Update the current agent's description.",
|
||||
"",
|
||||
"USAGE",
|
||||
" /description <text> — set agent description",
|
||||
" /description help — show this help",
|
||||
].join("\n");
|
||||
cmd.finish(output, true);
|
||||
return { submitted: true };
|
||||
}
|
||||
|
||||
if (!newDescription) {
|
||||
cmd.fail("Please provide a description: /description <text>");
|
||||
cmd.fail("Usage: /description <text>");
|
||||
return { submitted: true };
|
||||
}
|
||||
|
||||
@@ -6966,6 +7032,25 @@ export default function App({
|
||||
const parts = msg.trim().split(/\s+/);
|
||||
const targetConvId = parts[1]; // Optional conversation ID
|
||||
|
||||
if (targetConvId === "help") {
|
||||
const cmd = commandRunner.start(
|
||||
msg.trim(),
|
||||
"Showing resume help...",
|
||||
);
|
||||
const output = [
|
||||
"/resume help",
|
||||
"",
|
||||
"Resume a previous conversation.",
|
||||
"",
|
||||
"USAGE",
|
||||
" /resume — open conversation selector",
|
||||
" /resume <conversation_id> — switch directly to a conversation",
|
||||
" /resume help — show this help",
|
||||
].join("\n");
|
||||
cmd.finish(output, true);
|
||||
return { submitted: true };
|
||||
}
|
||||
|
||||
if (targetConvId) {
|
||||
const cmd = commandRunner.start(
|
||||
msg.trim(),
|
||||
@@ -7255,6 +7340,22 @@ export default function App({
|
||||
if (msg.trim() === "/pin" || msg.trim().startsWith("/pin ")) {
|
||||
const argsStr = msg.trim().slice(4).trim();
|
||||
|
||||
if (argsStr === "help") {
|
||||
const cmd = commandRunner.start(msg.trim(), "Showing pin help...");
|
||||
const output = [
|
||||
"/pin help",
|
||||
"",
|
||||
"Pin the current agent.",
|
||||
"",
|
||||
"USAGE",
|
||||
" /pin — pin globally (interactive)",
|
||||
" /pin -l — pin locally to this directory",
|
||||
" /pin help — show this help",
|
||||
].join("\n");
|
||||
cmd.finish(output, true);
|
||||
return { submitted: true };
|
||||
}
|
||||
|
||||
// Parse args to check if name was provided
|
||||
const parts = argsStr.split(/\s+/).filter(Boolean);
|
||||
let hasNameArg = false;
|
||||
@@ -7304,6 +7405,27 @@ export default function App({
|
||||
|
||||
// Special handling for /unpin command - unpin current agent from project (or globally with -g)
|
||||
if (msg.trim() === "/unpin" || msg.trim().startsWith("/unpin ")) {
|
||||
const unpinArgsStr = msg.trim().slice(6).trim();
|
||||
|
||||
if (unpinArgsStr === "help") {
|
||||
const cmd = commandRunner.start(
|
||||
msg.trim(),
|
||||
"Showing unpin help...",
|
||||
);
|
||||
const output = [
|
||||
"/unpin help",
|
||||
"",
|
||||
"Unpin the current agent.",
|
||||
"",
|
||||
"USAGE",
|
||||
" /unpin — unpin globally",
|
||||
" /unpin -l — unpin locally",
|
||||
" /unpin help — show this help",
|
||||
].join("\n");
|
||||
cmd.finish(output, true);
|
||||
return { submitted: true };
|
||||
}
|
||||
|
||||
const profileCtx: ProfileCommandContext = {
|
||||
buffersRef,
|
||||
refreshDerived,
|
||||
@@ -7454,12 +7576,17 @@ export default function App({
|
||||
|
||||
if (!subcommand || subcommand === "help") {
|
||||
const output = [
|
||||
"memfs commands:",
|
||||
"- /memfs status — show status",
|
||||
"- /memfs enable — enable filesystem-backed memory",
|
||||
"- /memfs disable — disable filesystem-backed memory",
|
||||
"- /memfs sync — sync blocks and files now",
|
||||
"- /memfs reset — move local memfs to /tmp and recreate dirs",
|
||||
"/memfs help",
|
||||
"",
|
||||
"Manage filesystem-backed memory.",
|
||||
"",
|
||||
"USAGE",
|
||||
" /memfs status — show status",
|
||||
" /memfs enable — enable filesystem-backed memory",
|
||||
" /memfs disable — disable filesystem-backed memory",
|
||||
" /memfs sync — sync blocks and files now",
|
||||
" /memfs reset — move local memfs to /tmp and recreate dirs",
|
||||
" /memfs help — show this help",
|
||||
].join("\n");
|
||||
cmd.finish(output, true);
|
||||
return { submitted: true };
|
||||
@@ -7668,7 +7795,7 @@ export default function App({
|
||||
|
||||
// Unknown subcommand
|
||||
cmd.fail(
|
||||
`Unknown subcommand: ${subcommand}. Use /memfs, /memfs enable, /memfs disable, /memfs sync, or /memfs reset.`,
|
||||
`Unknown subcommand: "${subcommand}". Run /memfs help for usage.`,
|
||||
);
|
||||
return { submitted: true };
|
||||
}
|
||||
|
||||
@@ -617,13 +617,36 @@ export async function handleDisconnect(
|
||||
const parts = msg.trim().split(/\s+/);
|
||||
const provider = parts[1]?.toLowerCase();
|
||||
|
||||
// /disconnect help
|
||||
if (provider === "help") {
|
||||
addCommandResult(
|
||||
ctx.buffersRef,
|
||||
ctx.refreshDerived,
|
||||
msg,
|
||||
[
|
||||
"/disconnect help",
|
||||
"",
|
||||
"Disconnect an existing account.",
|
||||
"",
|
||||
"USAGE",
|
||||
" /disconnect <provider> — disconnect a provider",
|
||||
" /disconnect help — show this help",
|
||||
"",
|
||||
"PROVIDERS",
|
||||
" codex, claude, zai, minimax, openrouter, bedrock",
|
||||
].join("\n"),
|
||||
true,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// If no provider specified, show usage
|
||||
if (!provider) {
|
||||
addCommandResult(
|
||||
ctx.buffersRef,
|
||||
ctx.refreshDerived,
|
||||
msg,
|
||||
"Usage: /disconnect <provider>\n\nAvailable providers: codex, claude, zai, minimax, openrouter, bedrock",
|
||||
"Usage: /disconnect <provider>",
|
||||
false,
|
||||
);
|
||||
return;
|
||||
@@ -670,7 +693,7 @@ export async function handleDisconnect(
|
||||
ctx.buffersRef,
|
||||
ctx.refreshDerived,
|
||||
msg,
|
||||
`Error: Unknown provider "${provider}"\n\nAvailable providers: codex, claude, zai, minimax, openrouter, bedrock\nUsage: /disconnect <provider>`,
|
||||
`Unknown provider: "${provider}". Run /disconnect help for usage.`,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -274,6 +274,19 @@ export const commands: Record<string, Command> = {
|
||||
desc: "Setup terminal shortcuts [--revert]",
|
||||
order: 37,
|
||||
handler: async (args: string[]) => {
|
||||
if (args.includes("help")) {
|
||||
return [
|
||||
"/terminal help",
|
||||
"",
|
||||
"Setup terminal keyboard shortcuts.",
|
||||
"",
|
||||
"USAGE",
|
||||
" /terminal — install Shift+Enter keybinding",
|
||||
" /terminal --revert — remove keybinding",
|
||||
" /terminal help — show this help",
|
||||
].join("\n");
|
||||
}
|
||||
|
||||
const {
|
||||
detectTerminalType,
|
||||
getKeybindingsPath,
|
||||
|
||||
Reference in New Issue
Block a user