Initial commit
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
import * as readline from 'readline';
|
||||
import chalk from 'chalk';
|
||||
import ora from 'ora';
|
||||
import type { Agent } from '../core/agent.js';
|
||||
|
||||
export class TerminalUI {
|
||||
private agent: Agent;
|
||||
private rl: readline.Interface;
|
||||
private spinner = ora();
|
||||
|
||||
constructor(agent: Agent) {
|
||||
this.agent = agent;
|
||||
this.rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
});
|
||||
}
|
||||
|
||||
// 显示欢迎信息
|
||||
private showWelcome(): void {
|
||||
console.log(chalk.cyan('\n╔════════════════════════════════════════╗'));
|
||||
console.log(chalk.cyan('║') + chalk.bold.white(' 🤖 AI Terminal Assistant ') + chalk.cyan('║'));
|
||||
console.log(chalk.cyan('║') + chalk.gray(' Powered by Claude ') + chalk.cyan('║'));
|
||||
console.log(chalk.cyan('╚════════════════════════════════════════╝\n'));
|
||||
console.log(chalk.gray('输入你的问题,或使用以下命令:'));
|
||||
console.log(chalk.yellow(' /help') + chalk.gray(' - 显示帮助'));
|
||||
console.log(chalk.yellow(' /clear') + chalk.gray(' - 清空对话历史'));
|
||||
console.log(chalk.yellow(' /exit') + chalk.gray(' - 退出程序'));
|
||||
console.log('');
|
||||
}
|
||||
|
||||
// 处理特殊命令
|
||||
private handleCommand(input: string): boolean {
|
||||
const command = input.toLowerCase().trim();
|
||||
|
||||
switch (command) {
|
||||
case '/help':
|
||||
console.log(chalk.cyan('\n📖 帮助信息:'));
|
||||
console.log(chalk.white(' 这是一个 AI 编程助手,可以帮你:'));
|
||||
console.log(chalk.gray(' • 读写文件'));
|
||||
console.log(chalk.gray(' • 执行 bash 命令'));
|
||||
console.log(chalk.gray(' • 搜索代码'));
|
||||
console.log(chalk.gray(' • 回答编程问题'));
|
||||
console.log('');
|
||||
return true;
|
||||
|
||||
case '/clear':
|
||||
this.agent.clearHistory();
|
||||
console.log(chalk.green('✓ 对话历史已清空\n'));
|
||||
return true;
|
||||
|
||||
case '/exit':
|
||||
case '/quit':
|
||||
console.log(chalk.cyan('\n👋 再见!\n'));
|
||||
process.exit(0);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 提问并获取用户输入
|
||||
private prompt(): Promise<string> {
|
||||
return new Promise((resolve) => {
|
||||
this.rl.question(chalk.green('You > '), (answer) => {
|
||||
resolve(answer);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 主循环
|
||||
async start(): Promise<void> {
|
||||
this.showWelcome();
|
||||
|
||||
while (true) {
|
||||
const input = await this.prompt();
|
||||
|
||||
// 跳过空输入
|
||||
if (!input.trim()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 处理命令
|
||||
if (input.startsWith('/')) {
|
||||
if (this.handleCommand(input)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// 发送给 AI
|
||||
this.spinner.start(chalk.gray('思考中...'));
|
||||
|
||||
try {
|
||||
let isFirstChunk = true;
|
||||
|
||||
await this.agent.chat(input, (text) => {
|
||||
if (isFirstChunk) {
|
||||
this.spinner.stop();
|
||||
process.stdout.write(chalk.blue('AI > '));
|
||||
isFirstChunk = false;
|
||||
}
|
||||
|
||||
// 处理工具调用的输出
|
||||
if (text.startsWith('\n[调用工具:')) {
|
||||
process.stdout.write(chalk.yellow(text));
|
||||
} else if (text.startsWith('[结果:') || text.startsWith('[错误:')) {
|
||||
process.stdout.write(chalk.gray(text));
|
||||
} else {
|
||||
process.stdout.write(text);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('\n');
|
||||
} catch (error) {
|
||||
this.spinner.stop();
|
||||
console.log(
|
||||
chalk.red(
|
||||
`\n❌ 错误: ${error instanceof Error ? error.message : String(error)}\n`
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭
|
||||
close(): void {
|
||||
this.rl.close();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user