feat(tui): improve tool use display and register Gmail tools
Format tool names as human-readable labels (e.g. "Gmail: List") and show args as compact key-value pairs instead of raw JSON. Also register Gmail tools in the TUI when automation.gmail is enabled. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+41
-3
@@ -13,8 +13,38 @@ const toolColors = {
|
|||||||
cyan: '\x1b[36m',
|
cyan: '\x1b[36m',
|
||||||
green: '\x1b[32m',
|
green: '\x1b[32m',
|
||||||
red: '\x1b[31m',
|
red: '\x1b[31m',
|
||||||
|
bold: '\x1b[1m',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Format a tool name like "gmail.list" → "Gmail: List" */
|
||||||
|
function formatToolName(name: string): string {
|
||||||
|
const parts = name.split('.');
|
||||||
|
return parts.map((p, i) => {
|
||||||
|
const capitalized = p.charAt(0).toUpperCase() + p.slice(1);
|
||||||
|
return i === 0 && parts.length > 1 ? capitalized + ':' : capitalized;
|
||||||
|
}).join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Format tool args as a compact, readable summary instead of raw JSON. */
|
||||||
|
function formatToolArgs(args: unknown): string {
|
||||||
|
if (!args || typeof args !== 'object') return '';
|
||||||
|
const entries = Object.entries(args as Record<string, unknown>);
|
||||||
|
if (entries.length === 0) return '';
|
||||||
|
|
||||||
|
const parts = entries.map(([key, value]) => {
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
const display = value.length > 60 ? value.slice(0, 57) + '...' : value;
|
||||||
|
return `${key}: "${display}"`;
|
||||||
|
}
|
||||||
|
if (typeof value === 'number' || typeof value === 'boolean') {
|
||||||
|
return `${key}: ${value}`;
|
||||||
|
}
|
||||||
|
return `${key}: ${JSON.stringify(value)}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
return parts.join(', ');
|
||||||
|
}
|
||||||
|
|
||||||
function loadSystemPrompt(): string {
|
function loadSystemPrompt(): string {
|
||||||
const paths = [
|
const paths = [
|
||||||
resolve(process.cwd(), 'SOUL.md'),
|
resolve(process.cwd(), 'SOUL.md'),
|
||||||
@@ -48,7 +78,7 @@ export function registerTuiCommand(program: Command): void {
|
|||||||
setLogLevel(config.log_level);
|
setLogLevel(config.log_level);
|
||||||
const { MinimalTui, startFullscreenTui } = await import('../frontends/tui/index.js');
|
const { MinimalTui, startFullscreenTui } = await import('../frontends/tui/index.js');
|
||||||
const { NativeAgent } = await import('../backends/index.js');
|
const { NativeAgent } = await import('../backends/index.js');
|
||||||
const { ToolRegistry, ToolExecutor, allBuiltinTools, createWebSearchTools, createProcessTools, ProcessManager } = await import('../tools/index.js');
|
const { ToolRegistry, ToolExecutor, allBuiltinTools, createWebSearchTools, createProcessTools, ProcessManager, createGmailTools } = await import('../tools/index.js');
|
||||||
const { HookEngine } = await import('../hooks/index.js');
|
const { HookEngine } = await import('../hooks/index.js');
|
||||||
const { createModelRouter } = await import('../daemon/index.js');
|
const { createModelRouter } = await import('../daemon/index.js');
|
||||||
|
|
||||||
@@ -97,6 +127,13 @@ export function registerTuiCommand(program: Command): void {
|
|||||||
toolRegistry.register(tool);
|
toolRegistry.register(tool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register Gmail tools if configured
|
||||||
|
if (config.automation.gmail?.enabled) {
|
||||||
|
for (const tool of createGmailTools(config.automation.gmail)) {
|
||||||
|
toolRegistry.register(tool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const toolExecutor = new ToolExecutor(toolRegistry, hookEngine);
|
const toolExecutor = new ToolExecutor(toolRegistry, hookEngine);
|
||||||
|
|
||||||
const session = sessionManager.getSession('tui', 'local');
|
const session = sessionManager.getSession('tui', 'local');
|
||||||
@@ -109,8 +146,9 @@ export function registerTuiCommand(program: Command): void {
|
|||||||
toolExecutor,
|
toolExecutor,
|
||||||
onToolUse: (event) => {
|
onToolUse: (event) => {
|
||||||
if (event.type === 'start') {
|
if (event.type === 'start') {
|
||||||
const argsStr = event.args ? ` ${toolColors.dim}${JSON.stringify(event.args)}${toolColors.reset}` : '';
|
const label = formatToolName(event.tool);
|
||||||
process.stdout.write(`${toolColors.cyan}> ${event.tool}${toolColors.reset}${argsStr}\n`);
|
const argsStr = event.args ? ` ${toolColors.dim}(${formatToolArgs(event.args)})${toolColors.reset}` : '';
|
||||||
|
process.stdout.write(`${toolColors.cyan}> ${toolColors.bold}${label}${toolColors.reset}${argsStr}\n`);
|
||||||
} else if (event.type === 'end' && event.result) {
|
} else if (event.type === 'end' && event.result) {
|
||||||
const icon = event.result.success ? `${toolColors.green}done` : `${toolColors.red}error`;
|
const icon = event.result.success ? `${toolColors.green}done` : `${toolColors.red}error`;
|
||||||
const detail = event.result.success
|
const detail = event.result.success
|
||||||
|
|||||||
Reference in New Issue
Block a user