feat(cli): TUI slash command parsing + local commands (P8-009) (#176)
All checks were successful
ci/woodpecker/push/ci Pipeline was successful

Co-authored-by: Jason Woltje <jason@diversecanvas.com>
Co-committed-by: Jason Woltje <jason@diversecanvas.com>
This commit was merged in pull request #176.
This commit is contained in:
2026-03-16 01:58:56 +00:00
committed by jason.woltje
parent 5a1991924c
commit f0741e045f
11 changed files with 328 additions and 7 deletions

View File

@@ -1,9 +1,14 @@
import React, { useState, useCallback } from 'react';
import { Box, Text } from 'ink';
import TextInput from 'ink-text-input';
import type { ParsedCommand } from '@mosaic/types';
import { parseSlashCommand, commandRegistry } from '../commands/index.js';
export interface InputBarProps {
onSubmit: (value: string) => void;
onSystemMessage?: (message: string) => void;
onLocalCommand?: (parsed: ParsedCommand) => void;
onGatewayCommand?: (parsed: ParsedCommand) => void;
isStreaming: boolean;
connected: boolean;
placeholder?: string;
@@ -11,6 +16,9 @@ export interface InputBarProps {
export function InputBar({
onSubmit,
onSystemMessage,
onLocalCommand,
onGatewayCommand,
isStreaming,
connected,
placeholder: placeholderOverride,
@@ -20,10 +28,39 @@ export function InputBar({
const handleSubmit = useCallback(
(value: string) => {
if (!value.trim() || isStreaming || !connected) return;
const trimmed = value.trim();
if (trimmed.startsWith('/')) {
const parsed = parseSlashCommand(trimmed);
if (!parsed) {
onSystemMessage?.(`Unknown command format: ${trimmed}`);
setInput('');
return;
}
const def = commandRegistry.find(parsed.command);
if (!def) {
onSystemMessage?.(
`Unknown command: /${parsed.command}. Type /help for available commands.`,
);
setInput('');
return;
}
if (def.execution === 'local') {
onLocalCommand?.(parsed);
setInput('');
return;
}
// Gateway-executed commands
onGatewayCommand?.(parsed);
setInput('');
return;
}
onSubmit(value);
setInput('');
},
[onSubmit, isStreaming, connected],
[onSubmit, onSystemMessage, onLocalCommand, onGatewayCommand, isStreaming, connected],
);
const placeholder =