fix: add fuzzy suggestions and filter context to spawn list (#501)

When `spawn list -a/-c` filter returns no results, suggest corrections
using the same fuzzy matching used elsewhere in the CLI. Also show total
history count so users know other entries exist.

When filter matches results, show "Showing X of Y spawns" with a
"Clear filter" hint instead of the default footer.

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
A 2026-02-11 11:53:44 -08:00 committed by GitHub
parent 9e4ea1e474
commit f244a4278e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 106 additions and 5 deletions

View file

@ -748,6 +748,40 @@ export async function cmdList(agentFilter?: string, cloudFilter?: string): Promi
if (agentFilter) parts.push(`agent=${pc.bold(agentFilter)}`);
if (cloudFilter) parts.push(`cloud=${pc.bold(cloudFilter)}`);
p.log.info(`No spawns found matching ${parts.join(", ")}.`);
// Suggest corrections for filter values using manifest data
try {
const manifest = await loadManifest();
if (agentFilter) {
const resolved = resolveAgentKey(manifest, agentFilter);
if (resolved && resolved !== agentFilter) {
p.log.info(`Did you mean ${pc.cyan(`spawn list -a ${resolved}`)}?`);
} else if (!resolved) {
const match = findClosestKeyByNameOrKey(agentFilter, agentKeys(manifest), (k) => manifest.agents[k].name);
if (match) {
p.log.info(`Did you mean ${pc.cyan(`spawn list -a ${match}`)}?`);
}
}
}
if (cloudFilter) {
const resolved = resolveCloudKey(manifest, cloudFilter);
if (resolved && resolved !== cloudFilter) {
p.log.info(`Did you mean ${pc.cyan(`spawn list -c ${resolved}`)}?`);
} else if (!resolved) {
const match = findClosestKeyByNameOrKey(cloudFilter, cloudKeys(manifest), (k) => manifest.clouds[k].name);
if (match) {
p.log.info(`Did you mean ${pc.cyan(`spawn list -c ${match}`)}?`);
}
}
}
} catch {
// Manifest unavailable -- skip suggestions
}
const totalRecords = filterHistory();
if (totalRecords.length > 0) {
p.log.info(`Run ${pc.cyan("spawn list")} to see all ${totalRecords.length} recorded spawn${totalRecords.length !== 1 ? "s" : ""}.`);
}
} else {
p.log.info("No spawns recorded yet.");
p.log.info(`Run ${pc.cyan("spawn <agent> <cloud>")} to launch your first agent.`);
@ -783,8 +817,14 @@ export async function cmdList(agentFilter?: string, cloudFilter?: string): Promi
console.log(`Rerun last: ${pc.cyan(`spawn ${latest.agent} ${latest.cloud}`)}`);
}
console.log(pc.dim(`${records.length} spawn${records.length !== 1 ? "s" : ""} recorded`));
console.log(pc.dim(`Filter: ${pc.cyan("spawn list -a <agent>")} or ${pc.cyan("spawn list -c <cloud>")}`));
if (agentFilter || cloudFilter) {
const totalRecords = filterHistory();
console.log(pc.dim(`Showing ${records.length} of ${totalRecords.length} spawn${totalRecords.length !== 1 ? "s" : ""}`));
console.log(pc.dim(`Clear filter: ${pc.cyan("spawn list")}`));
} else {
console.log(pc.dim(`${records.length} spawn${records.length !== 1 ? "s" : ""} recorded`));
console.log(pc.dim(`Filter: ${pc.cyan("spawn list -a <agent>")} or ${pc.cyan("spawn list -c <cloud>")}`));
}
console.log();
}