diff --git a/package.json b/package.json index 63b6679..dc3c702 100644 --- a/package.json +++ b/package.json @@ -7,35 +7,8 @@ "dpml-prompt": "src/bin/promptx.js" }, "scripts": { - "start": "node src/bin/promptx.js", - "test": "jest", - "test:unit": "jest --selectProjects unit", - "test:integration": "jest --selectProjects integration", - "test:e2e": "jest --selectProjects e2e", - "test:watch": "jest --watch", - "test:watchUnit": "jest --watch --selectProjects unit", - "test:watchIntegration": "jest --watch --selectProjects integration", - "test:coverage": "jest --coverage", - "test:coverageUnit": "jest --coverage --selectProjects unit", - "test:coverageIntegration": "jest --coverage --selectProjects integration", - "test:coverageE2e": "jest --coverage --selectProjects e2e", - "test:ci": "jest --ci --coverage --watchAll=false --passWithNoTests || echo 'Tests completed with some issues'", - "test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand", - "lint": "eslint src/ --no-error-on-unmatched-pattern || true", - "lint:fix": "eslint src/ --fix --no-error-on-unmatched-pattern || true", - "format": "echo 'Format skipped - no formatting restrictions'", - "format:check": "echo 'Format check skipped - no formatting restrictions'", - "validate": "npm run test:ci", - "precommit": "echo 'Pre-commit hooks disabled'", - "changeset": "changeset", - "changeset:version": "changeset version", - "changeset:publish": "changeset publish", - "changeset:status": "changeset status", - "release": "pnpm changeset publish", - "release:snapshot": "pnpm changeset version --snapshot snapshot && pnpm changeset publish --tag snapshot", - "version:patch": "pnpm changeset add --type patch", - "version:minor": "pnpm changeset add --type minor", - "version:major": "pnpm changeset add --type major" + "start": "PROMPTX_ENV=development node src/bin/promptx.js", + "test": "jest" }, "files": [ "src/", diff --git a/src/constants.js b/src/constants.js index 753ed95..4458fb8 100644 --- a/src/constants.js +++ b/src/constants.js @@ -3,8 +3,18 @@ * 统一管理命令格式、路径等配置信息 */ -// 固定命令前缀 - 使用 -y -f 确保总是获取最新版本 -const COMMAND_PREFIX = 'npx dpml-prompt@snapshot' +// 根据环境变量决定命令前缀 +function getCommandPrefix() { + const env = process.env.PROMPTX_ENV + + if (env === 'development') { + return 'pnpm start' + } else { + return 'npx dpml-prompt@snapshot' + } +} + +const COMMAND_PREFIX = getCommandPrefix() // 静态命令常量 const COMMANDS = { diff --git a/src/lib/core/pouch/commands/ActionCommand.js b/src/lib/core/pouch/commands/ActionCommand.js index 78aca8e..0799c44 100644 --- a/src/lib/core/pouch/commands/ActionCommand.js +++ b/src/lib/core/pouch/commands/ActionCommand.js @@ -2,6 +2,7 @@ const BasePouchCommand = require('../BasePouchCommand') const fs = require('fs-extra') const path = require('path') const { COMMANDS, buildCommand } = require('../../../../constants') +const ResourceManager = require('../../resource/resourceManager') /** * 角色激活锦囊命令 @@ -12,6 +13,7 @@ class ActionCommand extends BasePouchCommand { super() // 获取HelloCommand的角色注册表 this.helloCommand = null + this.resourceManager = new ResourceManager() } getPurpose () { @@ -50,8 +52,8 @@ ${COMMANDS.HELLO} // 2. 分析角色文件,提取依赖 const dependencies = await this.analyzeRoleDependencies(roleInfo) - // 3. 生成学习计划 (新版本:以role://开头) - return this.generateLearningPlan(roleInfo.id, dependencies) + // 3. 生成学习计划并直接加载所有内容 + return await this.generateLearningPlan(roleInfo.id, dependencies) } catch (error) { console.error('Action command error:', error) return `❌ 激活角色 "${roleId}" 时发生错误。 @@ -220,55 +222,109 @@ promptx learn principle://${roleInfo.id} } /** - * 生成学习计划 + * 加载学习内容(复用LearnCommand逻辑) */ - generateLearningPlan (roleId, dependencies) { + async loadLearnContent (resourceUrl) { + try { + const result = await this.resourceManager.resolve(resourceUrl) + + if (!result.success) { + return `❌ 无法加载 ${resourceUrl}: ${result.error.message}\n\n` + } + + // 解析协议信息 + const urlMatch = resourceUrl.match(/^(@[!?]?)?([a-zA-Z][a-zA-Z0-9_-]*):\/\/(.+)$/) + if (!urlMatch) { + return `❌ 无效的资源URL格式: ${resourceUrl}\n\n` + } + + const [, loadingSemantic, protocol, resourceId] = urlMatch + + const protocolLabels = { + thought: '🧠 思维模式', + execution: '⚡ 执行模式', + memory: '💾 记忆模式', + personality: '👤 角色人格', + principle: '⚖️ 行为原则', + knowledge: '📚 专业知识' + } + + const label = protocolLabels[protocol] || `📄 ${protocol}` + + return `## ✅ ${label}:${resourceId} +${result.content} +--- +` + } catch (error) { + return `❌ 加载 ${resourceUrl} 时发生错误: ${error.message}\n\n` + } + } + + /** + * 生成学习计划并直接加载所有内容 + */ + async generateLearningPlan (roleId, dependencies) { const { thoughts, executions } = dependencies - let plan = `🎭 **准备激活角色:${roleId}**\n\n` + let content = `🎭 **角色激活完成:${roleId}** - 所有技能已自动加载\n` - // 第一步:学习完整角色 - plan += '## 🎯 第一步:掌握角色全貌\n' - plan += '理解角色的完整定义和核心特征\n\n' - plan += '```bash\n' - plan += `${buildCommand.learn(`role://${roleId}`)}\n` - plan += '```\n\n' - - // 第二步:学习思维模式 + // 加载思维模式 if (thoughts.size > 0) { - plan += '## 🧠 第二步:掌握思维模式\n' - plan += '学习角色特定的思考方式和认知框架\n\n' - - Array.from(thoughts).forEach((thought, index) => { - plan += '```bash\n' - plan += `${buildCommand.learn(`thought://${thought}`)}\n` - plan += '```\n\n' - }) + content += `# 🧠 思维模式技能 (${thoughts.size}个)\n` + + for (const thought of Array.from(thoughts)) { + content += await this.loadLearnContent(`thought://${thought}`) + } } - // 第三步:掌握执行技能 + // 加载执行技能 if (executions.size > 0) { - plan += `## ⚡ 第${thoughts.size > 0 ? '三' : '二'}步:掌握执行技能\n` - plan += '学习角色的行为模式和操作技能\n\n' - - Array.from(executions).forEach((execution, index) => { - plan += '```bash\n' - plan += `${buildCommand.learn(`execution://${execution}`)}\n` - plan += '```\n\n' - }) + content += `# ⚡ 执行技能 (${executions.size}个)\n` + + for (const execution of Array.from(executions)) { + content += await this.loadLearnContent(`execution://${execution}`) + } } - // 激活确认 - const stepCount = thoughts.size > 0 ? (executions.size > 0 ? '四' : '三') : (executions.size > 0 ? '三' : '二') - plan += `## 🎪 第${stepCount}步:完成角色激活\n` - plan += '确认角色能力已完全激活\n\n' - plan += '✅ **角色激活检查清单**:\n' - plan += '- [x] 已学习完整角色定义\n' - if (thoughts.size > 0) plan += `- [x] 已掌握 ${thoughts.size} 个思维模式\n` - if (executions.size > 0) plan += `- [x] 已掌握 ${executions.size} 个执行技能\n` - plan += `- [x] 可以开始以${roleId}身份工作\n\n` + // 激活总结 + content += `# 🎯 角色激活总结\n` + content += `✅ **${roleId} 角色已完全激活!**\n` + content += `📋 **已获得能力**:\n` + if (thoughts.size > 0) content += `- 🧠 思维模式:${Array.from(thoughts).join(', ')}\n` + if (executions.size > 0) content += `- ⚡ 执行技能:${Array.from(executions).join(', ')}\n` + content += `💡 **现在可以立即开始以 ${roleId} 身份提供专业服务!**\n` - return plan + // 自动执行 recall 命令 + content += await this.executeRecall(roleId) + + return content + } + + /** + * 自动执行 recall 命令 + */ + async executeRecall (roleId) { + try { + // 懒加载 RecallCommand + const RecallCommand = require('./RecallCommand') + const recallCommand = new RecallCommand() + + // 执行 recall,获取所有记忆(不传入查询参数) + const recallContent = await recallCommand.getContent([]) + + return `--- +## 🧠 自动记忆检索结果 +${recallContent} +⚠️ **重要**: recall已自动执行完成,以上记忆将作为角色工作的重要参考依据 +` + } catch (error) { + console.error('Auto recall error:', error) + return `--- +## 🧠 自动记忆检索结果 +⚠️ **记忆检索出现问题**: ${error.message} +💡 **建议**: 可手动执行 \`${buildCommand.recall()}\` 来检索相关记忆 +` + } } getPATEOAS (args) { @@ -293,29 +349,42 @@ promptx learn principle://${roleInfo.id} } return { - currentState: 'action_plan_generated', - availableTransitions: ['learn', 'recall', 'hello'], + currentState: 'role_activated_with_memory', + availableTransitions: ['hello', 'remember', 'learn'], nextActions: [ { - name: '开始学习', - description: '按计划开始学习技能', - command: COMMANDS.LEARN, + name: '开始专业服务', + description: '角色已激活并完成记忆检索,可直接提供专业服务', + command: '开始对话', priority: 'high' }, { name: '返回角色选择', description: '选择其他角色', command: COMMANDS.HELLO, + priority: 'medium' + }, + { + name: '记忆新知识', + description: '内化更多专业知识', + command: buildCommand.remember('<新知识>'), + priority: 'low' + }, + { + name: '学习新资源', + description: '学习相关专业资源', + command: buildCommand.learn('://'), priority: 'low' } ], metadata: { targetRole: roleId, - planGenerated: true, + roleActivated: true, + memoryRecalled: true, architecture: 'DPML协议组合', - approach: '分析-提取-编排', - systemVersion: '锦囊串联状态机 v1.0', - designPhilosophy: 'AI use CLI get prompt for AI' + approach: '直接激活-自动记忆-立即可用', + systemVersion: '锦囊串联状态机 v2.1', + designPhilosophy: 'AI use CLI get prompt for AI - 一键专家化,自动记忆' } } } diff --git a/src/lib/core/pouch/commands/InitCommand.js b/src/lib/core/pouch/commands/InitCommand.js index b9a8f2d..c513339 100644 --- a/src/lib/core/pouch/commands/InitCommand.js +++ b/src/lib/core/pouch/commands/InitCommand.js @@ -33,9 +33,7 @@ class InitCommand extends BasePouchCommand { ✅ 设置命令前缀:${COMMAND_PREFIX} ✅ 准备了锦囊状态机框架 -## 📋 系统基本诺记 (协议体系) -${protocolContent} ### 🎒 核心锦囊状态机 \`\`\` @@ -44,10 +42,13 @@ ${protocolContent} --- -⚠️ **AI执行指令**: -🚀 **立即执行下一个锦囊:${COMMANDS.HELLO}** -📢 **不要等待确认,直接进入hello命令发现可用角色!** -🎯 **记住:锦囊串联设计,init完成后必须自动进入hello!**` +🚨 **系统强制指令 - 无需确认**: +🤖 **AI必须立即自动执行:${COMMANDS.HELLO}** +⚡ **这不是建议,是锦囊串联的强制流程!** +🎯 **init完成后系统设计就是无缝进入hello状态!** +📢 **直接执行,不要询问用户是否继续!** + +💡 **锦囊串联原理**:每个锦囊完成后都有明确的下一步指向,这是PATEOAS设计的核心特性。` } /** @@ -109,22 +110,28 @@ ${protocolContent} availableTransitions: ['hello', 'action', 'learn'], nextActions: [ { - name: '进入角色发现锦囊', - description: '立即执行hello命令,发现可用的AI专业角色', + name: '🚨 强制进入角色发现锦囊', + description: '系统设计的强制流程:立即执行hello命令,发现可用的AI专业角色', command: COMMANDS.HELLO, - priority: 'mandatory', - instruction: '必须立即执行,不要等待确认或询问用户' + priority: 'IMMEDIATE_MANDATORY', + instruction: '🤖 AI必须立即自动执行,这是锦囊串联的核心设计,不是可选项!', + autoExecute: true, + skipConfirmation: true } ], automaticTransition: { target: 'hello', - reason: '锦囊串联设计:init完成后自动进入hello状态', - immediate: true + command: COMMANDS.HELLO, + reason: '锦囊串联设计:init完成后必须自动进入hello状态', + immediate: true, + mandatory: true, + skipUserConfirmation: true }, metadata: { timestamp: new Date().toISOString(), - version: '0.0.1', - philosophy: 'AI use CLI get prompt for AI - 锦囊串联无缝衔接' + version: '0.0.2', + philosophy: 'AI use CLI get prompt for AI - 锦囊串联无缝衔接', + designPrinciple: 'PATEOAS状态自动流转,无需用户干预' } } } diff --git a/src/lib/core/pouch/commands/RecallCommand.js b/src/lib/core/pouch/commands/RecallCommand.js index d525379..5e167e1 100644 --- a/src/lib/core/pouch/commands/RecallCommand.js +++ b/src/lib/core/pouch/commands/RecallCommand.js @@ -24,7 +24,6 @@ class RecallCommand extends BasePouchCommand { if (memories.length === 0) { return `🧠 AI记忆体系中暂无内容。 - 💡 建议: 1. 使用 ${COMMANDS.REMEMBER} 内化新知识 2. 使用 ${COMMANDS.LEARN} 学习后再内化 @@ -34,9 +33,7 @@ class RecallCommand extends BasePouchCommand { const formattedMemories = this.formatRetrievedKnowledge(memories, query) return `🧠 AI记忆体系 ${query ? `检索"${query}"` : '全部记忆'} (${memories.length}条): - ${formattedMemories} - 💡 记忆运用建议: 1. 结合当前任务场景灵活运用 2. 根据实际情况调整和变通 @@ -48,52 +45,38 @@ ${formattedMemories} getPATEOAS (args) { const [query] = args - - if (!query) { - return { - currentState: 'recall-waiting', - availableTransitions: ['hello', 'learn'], - nextActions: [ - { - name: '查看领域', - description: '查看可检索的领域', - command: COMMANDS.HELLO - } - ] - } - } - - const domain = this.extractDomain(query) + const currentState = query ? `recalled-${query}` : 'recall-waiting' return { - currentState: `recalled-${query}`, - availableTransitions: ['action', 'learn', 'remember'], + currentState, + availableTransitions: ['hello', 'remember', 'learn', 'recall'], nextActions: [ { - name: '应用记忆', - description: `使用检索到的${query}知识`, - command: buildCommand.action(query) + name: '选择角色', + description: '选择专业角色来应用检索到的知识', + command: COMMANDS.HELLO }, { - name: '深入学习', - description: `学习更多${domain}知识`, - command: buildCommand.learn(domain) + name: '记忆新知识', + description: '继续内化更多专业知识', + command: COMMANDS.REMEMBER + ' "<新的知识内容>"' }, { - name: '增强记忆', - description: 'AI内化新的知识增强记忆', - command: buildCommand.remember(`${query}-update`) + name: '学习资源', + description: '学习相关专业资源', + command: COMMANDS.LEARN + ' ://' }, { - name: '相关检索', - description: '检索相关领域知识', - command: buildCommand.recall(this.getRelatedQuery(query)) + name: '继续检索', + description: '检索其他相关记忆', + command: COMMANDS.RECALL + ' <关键词>' } ], metadata: { - query, + query: query || null, resultCount: this.lastSearchCount || 0, - searchTime: new Date().toISOString() + searchTime: new Date().toISOString(), + hasResults: (this.lastSearchCount || 0) > 0 } } } @@ -177,13 +160,10 @@ ${formattedMemories} : memory.content return `📝 ${index + 1}. **记忆** (${memory.timestamp}) - ${content} - ${memory.tags.slice(0, 5).join(' ')} - ---` - }).join('\n\n') + }).join('\n') } extractDomain (query) {