fix(app): show one /exit row with /quit and /q as aliases
This commit is contained in:
@@ -181,7 +181,7 @@ test.describe("Client slash commands", () => {
|
|||||||
page,
|
page,
|
||||||
{ title: "Slash quit autocomplete e2e" },
|
{ title: "Slash quit autocomplete e2e" },
|
||||||
async ({ agent, title }) => {
|
async ({ agent, title }) => {
|
||||||
await selectClientSlashCommand(page, "/qu", "/quit");
|
await selectClientSlashCommand(page, "/qu", "/exit");
|
||||||
await expectWorkspaceTabHidden(page, agent.id);
|
await expectWorkspaceTabHidden(page, agent.id);
|
||||||
await expectAgentArchivedInSessions(page, title);
|
await expectAgentArchivedInSessions(page, title);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -57,33 +57,41 @@ function createAgent(overrides: Partial<Agent> = {}): Agent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe("resolveClientSlashCommand", () => {
|
describe("resolveClientSlashCommand", () => {
|
||||||
it("declares the exact client commands that execute immediately", () => {
|
it("declares the exact canonical client commands with their aliases", () => {
|
||||||
expect(CLIENT_SLASH_COMMANDS.map((command) => [command.name, command.execution])).toEqual([
|
expect(
|
||||||
["quit", "immediate"],
|
CLIENT_SLASH_COMMANDS.map((command) => [
|
||||||
["exit", "immediate"],
|
command.name,
|
||||||
["q", "immediate"],
|
[...command.aliases],
|
||||||
["clear", "immediate"],
|
command.execution,
|
||||||
["new", "immediate"],
|
]),
|
||||||
|
).toEqual([
|
||||||
|
["exit", ["quit", "q"], "immediate"],
|
||||||
|
["clear", ["new"], "immediate"],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("resolves exact client commands after trimming", () => {
|
it("resolves canonical names and aliases after trimming", () => {
|
||||||
expect(resolveClientSlashCommand({ text: " /quit ", hasAttachments: false })).toMatchObject({
|
expect(resolveClientSlashCommand({ text: " /quit ", hasAttachments: false })).toMatchObject({
|
||||||
|
name: "exit",
|
||||||
kind: "archive-agent",
|
kind: "archive-agent",
|
||||||
execution: "immediate",
|
execution: "immediate",
|
||||||
});
|
});
|
||||||
expect(resolveClientSlashCommand({ text: "/exit", hasAttachments: false })?.kind).toBe(
|
expect(resolveClientSlashCommand({ text: "/exit", hasAttachments: false })).toMatchObject({
|
||||||
"archive-agent",
|
name: "exit",
|
||||||
);
|
kind: "archive-agent",
|
||||||
expect(resolveClientSlashCommand({ text: "/q", hasAttachments: false })?.kind).toBe(
|
});
|
||||||
"archive-agent",
|
expect(resolveClientSlashCommand({ text: "/q", hasAttachments: false })).toMatchObject({
|
||||||
);
|
name: "exit",
|
||||||
expect(resolveClientSlashCommand({ text: "/clear", hasAttachments: false })?.kind).toBe(
|
kind: "archive-agent",
|
||||||
"replace-agent-with-draft",
|
});
|
||||||
);
|
expect(resolveClientSlashCommand({ text: "/clear", hasAttachments: false })).toMatchObject({
|
||||||
expect(resolveClientSlashCommand({ text: "/new", hasAttachments: false })?.kind).toBe(
|
name: "clear",
|
||||||
"replace-agent-with-draft",
|
kind: "replace-agent-with-draft",
|
||||||
);
|
});
|
||||||
|
expect(resolveClientSlashCommand({ text: "/new", hasAttachments: false })).toMatchObject({
|
||||||
|
name: "clear",
|
||||||
|
kind: "replace-agent-with-draft",
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("leaves provider commands, arguments, ordinary messages, and attachment submits alone", () => {
|
it("leaves provider commands, arguments, ordinary messages, and attachment submits alone", () => {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ export type ClientSlashCommandExecution = "immediate" | "insert";
|
|||||||
|
|
||||||
export interface ClientSlashCommand {
|
export interface ClientSlashCommand {
|
||||||
name: string;
|
name: string;
|
||||||
|
aliases: readonly string[];
|
||||||
description: string;
|
description: string;
|
||||||
argumentHint: string;
|
argumentHint: string;
|
||||||
kind: ClientSlashCommandKind;
|
kind: ClientSlashCommandKind;
|
||||||
@@ -13,22 +14,9 @@ export interface ClientSlashCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const CLIENT_SLASH_COMMANDS: readonly ClientSlashCommand[] = [
|
export const CLIENT_SLASH_COMMANDS: readonly ClientSlashCommand[] = [
|
||||||
{
|
|
||||||
name: "quit",
|
|
||||||
description: "Archive the current agent",
|
|
||||||
argumentHint: "",
|
|
||||||
kind: "archive-agent",
|
|
||||||
execution: "immediate",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "exit",
|
name: "exit",
|
||||||
description: "Archive the current agent",
|
aliases: ["quit", "q"],
|
||||||
argumentHint: "",
|
|
||||||
kind: "archive-agent",
|
|
||||||
execution: "immediate",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "q",
|
|
||||||
description: "Archive the current agent",
|
description: "Archive the current agent",
|
||||||
argumentHint: "",
|
argumentHint: "",
|
||||||
kind: "archive-agent",
|
kind: "archive-agent",
|
||||||
@@ -36,13 +24,7 @@ export const CLIENT_SLASH_COMMANDS: readonly ClientSlashCommand[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "clear",
|
name: "clear",
|
||||||
description: "Archive this agent and start a fresh draft",
|
aliases: ["new"],
|
||||||
argumentHint: "",
|
|
||||||
kind: "replace-agent-with-draft",
|
|
||||||
execution: "immediate",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "new",
|
|
||||||
description: "Archive this agent and start a fresh draft",
|
description: "Archive this agent and start a fresh draft",
|
||||||
argumentHint: "",
|
argumentHint: "",
|
||||||
kind: "replace-agent-with-draft",
|
kind: "replace-agent-with-draft",
|
||||||
@@ -50,7 +32,13 @@ export const CLIENT_SLASH_COMMANDS: readonly ClientSlashCommand[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const COMMAND_BY_NAME = new Map(CLIENT_SLASH_COMMANDS.map((command) => [command.name, command]));
|
const COMMAND_BY_NAME = new Map<string, ClientSlashCommand>();
|
||||||
|
for (const command of CLIENT_SLASH_COMMANDS) {
|
||||||
|
COMMAND_BY_NAME.set(command.name, command);
|
||||||
|
for (const alias of command.aliases) {
|
||||||
|
COMMAND_BY_NAME.set(alias, command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function resolveClientSlashCommand(input: {
|
export function resolveClientSlashCommand(input: {
|
||||||
text: string;
|
text: string;
|
||||||
|
|||||||
@@ -324,9 +324,13 @@ export function useAgentAutocomplete(input: UseAgentAutocompleteInput): AgentAut
|
|||||||
),
|
),
|
||||||
...providerCommands,
|
...providerCommands,
|
||||||
];
|
];
|
||||||
const matches = availableCommands.filter((entry) =>
|
const matches = availableCommands.filter((entry) => {
|
||||||
entry.command.name.toLowerCase().includes(filterLower),
|
if (entry.source === "provider") {
|
||||||
);
|
return entry.command.name.toLowerCase().includes(filterLower);
|
||||||
|
}
|
||||||
|
const candidates = [entry.command.name, ...entry.command.aliases];
|
||||||
|
return candidates.some((candidate) => candidate.toLowerCase().includes(filterLower));
|
||||||
|
});
|
||||||
const orderedMatches = orderAutocompleteOptions(matches);
|
const orderedMatches = orderAutocompleteOptions(matches);
|
||||||
return orderedMatches.map(mapCommandToOption);
|
return orderedMatches.map(mapCommandToOption);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user