From bb4deb8014a8457425c2e6e4a8619969514824ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20=C3=81ngel?= Date: Thu, 29 Oct 2026 05:03:43 +0000 Subject: [PATCH] fix(cli): an unknown command like search says which command does that (#6710) * fix(cli): an unknown command like search says which command does that * fix(cli): the synonym hint is checked before the spelling match, so list, find and browse reach it --- packages/cli/src/cli.agentMode.test.ts | 6 ++++++ packages/cli/src/cli.ts | 7 +++++-- packages/cli/src/utils/didYouMean.ts | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/cli.agentMode.test.ts b/packages/cli/src/cli.agentMode.test.ts index 4624d3a8ab..e58b4536b1 100644 --- a/packages/cli/src/cli.agentMode.test.ts +++ b/packages/cli/src/cli.agentMode.test.ts @@ -286,6 +286,12 @@ describe("agent-mode contract", () => { ["cloud rendr", "Did you mean 'hyperframes cloud render'?"], ["help rendr", "Did you mean 'hyperframes render'?"], ["help cloud rendr", "Did you mean 'hyperframes cloud render'?"], + ["search crossfade", "Did you mean 'hyperframes catalog'?"], + ["install crossfade", "Did you mean 'hyperframes add'?"], + ["find crossfade", "Did you mean 'hyperframes catalog'?"], + ["list", "Did you mean 'hyperframes catalog'?"], + ["browse", "Did you mean 'hyperframes catalog'?"], + ["registry", "Did you mean 'hyperframes catalog'?"], ])( "unknown command `%s` suggests the closest one, usage on stderr, exit 2", async (args, hint) => { diff --git a/packages/cli/src/cli.ts b/packages/cli/src/cli.ts index 0c114392f3..6772c56d79 100644 --- a/packages/cli/src/cli.ts +++ b/packages/cli/src/cli.ts @@ -98,7 +98,7 @@ import { markCommandDelivered, } from "./utils/render-success-state.js"; import { resolveCommandUsage, type ResolvedCommandUsage } from "./utils/commandUsageResolution.js"; -import { closestMatch } from "./utils/didYouMean.js"; +import { closestMatch, synonymMatch } from "./utils/didYouMean.js"; import { jsonErrorBody, watchOutput, writeJsonFailure } from "./utils/jsonError.js"; import { isDevMode } from "./utils/env.js"; import { @@ -542,7 +542,10 @@ async function unknownCommandError(requested: ResolvedCommandUsage): Promise): strin } return best; } + +const COMMAND_SYNONYMS: Record = { + search: "catalog", + find: "catalog", + browse: "catalog", + registry: "catalog", + list: "catalog", + install: "add", +}; + +export function synonymMatch(input: string, candidates: Iterable): string | undefined { + const target = COMMAND_SYNONYMS[input]; + return target !== undefined && [...candidates].includes(target) ? target : undefined; +}