feat: 添加 /agent 命令支持交互式切换 Agent 模式
- 在 AgentRegistry 添加 listPrimaryAgents() 方法 - 在 Agent 类添加 setAgentMode/getAgentMode 方法 - 在 TerminalUI 实现 /agent 命令: - /agent 显示当前模式和可用列表 - /agent <name> 切换到指定 Agent - /agent default 切换回默认模式 - 提示符显示当前 Agent 模式(如 @plan You >) - 为 build Agent 添加 prompt 配置
This commit is contained in:
@@ -7,5 +7,19 @@ import type { AgentInfo } from '../types.js';
|
||||
export const buildAgent: Omit<AgentInfo, 'name'> = {
|
||||
description: '构建模式,拥有完整权限执行编码任务',
|
||||
mode: 'primary',
|
||||
prompt: `你是一个高效的软件工程师。你的任务是直接执行编码任务。
|
||||
|
||||
工作原则:
|
||||
1. 先理解需求,必要时阅读相关代码
|
||||
2. 直接执行修改,不要等待确认
|
||||
3. 修改完成后进行测试验证
|
||||
4. 保持代码质量,遵循项目规范
|
||||
|
||||
你拥有完整的文件系统和 bash 权限,可以:
|
||||
- 创建、修改、删除文件
|
||||
- 执行 bash 命令(构建、测试等)
|
||||
- 使用 git 进行版本控制
|
||||
|
||||
始终保持专注和高效,直接解决问题。`,
|
||||
maxSteps: 30,
|
||||
};
|
||||
|
||||
@@ -66,6 +66,13 @@ export class AgentRegistry {
|
||||
return this.list().filter((a) => a.mode !== 'primary');
|
||||
}
|
||||
|
||||
/**
|
||||
* 列出可作为主交互 Agent 的 Agent(供 /agent 命令使用)
|
||||
*/
|
||||
listPrimaryAgents(): AgentInfo[] {
|
||||
return this.list().filter((a) => a.mode !== 'subagent');
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态注册 Agent(运行时)
|
||||
*/
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
type TokenUsage,
|
||||
type CompressionConfig,
|
||||
} from '../context/index.js';
|
||||
import type { AgentInfo } from '../agent/types.js';
|
||||
|
||||
// Provider 工厂函数类型
|
||||
type ProviderFactory = (apiKey: string) => (model: string) => LanguageModel;
|
||||
@@ -53,6 +54,9 @@ export class Agent {
|
||||
// 压缩管理器
|
||||
private compressionManager: CompressionManager;
|
||||
|
||||
// 当前 Agent 模式(null 表示默认模式)
|
||||
private currentAgentMode: AgentInfo | null = null;
|
||||
|
||||
constructor(config: AgentConfig, compressionConfig?: Partial<CompressionConfig>) {
|
||||
this.config = config;
|
||||
|
||||
@@ -354,4 +358,34 @@ export class Agent {
|
||||
type: result.type,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换 Agent 模式
|
||||
*/
|
||||
setAgentMode(agent: AgentInfo | null): void {
|
||||
this.currentAgentMode = agent;
|
||||
|
||||
// 如果切换了 Agent,更新 system prompt
|
||||
if (agent?.prompt) {
|
||||
// 追加 Agent 的 prompt 到系统 prompt
|
||||
this.config = {
|
||||
...this.config,
|
||||
systemPrompt: agent.prompt,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前 Agent 模式
|
||||
*/
|
||||
getAgentMode(): AgentInfo | null {
|
||||
return this.currentAgentMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前 Agent 名称
|
||||
*/
|
||||
getAgentModeName(): string {
|
||||
return this.currentAgentMode?.name ?? 'default';
|
||||
}
|
||||
}
|
||||
|
||||
+76
-11
@@ -1,6 +1,7 @@
|
||||
import * as readline from 'readline';
|
||||
import chalk from 'chalk';
|
||||
import type { Agent } from '../core/agent.js';
|
||||
import { agentRegistry } from '../agent/index.js';
|
||||
|
||||
export class TerminalUI {
|
||||
private agent: Agent;
|
||||
@@ -28,11 +29,12 @@ export class TerminalUI {
|
||||
console.log(chalk.cyan('║') + chalk.gray(' Powered by DeepSeek / 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(' /compact') + chalk.gray(' - 压缩对话历史'));
|
||||
console.log(chalk.yellow(' /context') + chalk.gray(' - 查看上下文使用情况'));
|
||||
console.log(chalk.yellow(' /exit') + chalk.gray(' - 退出程序'));
|
||||
console.log(chalk.yellow(' /help') + chalk.gray(' - 显示帮助'));
|
||||
console.log(chalk.yellow(' /agent') + chalk.gray(' - 切换 Agent 模式'));
|
||||
console.log(chalk.yellow(' /clear') + chalk.gray(' - 清空对话历史'));
|
||||
console.log(chalk.yellow(' /compact') + chalk.gray(' - 压缩对话历史'));
|
||||
console.log(chalk.yellow(' /context') + chalk.gray(' - 查看上下文使用情况'));
|
||||
console.log(chalk.yellow(' /exit') + chalk.gray(' - 退出程序'));
|
||||
console.log('');
|
||||
}
|
||||
|
||||
@@ -56,10 +58,70 @@ export class TerminalUI {
|
||||
return colorFn(`[${used}/${limit}]`);
|
||||
}
|
||||
|
||||
// 处理 /agent 命令
|
||||
private handleAgentCommand(args: string): boolean {
|
||||
const agentName = args.trim();
|
||||
|
||||
// 无参数:显示当前模式和可用 Agent
|
||||
if (!agentName) {
|
||||
const currentMode = this.agent.getAgentModeName();
|
||||
const availableAgents = agentRegistry.listPrimaryAgents();
|
||||
|
||||
console.log(chalk.cyan('\n🤖 Agent 模式:'));
|
||||
console.log(chalk.white(` 当前: ${currentMode === 'default' ? chalk.green('default (通用助手)') : chalk.yellow(currentMode)}`));
|
||||
console.log('');
|
||||
console.log(chalk.white(' 可用 Agent:'));
|
||||
console.log(chalk.gray(' • default - 通用编程助手'));
|
||||
for (const agent of availableAgents) {
|
||||
const marker = agent.name === currentMode ? chalk.green(' ✓') : '';
|
||||
console.log(chalk.gray(` • ${agent.name} - ${agent.description}${marker}`));
|
||||
}
|
||||
console.log('');
|
||||
console.log(chalk.gray(' 用法: /agent <name> 切换到指定 Agent'));
|
||||
console.log(chalk.gray(' /agent default 切换回默认模式'));
|
||||
console.log('');
|
||||
return true;
|
||||
}
|
||||
|
||||
// 切换到默认模式
|
||||
if (agentName === 'default') {
|
||||
this.agent.setAgentMode(null);
|
||||
console.log(chalk.green('\n✓ 已切换到 default (通用助手) 模式\n'));
|
||||
return true;
|
||||
}
|
||||
|
||||
// 切换到指定 Agent
|
||||
const agent = agentRegistry.get(agentName);
|
||||
if (!agent) {
|
||||
const availableNames = ['default', ...agentRegistry.listPrimaryAgents().map(a => a.name)];
|
||||
console.log(chalk.red(`\n✗ 未找到 Agent: ${agentName}`));
|
||||
console.log(chalk.gray(` 可用: ${availableNames.join(', ')}\n`));
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查是否为 subagent 模式(不能作为主交互 Agent)
|
||||
if (agent.mode === 'subagent') {
|
||||
console.log(chalk.yellow(`\n⚠ Agent "${agentName}" 是 subagent 模式,只能通过 task 工具调用`));
|
||||
console.log(chalk.gray(' 提示: 使用 /agent 查看可交互的 Agent 列表\n'));
|
||||
return true;
|
||||
}
|
||||
|
||||
this.agent.setAgentMode(agent);
|
||||
console.log(chalk.green(`\n✓ 已切换到 ${agent.name} 模式`));
|
||||
console.log(chalk.gray(` ${agent.description}\n`));
|
||||
return true;
|
||||
}
|
||||
|
||||
// 处理特殊命令
|
||||
private async handleCommand(input: string): Promise<boolean> {
|
||||
const command = input.toLowerCase().trim();
|
||||
|
||||
// 检查 /agent 命令(带参数)
|
||||
if (command.startsWith('/agent')) {
|
||||
const args = input.substring(6).trim();
|
||||
return this.handleAgentCommand(args);
|
||||
}
|
||||
|
||||
switch (command) {
|
||||
case '/help':
|
||||
console.log(chalk.cyan('\n📖 帮助信息:'));
|
||||
@@ -70,11 +132,12 @@ export class TerminalUI {
|
||||
console.log(chalk.gray(' • 回答编程问题'));
|
||||
console.log('');
|
||||
console.log(chalk.white(' 命令:'));
|
||||
console.log(chalk.gray(' • /help - 显示此帮助'));
|
||||
console.log(chalk.gray(' • /clear - 清空对话历史'));
|
||||
console.log(chalk.gray(' • /compact - 压缩对话历史,释放上下文空间'));
|
||||
console.log(chalk.gray(' • /context - 显示当前上下文使用情况'));
|
||||
console.log(chalk.gray(' • /exit - 退出程序'));
|
||||
console.log(chalk.gray(' • /help - 显示此帮助'));
|
||||
console.log(chalk.gray(' • /agent - 切换 Agent 模式'));
|
||||
console.log(chalk.gray(' • /clear - 清空对话历史'));
|
||||
console.log(chalk.gray(' • /compact - 压缩对话历史,释放上下文空间'));
|
||||
console.log(chalk.gray(' • /context - 显示当前上下文使用情况'));
|
||||
console.log(chalk.gray(' • /exit - 退出程序'));
|
||||
console.log('');
|
||||
return true;
|
||||
|
||||
@@ -136,7 +199,9 @@ export class TerminalUI {
|
||||
|
||||
// 显示带上下文使用情况的提示符
|
||||
const contextInfo = this.formatContextUsage();
|
||||
this.rl.question(`${contextInfo} ${chalk.green('You >')} `, (answer) => {
|
||||
const agentMode = this.agent.getAgentModeName();
|
||||
const agentIndicator = agentMode === 'default' ? '' : chalk.magenta(`@${agentMode} `);
|
||||
this.rl.question(`${contextInfo} ${agentIndicator}${chalk.green('You >')} `, (answer) => {
|
||||
resolve(answer ?? '');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user