211 lines
5.3 KiB
JavaScript
211 lines
5.3 KiB
JavaScript
const PouchStateMachine = require('./state/PouchStateMachine')
|
||
const PouchRegistry = require('./PouchRegistry')
|
||
const commands = require('./commands')
|
||
const { COMMANDS } = require('../../../constants')
|
||
const logger = require('../../utils/logger')
|
||
|
||
/**
|
||
* 锦囊CLI主入口
|
||
* 提供命令行接口和统一的执行入口
|
||
*/
|
||
class PouchCLI {
|
||
constructor () {
|
||
this.stateMachine = new PouchStateMachine()
|
||
this.registry = new PouchRegistry()
|
||
this.initialized = false
|
||
}
|
||
|
||
/**
|
||
* 初始化CLI
|
||
*/
|
||
async initialize () {
|
||
if (this.initialized) {
|
||
return
|
||
}
|
||
|
||
// 批量注册所有命令
|
||
this.registry.registerBatch({
|
||
init: commands.InitCommand,
|
||
welcome: commands.WelcomeCommand,
|
||
action: commands.ActionCommand,
|
||
learn: commands.LearnCommand,
|
||
recall: commands.RecallCommand,
|
||
remember: commands.RememberCommand,
|
||
dacp: commands.DACPCommand
|
||
})
|
||
|
||
// 将命令注册到状态机
|
||
for (const name of this.registry.list()) {
|
||
const command = this.registry.get(name)
|
||
this.stateMachine.registerCommand(name, command)
|
||
}
|
||
|
||
// 加载历史状态
|
||
await this.stateMachine.loadState()
|
||
|
||
this.initialized = true
|
||
}
|
||
|
||
/**
|
||
* 执行命令
|
||
* @param {string} commandName - 命令名称
|
||
* @param {Array} args - 命令参数
|
||
* @param {boolean} silent - 静默模式,不输出到console(用于MCP)
|
||
* @returns {Promise<PouchOutput>} 执行结果
|
||
*/
|
||
async execute (commandName, args = [], silent = false) {
|
||
// 确保已初始化
|
||
if (!this.initialized) {
|
||
await this.initialize()
|
||
}
|
||
|
||
// 验证命令是否存在
|
||
if (!this.registry.validate(commandName)) {
|
||
throw new Error(`未知命令: ${commandName}\n使用 '${COMMANDS.HELP}' 查看可用命令`)
|
||
}
|
||
|
||
try {
|
||
// 通过状态机执行命令
|
||
const result = await this.stateMachine.transition(commandName, args)
|
||
|
||
// 只在非静默模式下输出(避免干扰MCP协议)
|
||
if (!silent) {
|
||
// 如果结果有 toString 方法,打印人类可读格式
|
||
if (result && result.toString && typeof result.toString === 'function') {
|
||
logger.log(result.toString())
|
||
} else {
|
||
logger.log(JSON.stringify(result, null, 2))
|
||
}
|
||
}
|
||
|
||
return result
|
||
} catch (error) {
|
||
// 错误输出始终使用stderr,不干扰MCP协议
|
||
if (!silent) {
|
||
logger.error(`执行命令出错: ${error.message}`)
|
||
}
|
||
throw error
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取帮助信息
|
||
* @returns {string} 帮助文本
|
||
*/
|
||
getHelp () {
|
||
const commands = this.registry.getCommandDetails()
|
||
const currentState = this.stateMachine.getCurrentState()
|
||
const availableTransitions = this.stateMachine.getAvailableTransitions()
|
||
|
||
let help = `
|
||
🎯 PromptX 锦囊系统帮助
|
||
========================
|
||
|
||
当前状态: ${currentState}
|
||
可用转换: ${availableTransitions.join(', ')}
|
||
|
||
📋 可用命令:
|
||
`
|
||
|
||
for (const cmd of commands) {
|
||
help += `\n ${cmd.name.padEnd(12)} - ${cmd.purpose}`
|
||
}
|
||
|
||
help += `
|
||
|
||
💡 使用示例:
|
||
${COMMANDS.INIT} # 初始化工作环境
|
||
${COMMANDS.WELCOME} # 发现可用角色
|
||
${COMMANDS.ACTION} copywriter # 激活文案专家
|
||
${COMMANDS.LEARN} scrum # 学习敏捷知识
|
||
${COMMANDS.RECALL} frontend # 检索前端记忆
|
||
|
||
🔄 PATEOAS 导航:
|
||
每个命令执行后都会提供下一步的建议操作,
|
||
按照提示即可完成完整的工作流程。
|
||
|
||
📚 更多信息请访问: https://github.com/yourusername/promptx
|
||
`
|
||
|
||
return help
|
||
}
|
||
|
||
/**
|
||
* 获取当前状态信息
|
||
* @returns {StateContext} 状态上下文
|
||
*/
|
||
getStatus () {
|
||
return {
|
||
currentState: this.stateMachine.getCurrentState(),
|
||
availableCommands: this.registry.list(),
|
||
availableTransitions: this.stateMachine.getAvailableTransitions(),
|
||
context: this.stateMachine.context,
|
||
initialized: this.initialized
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 解析命令行输入
|
||
* @param {string} input - 用户输入
|
||
* @returns {Object} 解析结果
|
||
*/
|
||
parseCommand (input) {
|
||
const parts = input.trim().split(/\s+/)
|
||
const command = parts[0]
|
||
const args = parts.slice(1)
|
||
|
||
return {
|
||
command,
|
||
args
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 运行交互式CLI
|
||
*/
|
||
async runInteractive () {
|
||
logger.info('🎯 欢迎使用 PromptX 锦囊系统!')
|
||
logger.info('输入 "help" 查看帮助,"exit" 退出\n')
|
||
|
||
const readline = require('readline')
|
||
const rl = readline.createInterface({
|
||
input: process.stdin,
|
||
output: process.stdout,
|
||
prompt: 'promptx> '
|
||
})
|
||
|
||
rl.prompt()
|
||
|
||
rl.on('line', async (line) => {
|
||
const input = line.trim()
|
||
|
||
if (input === 'exit' || input === 'quit') {
|
||
logger.info('再见!')
|
||
rl.close()
|
||
return
|
||
}
|
||
|
||
if (input === 'help') {
|
||
logger.info(this.getHelp())
|
||
} else if (input === 'status') {
|
||
logger.info(JSON.stringify(this.getStatus(), null, 2))
|
||
} else if (input) {
|
||
const { command, args } = this.parseCommand(input)
|
||
try {
|
||
await this.execute(command, args)
|
||
} catch (error) {
|
||
logger.error(error.message)
|
||
}
|
||
}
|
||
|
||
rl.prompt()
|
||
})
|
||
|
||
rl.on('close', () => {
|
||
process.exit(0)
|
||
})
|
||
}
|
||
}
|
||
|
||
module.exports = PouchCLI
|