修复多轮对话bug
This commit is contained in:
+68
-45
@@ -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,58 +83,70 @@ export class TerminalUI {
|
|||||||
async start(): Promise<void> {
|
async start(): Promise<void> {
|
||||||
this.showWelcome();
|
this.showWelcome();
|
||||||
|
|
||||||
while (true) {
|
while (!this.isClosed) {
|
||||||
const input = await this.prompt();
|
try {
|
||||||
|
const input = await this.prompt();
|
||||||
|
|
||||||
// 跳过空输入
|
// 跳过空输入
|
||||||
if (!input.trim()) {
|
if (!input.trim()) {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理命令
|
|
||||||
if (input.startsWith('/')) {
|
|
||||||
if (this.handleCommand(input)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 发送给 AI
|
// 处理命令
|
||||||
this.spinner.start(chalk.gray('思考中...'));
|
if (input.startsWith('/')) {
|
||||||
|
if (this.handleCommand(input)) {
|
||||||
try {
|
continue;
|
||||||
let isFirstChunk = true;
|
|
||||||
|
|
||||||
await this.agent.chat(input, (text) => {
|
|
||||||
if (isFirstChunk) {
|
|
||||||
this.spinner.stop();
|
|
||||||
process.stdout.write(chalk.blue('AI > '));
|
|
||||||
isFirstChunk = false;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 处理工具调用的输出
|
// 发送给 AI
|
||||||
if (text.startsWith('\n[调用工具:')) {
|
process.stdout.write(chalk.gray('思考中...'));
|
||||||
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');
|
try {
|
||||||
} catch (error) {
|
let isFirstChunk = true;
|
||||||
this.spinner.stop();
|
|
||||||
console.log(
|
await this.agent.chat(input, (text) => {
|
||||||
chalk.red(
|
if (isFirstChunk) {
|
||||||
`\n❌ 错误: ${error instanceof Error ? error.message : String(error)}\n`
|
// 清除 "思考中..." 并显示 AI 前缀
|
||||||
)
|
process.stdout.write('\r' + ' '.repeat(20) + '\r');
|
||||||
);
|
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) {
|
||||||
|
// 清除 "思考中..."
|
||||||
|
process.stdout.write('\r' + ' '.repeat(20) + '\r');
|
||||||
|
console.log(
|
||||||
|
chalk.red(
|
||||||
|
`❌ 错误: ${error instanceof Error ? error.message : String(error)}\n`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// readline 关闭,退出循环
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(chalk.cyan('\n👋 再见!\n'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关闭
|
// 关闭
|
||||||
close(): void {
|
close(): void {
|
||||||
this.rl.close();
|
if (!this.isClosed) {
|
||||||
|
this.isClosed = true;
|
||||||
|
this.rl.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user