修复多轮对话bug

This commit is contained in:
2025-12-10 16:35:04 +08:00
parent a53bf1d6e4
commit 9973e8ec06
+33 -10
View File
@@ -1,18 +1,23 @@
import * as readline from 'readline'; import * as readline from 'readline';
import chalk from 'chalk'; import chalk from 'chalk';
import ora from 'ora';
import type { Agent } from '../core/agent.js'; import type { Agent } from '../core/agent.js';
export class TerminalUI { export class TerminalUI {
private agent: Agent; private agent: Agent;
private rl: readline.Interface; private rl: readline.Interface;
private spinner = ora(); private isClosed = false;
constructor(agent: Agent) { constructor(agent: Agent) {
this.agent = agent; this.agent = agent;
this.rl = readline.createInterface({ this.rl = readline.createInterface({
input: process.stdin, input: process.stdin,
output: process.stdout, output: process.stdout,
terminal: true,
});
// 监听关闭事件
this.rl.on('close', () => {
this.isClosed = true;
}); });
} }
@@ -20,7 +25,7 @@ export class TerminalUI {
private showWelcome(): void { private showWelcome(): void {
console.log(chalk.cyan('\n╔════════════════════════════════════════╗')); console.log(chalk.cyan('\n╔════════════════════════════════════════╗'));
console.log(chalk.cyan('║') + chalk.bold.white(' 🤖 AI Terminal Assistant ') + chalk.cyan('║')); 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('║') + chalk.gray(' Powered by DeepSeek / Claude ') + chalk.cyan('║'));
console.log(chalk.cyan('╚════════════════════════════════════════╝\n')); console.log(chalk.cyan('╚════════════════════════════════════════╝\n'));
console.log(chalk.gray('输入你的问题,或使用以下命令:')); console.log(chalk.gray('输入你的问题,或使用以下命令:'));
console.log(chalk.yellow(' /help') + chalk.gray(' - 显示帮助')); console.log(chalk.yellow(' /help') + chalk.gray(' - 显示帮助'));
@@ -52,6 +57,7 @@ export class TerminalUI {
case '/exit': case '/exit':
case '/quit': case '/quit':
console.log(chalk.cyan('\n👋 再见!\n')); console.log(chalk.cyan('\n👋 再见!\n'));
this.close();
process.exit(0); process.exit(0);
default: default:
@@ -61,9 +67,14 @@ export class TerminalUI {
// 提问并获取用户输入 // 提问并获取用户输入
private prompt(): Promise<string> { private prompt(): Promise<string> {
return new Promise((resolve) => { return new Promise((resolve, reject) => {
if (this.isClosed) {
reject(new Error('readline closed'));
return;
}
this.rl.question(chalk.green('You > '), (answer) => { this.rl.question(chalk.green('You > '), (answer) => {
resolve(answer); resolve(answer ?? '');
}); });
}); });
} }
@@ -72,7 +83,8 @@ export class TerminalUI {
async start(): Promise<void> { async start(): Promise<void> {
this.showWelcome(); this.showWelcome();
while (true) { while (!this.isClosed) {
try {
const input = await this.prompt(); const input = await this.prompt();
// 跳过空输入 // 跳过空输入
@@ -88,14 +100,15 @@ export class TerminalUI {
} }
// 发送给 AI // 发送给 AI
this.spinner.start(chalk.gray('思考中...')); process.stdout.write(chalk.gray('思考中...'));
try { try {
let isFirstChunk = true; let isFirstChunk = true;
await this.agent.chat(input, (text) => { await this.agent.chat(input, (text) => {
if (isFirstChunk) { if (isFirstChunk) {
this.spinner.stop(); // 清除 "思考中..." 并显示 AI 前缀
process.stdout.write('\r' + ' '.repeat(20) + '\r');
process.stdout.write(chalk.blue('AI > ')); process.stdout.write(chalk.blue('AI > '));
isFirstChunk = false; isFirstChunk = false;
} }
@@ -112,18 +125,28 @@ export class TerminalUI {
console.log('\n'); console.log('\n');
} catch (error) { } catch (error) {
this.spinner.stop(); // 清除 "思考中..."
process.stdout.write('\r' + ' '.repeat(20) + '\r');
console.log( console.log(
chalk.red( chalk.red(
`\n❌ 错误: ${error instanceof Error ? error.message : String(error)}\n` `❌ 错误: ${error instanceof Error ? error.message : String(error)}\n`
) )
); );
} }
} catch {
// readline 关闭,退出循环
break;
} }
} }
console.log(chalk.cyan('\n👋 再见!\n'));
}
// 关闭 // 关闭
close(): void { close(): void {
if (!this.isClosed) {
this.isClosed = true;
this.rl.close(); this.rl.close();
} }
} }
}