Unify TUI slash commands and harden tool inventory responses

This commit is contained in:
William Valentin
2026-02-21 12:39:27 -08:00
parent e9cb1d7c1a
commit b09bfc8373
16 changed files with 505 additions and 21 deletions
+29 -1
View File
@@ -1,6 +1,6 @@
import { describe, it, expect, vi } from 'vitest';
import { createApproveCommand, createApprovalsCommand, createContextCommand, createCouncilCommand, createDenyCommand, createElevateCommand, createModelCommand, createQueueCommand, createResearchCommand, createSkillCommand, createStopCommand, createTransferCommand } from './index.js';
import { createApproveCommand, createApprovalsCommand, createContextCommand, createCouncilCommand, createDenyCommand, createElevateCommand, createModelCommand, createQueueCommand, createResearchCommand, createSkillCommand, createStopCommand, createToolsCommand, createTransferCommand } from './index.js';
describe('builtin /model command', () => {
it('passes through the full argument string', async () => {
@@ -198,6 +198,34 @@ describe('builtin /context command', () => {
});
});
describe('builtin /tools command', () => {
it('returns tools text from services', async () => {
const cmd = createToolsCommand();
const getTools = vi.fn(() => 'Available tools (2):\n- file.read\n- web.fetch');
const result = await cmd.execute([], {
channel: 'test',
senderId: 'user',
sessionId: 's1',
rawInput: '/tools',
services: { getTools },
});
expect(getTools).toHaveBeenCalledOnce();
expect(result).toEqual({ handled: true, text: 'Available tools (2):\n- file.read\n- web.fetch' });
});
it('returns not-available when service is missing', async () => {
const cmd = createToolsCommand();
const result = await cmd.execute([], {
channel: 'test',
senderId: 'user',
sessionId: 's1',
rawInput: '/tools',
services: {},
});
expect(result).toEqual({ handled: true, text: 'Tools command is not available in this session.' });
});
});
describe('builtin /transfer command', () => {
it('passes through the full target argument string', async () => {
const cmd = createTransferCommand();
+17
View File
@@ -48,6 +48,22 @@ export function createStatusCommand(): CommandDefinition {
};
}
export function createToolsCommand(): CommandDefinition {
return {
name: 'tools',
description: 'Show available tools in this session',
execute: async (_args, ctx) => {
if (!ctx.services?.getTools) {
return notAvailable('Tools command');
}
return {
handled: true,
text: await ctx.services.getTools(),
};
},
};
}
export function createUsageCommand(): CommandDefinition {
return {
name: 'usage',
@@ -343,6 +359,7 @@ export function createSkillCommand(): CommandDefinition {
export function registerBuiltinCommands(registry: CommandRegistry): void {
registry.register(createHelpCommand(registry));
registry.register(createStatusCommand());
registry.register(createToolsCommand());
registry.register(createUsageCommand());
registry.register(createContextCommand());
registry.register(createResearchCommand());
+1
View File
@@ -3,6 +3,7 @@ export type { CommandContext, CommandDefinition, CommandResult, CommandServices
export {
createHelpCommand,
createStatusCommand,
createToolsCommand,
createUsageCommand,
createContextCommand,
createModelCommand,
+1
View File
@@ -20,6 +20,7 @@ export interface CommandDefinition {
export interface CommandServices {
getStatus?: () => Promise<string> | string;
getTools?: () => Promise<string> | string;
getUsage?: () => Promise<string> | string;
getContext?: () => Promise<string> | string;
getModel?: () => Promise<string> | string;