Migrate /corgi (#4419)
This commit is contained in:
parent
5df6c9fb66
commit
ca07b5b0c4
|
@ -11,6 +11,7 @@ import { type SlashCommand } from '../ui/commands/types.js';
|
||||||
import { memoryCommand } from '../ui/commands/memoryCommand.js';
|
import { memoryCommand } from '../ui/commands/memoryCommand.js';
|
||||||
import { helpCommand } from '../ui/commands/helpCommand.js';
|
import { helpCommand } from '../ui/commands/helpCommand.js';
|
||||||
import { clearCommand } from '../ui/commands/clearCommand.js';
|
import { clearCommand } from '../ui/commands/clearCommand.js';
|
||||||
|
import { corgiCommand } from '../ui/commands/corgiCommand.js';
|
||||||
import { docsCommand } from '../ui/commands/docsCommand.js';
|
import { docsCommand } from '../ui/commands/docsCommand.js';
|
||||||
import { chatCommand } from '../ui/commands/chatCommand.js';
|
import { chatCommand } from '../ui/commands/chatCommand.js';
|
||||||
import { authCommand } from '../ui/commands/authCommand.js';
|
import { authCommand } from '../ui/commands/authCommand.js';
|
||||||
|
@ -38,6 +39,9 @@ vi.mock('../ui/commands/helpCommand.js', () => ({
|
||||||
vi.mock('../ui/commands/clearCommand.js', () => ({
|
vi.mock('../ui/commands/clearCommand.js', () => ({
|
||||||
clearCommand: { name: 'clear', description: 'Mock Clear' },
|
clearCommand: { name: 'clear', description: 'Mock Clear' },
|
||||||
}));
|
}));
|
||||||
|
vi.mock('../ui/commands/corgiCommand.js', () => ({
|
||||||
|
corgiCommand: { name: 'corgi', description: 'Mock Corgi' },
|
||||||
|
}));
|
||||||
vi.mock('../ui/commands/docsCommand.js', () => ({
|
vi.mock('../ui/commands/docsCommand.js', () => ({
|
||||||
docsCommand: { name: 'docs', description: 'Mock Docs' },
|
docsCommand: { name: 'docs', description: 'Mock Docs' },
|
||||||
}));
|
}));
|
||||||
|
@ -85,7 +89,7 @@ vi.mock('../ui/commands/restoreCommand.js', () => ({
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('CommandService', () => {
|
describe('CommandService', () => {
|
||||||
const subCommandLen = 17;
|
const subCommandLen = 18;
|
||||||
let mockConfig: Mocked<Config>;
|
let mockConfig: Mocked<Config>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
@ -128,6 +132,8 @@ describe('CommandService', () => {
|
||||||
expect(commandNames).toContain('memory');
|
expect(commandNames).toContain('memory');
|
||||||
expect(commandNames).toContain('help');
|
expect(commandNames).toContain('help');
|
||||||
expect(commandNames).toContain('clear');
|
expect(commandNames).toContain('clear');
|
||||||
|
expect(commandNames).toContain('compress');
|
||||||
|
expect(commandNames).toContain('corgi');
|
||||||
expect(commandNames).toContain('docs');
|
expect(commandNames).toContain('docs');
|
||||||
expect(commandNames).toContain('chat');
|
expect(commandNames).toContain('chat');
|
||||||
expect(commandNames).toContain('theme');
|
expect(commandNames).toContain('theme');
|
||||||
|
@ -136,7 +142,6 @@ describe('CommandService', () => {
|
||||||
expect(commandNames).toContain('about');
|
expect(commandNames).toContain('about');
|
||||||
expect(commandNames).toContain('extensions');
|
expect(commandNames).toContain('extensions');
|
||||||
expect(commandNames).toContain('tools');
|
expect(commandNames).toContain('tools');
|
||||||
expect(commandNames).toContain('compress');
|
|
||||||
expect(commandNames).toContain('mcp');
|
expect(commandNames).toContain('mcp');
|
||||||
expect(commandNames).not.toContain('ide');
|
expect(commandNames).not.toContain('ide');
|
||||||
});
|
});
|
||||||
|
@ -201,6 +206,7 @@ describe('CommandService', () => {
|
||||||
chatCommand,
|
chatCommand,
|
||||||
clearCommand,
|
clearCommand,
|
||||||
compressCommand,
|
compressCommand,
|
||||||
|
corgiCommand,
|
||||||
docsCommand,
|
docsCommand,
|
||||||
editorCommand,
|
editorCommand,
|
||||||
extensionsCommand,
|
extensionsCommand,
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { SlashCommand } from '../ui/commands/types.js';
|
||||||
import { memoryCommand } from '../ui/commands/memoryCommand.js';
|
import { memoryCommand } from '../ui/commands/memoryCommand.js';
|
||||||
import { helpCommand } from '../ui/commands/helpCommand.js';
|
import { helpCommand } from '../ui/commands/helpCommand.js';
|
||||||
import { clearCommand } from '../ui/commands/clearCommand.js';
|
import { clearCommand } from '../ui/commands/clearCommand.js';
|
||||||
|
import { corgiCommand } from '../ui/commands/corgiCommand.js';
|
||||||
import { docsCommand } from '../ui/commands/docsCommand.js';
|
import { docsCommand } from '../ui/commands/docsCommand.js';
|
||||||
import { mcpCommand } from '../ui/commands/mcpCommand.js';
|
import { mcpCommand } from '../ui/commands/mcpCommand.js';
|
||||||
import { authCommand } from '../ui/commands/authCommand.js';
|
import { authCommand } from '../ui/commands/authCommand.js';
|
||||||
|
@ -36,6 +37,7 @@ const loadBuiltInCommands = async (
|
||||||
chatCommand,
|
chatCommand,
|
||||||
clearCommand,
|
clearCommand,
|
||||||
compressCommand,
|
compressCommand,
|
||||||
|
corgiCommand,
|
||||||
docsCommand,
|
docsCommand,
|
||||||
editorCommand,
|
editorCommand,
|
||||||
extensionsCommand,
|
extensionsCommand,
|
||||||
|
|
|
@ -47,6 +47,7 @@ export const createMockCommandContext = (
|
||||||
pendingItem: null,
|
pendingItem: null,
|
||||||
setPendingItem: vi.fn(),
|
setPendingItem: vi.fn(),
|
||||||
loadHistory: vi.fn(),
|
loadHistory: vi.fn(),
|
||||||
|
toggleCorgiMode: vi.fn(),
|
||||||
},
|
},
|
||||||
session: {
|
session: {
|
||||||
stats: {
|
stats: {
|
||||||
|
|
|
@ -379,7 +379,6 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||||
} = useSlashCommandProcessor(
|
} = useSlashCommandProcessor(
|
||||||
config,
|
config,
|
||||||
settings,
|
settings,
|
||||||
history,
|
|
||||||
addItem,
|
addItem,
|
||||||
clearItems,
|
clearItems,
|
||||||
loadHistory,
|
loadHistory,
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright 2025 Google LLC
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||||
|
import { corgiCommand } from './corgiCommand.js';
|
||||||
|
import { type CommandContext } from './types.js';
|
||||||
|
import { createMockCommandContext } from '../../test-utils/mockCommandContext.js';
|
||||||
|
|
||||||
|
describe('corgiCommand', () => {
|
||||||
|
let mockContext: CommandContext;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mockContext = createMockCommandContext();
|
||||||
|
vi.spyOn(mockContext.ui, 'toggleCorgiMode');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call the toggleCorgiMode function on the UI context', async () => {
|
||||||
|
if (!corgiCommand.action) {
|
||||||
|
throw new Error('The corgi command must have an action.');
|
||||||
|
}
|
||||||
|
|
||||||
|
await corgiCommand.action(mockContext, '');
|
||||||
|
|
||||||
|
expect(mockContext.ui.toggleCorgiMode).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have the correct name and description', () => {
|
||||||
|
expect(corgiCommand.name).toBe('corgi');
|
||||||
|
expect(corgiCommand.description).toBe('Toggles corgi mode.');
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,15 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright 2025 Google LLC
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { type SlashCommand } from './types.js';
|
||||||
|
|
||||||
|
export const corgiCommand: SlashCommand = {
|
||||||
|
name: 'corgi',
|
||||||
|
description: 'Toggles corgi mode.',
|
||||||
|
action: (context, _args) => {
|
||||||
|
context.ui.toggleCorgiMode();
|
||||||
|
},
|
||||||
|
};
|
|
@ -47,6 +47,8 @@ export interface CommandContext {
|
||||||
* @param history The array of history items to load.
|
* @param history The array of history items to load.
|
||||||
*/
|
*/
|
||||||
loadHistory: UseHistoryManagerReturn['loadHistory'];
|
loadHistory: UseHistoryManagerReturn['loadHistory'];
|
||||||
|
/** Toggles a special display mode. */
|
||||||
|
toggleCorgiMode: () => void;
|
||||||
};
|
};
|
||||||
// Session-specific data
|
// Session-specific data
|
||||||
session: {
|
session: {
|
||||||
|
@ -103,6 +105,7 @@ export type SlashCommandActionReturn =
|
||||||
| QuitActionReturn
|
| QuitActionReturn
|
||||||
| OpenDialogActionReturn
|
| OpenDialogActionReturn
|
||||||
| LoadHistoryActionReturn;
|
| LoadHistoryActionReturn;
|
||||||
|
|
||||||
// The standardized contract for any command in the system.
|
// The standardized contract for any command in the system.
|
||||||
export interface SlashCommand {
|
export interface SlashCommand {
|
||||||
name: string;
|
name: string;
|
||||||
|
|
|
@ -14,7 +14,7 @@ vi.mock('node:process', () => ({
|
||||||
cwd: vi.fn(() => '/mock/cwd'),
|
cwd: vi.fn(() => '/mock/cwd'),
|
||||||
get env() {
|
get env() {
|
||||||
return process.env;
|
return process.env;
|
||||||
}, // Use a getter to ensure current process.env is used
|
},
|
||||||
platform: 'test-platform',
|
platform: 'test-platform',
|
||||||
version: 'test-node-version',
|
version: 'test-node-version',
|
||||||
memoryUsage: vi.fn(() => ({
|
memoryUsage: vi.fn(() => ({
|
||||||
|
@ -25,12 +25,11 @@ vi.mock('node:process', () => ({
|
||||||
arrayBuffers: 123456,
|
arrayBuffers: 123456,
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
// Provide top-level exports as well for compatibility
|
|
||||||
exit: mockProcessExit,
|
exit: mockProcessExit,
|
||||||
cwd: vi.fn(() => '/mock/cwd'),
|
cwd: vi.fn(() => '/mock/cwd'),
|
||||||
get env() {
|
get env() {
|
||||||
return process.env;
|
return process.env;
|
||||||
}, // Use a getter here too
|
},
|
||||||
platform: 'test-platform',
|
platform: 'test-platform',
|
||||||
version: 'test-node-version',
|
version: 'test-node-version',
|
||||||
memoryUsage: vi.fn(() => ({
|
memoryUsage: vi.fn(() => ({
|
||||||
|
@ -106,20 +105,8 @@ describe('useSlashCommandProcessor', () => {
|
||||||
const mockUseSessionStats = useSessionStats as Mock;
|
const mockUseSessionStats = useSessionStats as Mock;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
// Reset all mocks to clear any previous state or calls.
|
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
|
|
||||||
// Default mock setup for CommandService for all the OLD tests.
|
|
||||||
// This makes them pass again by simulating the original behavior where
|
|
||||||
// the service is constructed but doesn't do much yet.
|
|
||||||
vi.mocked(CommandService).mockImplementation(
|
|
||||||
() =>
|
|
||||||
({
|
|
||||||
loadCommands: vi.fn().mockResolvedValue(undefined),
|
|
||||||
getCommands: vi.fn().mockReturnValue([]), // Return an empty array by default
|
|
||||||
}) as unknown as CommandService,
|
|
||||||
);
|
|
||||||
|
|
||||||
mockAddItem = vi.fn();
|
mockAddItem = vi.fn();
|
||||||
mockClearItems = vi.fn();
|
mockClearItems = vi.fn();
|
||||||
mockLoadHistory = vi.fn();
|
mockLoadHistory = vi.fn();
|
||||||
|
@ -177,7 +164,6 @@ describe('useSlashCommandProcessor', () => {
|
||||||
useSlashCommandProcessor(
|
useSlashCommandProcessor(
|
||||||
mockConfig,
|
mockConfig,
|
||||||
settings,
|
settings,
|
||||||
[],
|
|
||||||
mockAddItem,
|
mockAddItem,
|
||||||
mockClearItems,
|
mockClearItems,
|
||||||
mockLoadHistory,
|
mockLoadHistory,
|
||||||
|
@ -194,7 +180,7 @@ describe('useSlashCommandProcessor', () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('New command registry', () => {
|
describe('Command Processing', () => {
|
||||||
let ActualCommandService: typeof CommandService;
|
let ActualCommandService: typeof CommandService;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
@ -208,7 +194,7 @@ describe('useSlashCommandProcessor', () => {
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should execute a command from the new registry', async () => {
|
it('should execute a registered command', async () => {
|
||||||
const mockAction = vi.fn();
|
const mockAction = vi.fn();
|
||||||
const newCommand: SlashCommand = { name: 'test', action: mockAction };
|
const newCommand: SlashCommand = { name: 'test', action: mockAction };
|
||||||
const mockLoader = async () => [newCommand];
|
const mockLoader = async () => [newCommand];
|
||||||
|
@ -243,7 +229,7 @@ describe('useSlashCommandProcessor', () => {
|
||||||
expect(commandResult).toEqual({ type: 'handled' });
|
expect(commandResult).toEqual({ type: 'handled' });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return "schedule_tool" when a new command returns a tool action', async () => {
|
it('should return "schedule_tool" for a command returning a tool action', async () => {
|
||||||
const mockAction = vi.fn().mockResolvedValue({
|
const mockAction = vi.fn().mockResolvedValue({
|
||||||
type: 'tool',
|
type: 'tool',
|
||||||
toolName: 'my_tool',
|
toolName: 'my_tool',
|
||||||
|
@ -276,7 +262,7 @@ describe('useSlashCommandProcessor', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return "handled" when a new command returns a message action', async () => {
|
it('should return "handled" for a command returning a message action', async () => {
|
||||||
const mockAction = vi.fn().mockResolvedValue({
|
const mockAction = vi.fn().mockResolvedValue({
|
||||||
type: 'message',
|
type: 'message',
|
||||||
messageType: 'info',
|
messageType: 'info',
|
||||||
|
@ -312,7 +298,7 @@ describe('useSlashCommandProcessor', () => {
|
||||||
expect(commandResult).toEqual({ type: 'handled' });
|
expect(commandResult).toEqual({ type: 'handled' });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return "handled" when a new command returns a dialog action', async () => {
|
it('should return "handled" for a command returning a dialog action', async () => {
|
||||||
const mockAction = vi.fn().mockResolvedValue({
|
const mockAction = vi.fn().mockResolvedValue({
|
||||||
type: 'dialog',
|
type: 'dialog',
|
||||||
dialog: 'help',
|
dialog: 'help',
|
||||||
|
@ -341,7 +327,7 @@ describe('useSlashCommandProcessor', () => {
|
||||||
expect(commandResult).toEqual({ type: 'handled' });
|
expect(commandResult).toEqual({ type: 'handled' });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should open the auth dialog when a new command returns an auth dialog action', async () => {
|
it('should open the auth dialog for a command returning an auth dialog action', async () => {
|
||||||
const mockAction = vi.fn().mockResolvedValue({
|
const mockAction = vi.fn().mockResolvedValue({
|
||||||
type: 'dialog',
|
type: 'dialog',
|
||||||
dialog: 'auth',
|
dialog: 'auth',
|
||||||
|
@ -371,7 +357,7 @@ describe('useSlashCommandProcessor', () => {
|
||||||
expect(commandResult).toEqual({ type: 'handled' });
|
expect(commandResult).toEqual({ type: 'handled' });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should open the theme dialog when a new command returns a theme dialog action', async () => {
|
it('should open the theme dialog for a command returning a theme dialog action', async () => {
|
||||||
const mockAction = vi.fn().mockResolvedValue({
|
const mockAction = vi.fn().mockResolvedValue({
|
||||||
type: 'dialog',
|
type: 'dialog',
|
||||||
dialog: 'theme',
|
dialog: 'theme',
|
||||||
|
|
|
@ -19,37 +19,15 @@ import {
|
||||||
SlashCommandProcessorResult,
|
SlashCommandProcessorResult,
|
||||||
} from '../types.js';
|
} from '../types.js';
|
||||||
import { LoadedSettings } from '../../config/settings.js';
|
import { LoadedSettings } from '../../config/settings.js';
|
||||||
import {
|
import { type CommandContext, type SlashCommand } from '../commands/types.js';
|
||||||
type CommandContext,
|
|
||||||
type SlashCommandActionReturn,
|
|
||||||
type SlashCommand,
|
|
||||||
} from '../commands/types.js';
|
|
||||||
import { CommandService } from '../../services/CommandService.js';
|
import { CommandService } from '../../services/CommandService.js';
|
||||||
|
|
||||||
// This interface is for the old, inline command definitions.
|
|
||||||
// It will be removed once all commands are migrated to the new system.
|
|
||||||
export interface LegacySlashCommand {
|
|
||||||
name: string;
|
|
||||||
altName?: string;
|
|
||||||
description?: string;
|
|
||||||
completion?: () => Promise<string[]>;
|
|
||||||
action: (
|
|
||||||
mainCommand: string,
|
|
||||||
subCommand?: string,
|
|
||||||
args?: string,
|
|
||||||
) =>
|
|
||||||
| void
|
|
||||||
| SlashCommandActionReturn
|
|
||||||
| Promise<void | SlashCommandActionReturn>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook to define and process slash commands (e.g., /help, /clear).
|
* Hook to define and process slash commands (e.g., /help, /clear).
|
||||||
*/
|
*/
|
||||||
export const useSlashCommandProcessor = (
|
export const useSlashCommandProcessor = (
|
||||||
config: Config | null,
|
config: Config | null,
|
||||||
settings: LoadedSettings,
|
settings: LoadedSettings,
|
||||||
history: HistoryItem[],
|
|
||||||
addItem: UseHistoryManagerReturn['addItem'],
|
addItem: UseHistoryManagerReturn['addItem'],
|
||||||
clearItems: UseHistoryManagerReturn['clearItems'],
|
clearItems: UseHistoryManagerReturn['clearItems'],
|
||||||
loadHistory: UseHistoryManagerReturn['loadHistory'],
|
loadHistory: UseHistoryManagerReturn['loadHistory'],
|
||||||
|
@ -157,6 +135,7 @@ export const useSlashCommandProcessor = (
|
||||||
setDebugMessage: onDebugMessage,
|
setDebugMessage: onDebugMessage,
|
||||||
pendingItem: pendingCompressionItemRef.current,
|
pendingItem: pendingCompressionItemRef.current,
|
||||||
setPendingItem: setPendingCompressionItem,
|
setPendingItem: setPendingCompressionItem,
|
||||||
|
toggleCorgiMode,
|
||||||
},
|
},
|
||||||
session: {
|
session: {
|
||||||
stats: session.stats,
|
stats: session.stats,
|
||||||
|
@ -175,6 +154,7 @@ export const useSlashCommandProcessor = (
|
||||||
onDebugMessage,
|
onDebugMessage,
|
||||||
pendingCompressionItemRef,
|
pendingCompressionItemRef,
|
||||||
setPendingCompressionItem,
|
setPendingCompressionItem,
|
||||||
|
toggleCorgiMode,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -189,23 +169,6 @@ export const useSlashCommandProcessor = (
|
||||||
load();
|
load();
|
||||||
}, [commandService]);
|
}, [commandService]);
|
||||||
|
|
||||||
// Define legacy commands
|
|
||||||
// This list contains all commands that have NOT YET been migrated to the
|
|
||||||
// new system. As commands are migrated, they are removed from this list.
|
|
||||||
const legacyCommands: LegacySlashCommand[] = useMemo(() => {
|
|
||||||
const commands: LegacySlashCommand[] = [
|
|
||||||
// `/help` and `/clear` have been migrated and REMOVED from this list.
|
|
||||||
{
|
|
||||||
name: 'corgi',
|
|
||||||
action: (_mainCommand, _subCommand, _args) => {
|
|
||||||
toggleCorgiMode();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return commands;
|
|
||||||
}, [toggleCorgiMode]);
|
|
||||||
|
|
||||||
const handleSlashCommand = useCallback(
|
const handleSlashCommand = useCallback(
|
||||||
async (
|
async (
|
||||||
rawQuery: PartListUnion,
|
rawQuery: PartListUnion,
|
||||||
|
@ -230,8 +193,6 @@ export const useSlashCommandProcessor = (
|
||||||
const parts = trimmed.substring(1).trim().split(/\s+/);
|
const parts = trimmed.substring(1).trim().split(/\s+/);
|
||||||
const commandPath = parts.filter((p) => p); // The parts of the command, e.g., ['memory', 'add']
|
const commandPath = parts.filter((p) => p); // The parts of the command, e.g., ['memory', 'add']
|
||||||
|
|
||||||
// --- Start of New Tree Traversal Logic ---
|
|
||||||
|
|
||||||
let currentCommands = commands;
|
let currentCommands = commands;
|
||||||
let commandToExecute: SlashCommand | undefined;
|
let commandToExecute: SlashCommand | undefined;
|
||||||
let pathIndex = 0;
|
let pathIndex = 0;
|
||||||
|
@ -341,45 +302,6 @@ export const useSlashCommandProcessor = (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- End of New Tree Traversal Logic ---
|
|
||||||
|
|
||||||
// --- Legacy Fallback Logic (for commands not yet migrated) ---
|
|
||||||
|
|
||||||
const mainCommand = parts[0];
|
|
||||||
const subCommand = parts[1];
|
|
||||||
const legacyArgs = parts.slice(2).join(' ');
|
|
||||||
|
|
||||||
for (const cmd of legacyCommands) {
|
|
||||||
if (mainCommand === cmd.name || mainCommand === cmd.altName) {
|
|
||||||
const actionResult = await cmd.action(
|
|
||||||
mainCommand,
|
|
||||||
subCommand,
|
|
||||||
legacyArgs,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (actionResult?.type === 'tool') {
|
|
||||||
return {
|
|
||||||
type: 'schedule_tool',
|
|
||||||
toolName: actionResult.toolName,
|
|
||||||
toolArgs: actionResult.toolArgs,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (actionResult?.type === 'message') {
|
|
||||||
addItem(
|
|
||||||
{
|
|
||||||
type:
|
|
||||||
actionResult.messageType === 'error'
|
|
||||||
? MessageType.ERROR
|
|
||||||
: MessageType.INFO,
|
|
||||||
text: actionResult.content,
|
|
||||||
},
|
|
||||||
Date.now(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return { type: 'handled' };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addMessage({
|
addMessage({
|
||||||
type: MessageType.ERROR,
|
type: MessageType.ERROR,
|
||||||
content: `Unknown command: ${trimmed}`,
|
content: `Unknown command: ${trimmed}`,
|
||||||
|
@ -393,7 +315,6 @@ export const useSlashCommandProcessor = (
|
||||||
setShowHelp,
|
setShowHelp,
|
||||||
openAuthDialog,
|
openAuthDialog,
|
||||||
commands,
|
commands,
|
||||||
legacyCommands,
|
|
||||||
commandContext,
|
commandContext,
|
||||||
addMessage,
|
addMessage,
|
||||||
openThemeDialog,
|
openThemeDialog,
|
||||||
|
@ -403,38 +324,9 @@ export const useSlashCommandProcessor = (
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
const allCommands = useMemo(() => {
|
|
||||||
// Adapt legacy commands to the new SlashCommand interface
|
|
||||||
const adaptedLegacyCommands: SlashCommand[] = legacyCommands.map(
|
|
||||||
(legacyCmd) => ({
|
|
||||||
name: legacyCmd.name,
|
|
||||||
altName: legacyCmd.altName,
|
|
||||||
description: legacyCmd.description,
|
|
||||||
action: async (_context: CommandContext, args: string) => {
|
|
||||||
const parts = args.split(/\s+/);
|
|
||||||
const subCommand = parts[0] || undefined;
|
|
||||||
const restOfArgs = parts.slice(1).join(' ') || undefined;
|
|
||||||
|
|
||||||
return legacyCmd.action(legacyCmd.name, subCommand, restOfArgs);
|
|
||||||
},
|
|
||||||
completion: legacyCmd.completion
|
|
||||||
? async (_context: CommandContext, _partialArg: string) =>
|
|
||||||
legacyCmd.completion!()
|
|
||||||
: undefined,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
const newCommandNames = new Set(commands.map((c) => c.name));
|
|
||||||
const filteredAdaptedLegacy = adaptedLegacyCommands.filter(
|
|
||||||
(c) => !newCommandNames.has(c.name),
|
|
||||||
);
|
|
||||||
|
|
||||||
return [...commands, ...filteredAdaptedLegacy];
|
|
||||||
}, [commands, legacyCommands]);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
handleSlashCommand,
|
handleSlashCommand,
|
||||||
slashCommands: allCommands,
|
slashCommands: commands,
|
||||||
pendingHistoryItems,
|
pendingHistoryItems,
|
||||||
commandContext,
|
commandContext,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue