px2cc 1.1.1 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.js +107 -83
- package/package.json +3 -2
- package/src/PromptXActionProcessor.js +473 -0
package/cli.js
CHANGED
|
@@ -7,12 +7,20 @@
|
|
|
7
7
|
|
|
8
8
|
import { resource } from '@promptx/core';
|
|
9
9
|
import { ClaudeCodeBuilder } from 'claude-code-builder';
|
|
10
|
+
import { PromptXActionProcessor } from './src/PromptXActionProcessor.js';
|
|
10
11
|
import inquirer from 'inquirer';
|
|
11
12
|
import chalk from 'chalk';
|
|
12
13
|
import path from 'path';
|
|
13
14
|
import fs from 'fs';
|
|
14
15
|
import { execSync } from 'child_process';
|
|
15
16
|
|
|
17
|
+
// 注意:原有的parsePromptXRole函数已被PromptXActionProcessor替代
|
|
18
|
+
// 新的处理器实现完整的PromptX Action流程,包括:
|
|
19
|
+
// 1. RoleLoader - 加载角色定义
|
|
20
|
+
// 2. DependencyAnalyzer - 分析资源依赖
|
|
21
|
+
// 3. CognitionLoader - 加载认知网络
|
|
22
|
+
// 4. LayerAssembler - 三层内容组装
|
|
23
|
+
|
|
16
24
|
// 发现MCP服务器
|
|
17
25
|
async function discoverMCPServers() {
|
|
18
26
|
const servers = {
|
|
@@ -21,10 +29,11 @@ async function discoverMCPServers() {
|
|
|
21
29
|
};
|
|
22
30
|
|
|
23
31
|
try {
|
|
24
|
-
|
|
32
|
+
console.log(chalk.gray(' 检查MCP服务器状态(可能需要一些时间)...'));
|
|
33
|
+
// 使用claude mcp list获取所有MCP服务器(增加超时时间)
|
|
25
34
|
const mcpOutput = execSync('claude mcp list', {
|
|
26
35
|
encoding: 'utf8',
|
|
27
|
-
timeout:
|
|
36
|
+
timeout: 30000 // 增加到30秒
|
|
28
37
|
});
|
|
29
38
|
|
|
30
39
|
// 解析输出,提取服务器信息
|
|
@@ -48,8 +57,14 @@ async function discoverMCPServers() {
|
|
|
48
57
|
console.log(chalk.green(`✅ 发现 ${servers.mcpServers.length} 个MCP服务器`));
|
|
49
58
|
|
|
50
59
|
} catch (error) {
|
|
51
|
-
|
|
52
|
-
|
|
60
|
+
if (error.code === 'ETIMEDOUT') {
|
|
61
|
+
console.error(chalk.red('❌ MCP服务器检查超时'));
|
|
62
|
+
console.error(chalk.gray(' 请检查网络连接或MCP服务器配置'));
|
|
63
|
+
} else {
|
|
64
|
+
console.error(chalk.red('❌ 无法获取MCP服务器列表'));
|
|
65
|
+
console.error(chalk.gray(` 原因: ${error.message}`));
|
|
66
|
+
}
|
|
67
|
+
throw error;
|
|
53
68
|
}
|
|
54
69
|
|
|
55
70
|
return servers;
|
|
@@ -57,62 +72,51 @@ async function discoverMCPServers() {
|
|
|
57
72
|
|
|
58
73
|
// 显示MCP服务器选择界面
|
|
59
74
|
async function selectMCPServers(roleName, availableServers) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
checked: true,
|
|
66
|
-
disabled: '(必需)'
|
|
67
|
-
}))
|
|
68
|
-
];
|
|
69
|
-
|
|
70
|
-
if (availableServers.mcpServers.length > 0) {
|
|
71
|
-
choices.push(
|
|
72
|
-
new inquirer.Separator(chalk.blue('🛠️ MCP服务器(选择后将获得该服务器的所有工具权限)'))
|
|
73
|
-
);
|
|
75
|
+
// 如果没有MCP服务器,直接返回undefined(继承所有工具)
|
|
76
|
+
if (availableServers.mcpServers.length === 0) {
|
|
77
|
+
console.log(chalk.gray(' 没有发现MCP服务器,将继承所有可用工具'));
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
74
80
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
81
|
+
// 只显示MCP服务器选择
|
|
82
|
+
const choices = [];
|
|
83
|
+
|
|
84
|
+
for (const server of availableServers.mcpServers) {
|
|
85
|
+
const statusIcon = server.connected ? '✓' : '✗';
|
|
86
|
+
const statusColor = server.connected ? chalk.green : chalk.red;
|
|
87
|
+
choices.push({
|
|
88
|
+
name: `${statusColor(statusIcon)} ${server.name} ${chalk.gray(`(${server.status})`)}`,
|
|
89
|
+
value: server.name,
|
|
90
|
+
checked: false, // 默认不选中任何MCP服务器
|
|
91
|
+
disabled: !server.connected ? '(未连接)' : false
|
|
92
|
+
});
|
|
85
93
|
}
|
|
86
94
|
|
|
95
|
+
console.log(chalk.blue('\n🔧 默认工具(自动包含):'), availableServers.defaultTools.join(', '));
|
|
96
|
+
|
|
87
97
|
const answer = await inquirer.prompt([{
|
|
88
98
|
type: 'checkbox',
|
|
89
|
-
name: '
|
|
90
|
-
message: `为 ${roleName}
|
|
91
|
-
choices: choices
|
|
92
|
-
validate: (input) => {
|
|
93
|
-
// 确保包含所有默认工具
|
|
94
|
-
const hasAllDefaults = availableServers.defaultTools.every(tool => input.includes(tool));
|
|
95
|
-
if (!hasAllDefaults) {
|
|
96
|
-
return '必须包含所有默认工具';
|
|
97
|
-
}
|
|
98
|
-
return true;
|
|
99
|
-
}
|
|
99
|
+
name: 'selectedServers',
|
|
100
|
+
message: `为 ${roleName} 选择额外的MCP服务器(可选):`,
|
|
101
|
+
choices: choices
|
|
100
102
|
}]);
|
|
101
103
|
|
|
102
|
-
//
|
|
103
|
-
const
|
|
104
|
-
const selectedServers = [];
|
|
104
|
+
// 处理选中的MCP服务器
|
|
105
|
+
const selectedMCPServers = answer.selectedServers || [];
|
|
105
106
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
} else {
|
|
110
|
-
selectedServers.push(item);
|
|
111
|
-
// 为选中的服务器添加通配符权限
|
|
112
|
-
selectedTools.push(`mcp__${item}__*`);
|
|
113
|
-
}
|
|
107
|
+
if (selectedMCPServers.length === 0) {
|
|
108
|
+
console.log(chalk.gray(' 将继承所有可用工具(Claude Code默认行为)'));
|
|
109
|
+
return undefined; // Claude Code会继承所有工具
|
|
114
110
|
}
|
|
115
|
-
|
|
111
|
+
|
|
112
|
+
// 如果选择了特定服务器,只包含默认工具+选中服务器的工具
|
|
113
|
+
const selectedTools = availableServers.defaultTools.slice();
|
|
114
|
+
for (const serverName of selectedMCPServers) {
|
|
115
|
+
// 添加该服务器的所有工具(使用通配符或具体工具名)
|
|
116
|
+
selectedTools.push(`mcp__${serverName}__*`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
console.log(chalk.blue(` 已选择 ${selectedMCPServers.length} 个MCP服务器: ${selectedMCPServers.join(', ')}`));
|
|
116
120
|
return selectedTools;
|
|
117
121
|
}
|
|
118
122
|
|
|
@@ -227,27 +231,31 @@ async function installRole(selectedRole, installType, claudeDir, manager, select
|
|
|
227
231
|
const results = {};
|
|
228
232
|
|
|
229
233
|
try {
|
|
230
|
-
//
|
|
231
|
-
|
|
232
|
-
const
|
|
234
|
+
// 使用新的PromptXActionProcessor执行完整的action流程
|
|
235
|
+
const processor = new PromptXActionProcessor();
|
|
236
|
+
const mode = installType === 'agents' ? 'subagent' : 'command';
|
|
237
|
+
const processedContent = await processor.processRole(roleName, mode);
|
|
233
238
|
|
|
234
|
-
|
|
235
|
-
throw new Error(`无法加载角色 ${roleName} 的内容`);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// 2. 根据安装目录创建相应文件
|
|
239
|
+
// 根据安装模式创建相应文件
|
|
239
240
|
if (installType === 'agents') {
|
|
240
|
-
console.log(chalk.cyan(`🔧 生成 ${roleName}
|
|
241
|
-
const
|
|
241
|
+
console.log(chalk.cyan(`🔧 生成 ${roleName} subagent文件...`));
|
|
242
|
+
const agentConfig = {
|
|
242
243
|
name: roleName,
|
|
243
|
-
description: `基于PromptX ${roleName}角色的专业AI
|
|
244
|
-
content:
|
|
245
|
-
tools: selectedTools,
|
|
244
|
+
description: `基于PromptX ${roleName}角色的专业AI助手 - 完整action实现`,
|
|
245
|
+
content: processedContent,
|
|
246
246
|
targetDir: claudeDir
|
|
247
|
-
}
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// 设置工具配置 - 如果用户没有选择特定工具,则继承所有可用工具
|
|
250
|
+
if (selectedTools) {
|
|
251
|
+
agentConfig.tools = selectedTools;
|
|
252
|
+
}
|
|
253
|
+
// 如果没有选择特定工具,Claude Code会自动继承所有可用工具
|
|
254
|
+
|
|
255
|
+
const subagentResult = await ClaudeCodeBuilder.createSubagent(agentConfig);
|
|
248
256
|
|
|
249
257
|
if (!subagentResult.success) {
|
|
250
|
-
throw new Error(`创建
|
|
258
|
+
throw new Error(`创建Subagent失败: ${subagentResult.error}`);
|
|
251
259
|
}
|
|
252
260
|
results.agentFile = `${roleName}.md`;
|
|
253
261
|
results.usage = `/subagent ${roleName}`;
|
|
@@ -255,20 +263,21 @@ async function installRole(selectedRole, installType, claudeDir, manager, select
|
|
|
255
263
|
|
|
256
264
|
if (installType === 'commands') {
|
|
257
265
|
console.log(chalk.cyan(`📋 生成 ${roleName} command文件...`));
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
${roleContent.content}
|
|
262
|
-
|
|
263
|
-
现在开始处理用户需求。`;
|
|
264
|
-
|
|
265
|
-
const commandResult = await ClaudeCodeBuilder.createCommand({
|
|
266
|
+
|
|
267
|
+
const commandConfig = {
|
|
266
268
|
name: roleName,
|
|
267
|
-
description: `基于PromptX ${roleName}
|
|
268
|
-
content:
|
|
269
|
-
allowedTools: selectedTools,
|
|
269
|
+
description: `基于PromptX ${roleName}角色的专业助手 - 完整action实现`,
|
|
270
|
+
content: processedContent,
|
|
270
271
|
targetDir: claudeDir
|
|
271
|
-
}
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
// 设置工具配置 - 如果用户没有选择特定工具,则继承所有可用工具
|
|
275
|
+
if (selectedTools) {
|
|
276
|
+
commandConfig.allowedTools = selectedTools;
|
|
277
|
+
}
|
|
278
|
+
// 如果没有选择特定工具,Claude Code会自动继承所有可用工具
|
|
279
|
+
|
|
280
|
+
const commandResult = await ClaudeCodeBuilder.createCommand(commandConfig);
|
|
272
281
|
|
|
273
282
|
if (!commandResult.success) {
|
|
274
283
|
throw new Error(`创建Command失败: ${commandResult.error}`);
|
|
@@ -291,9 +300,21 @@ async function main() {
|
|
|
291
300
|
try {
|
|
292
301
|
showWelcome();
|
|
293
302
|
|
|
294
|
-
//
|
|
295
|
-
|
|
296
|
-
|
|
303
|
+
// 检查是否跳过MCP发现(用于快速测试)
|
|
304
|
+
const skipMCP = process.argv.includes('--skip-mcp');
|
|
305
|
+
|
|
306
|
+
let availableServers;
|
|
307
|
+
if (skipMCP) {
|
|
308
|
+
console.log(chalk.yellow('⚠️ 跳过MCP发现(测试模式)'));
|
|
309
|
+
availableServers = {
|
|
310
|
+
defaultTools: ['Read', 'Write', 'Edit', 'Bash'],
|
|
311
|
+
mcpServers: []
|
|
312
|
+
};
|
|
313
|
+
} else {
|
|
314
|
+
// 发现MCP服务器
|
|
315
|
+
console.log(chalk.cyan('🔍 正在发现MCP服务器...\n'));
|
|
316
|
+
availableServers = await discoverMCPServers();
|
|
317
|
+
}
|
|
297
318
|
|
|
298
319
|
// 加载角色
|
|
299
320
|
console.log(chalk.cyan('🔍 正在从PromptX系统加载角色...\n'));
|
|
@@ -342,6 +363,9 @@ async function main() {
|
|
|
342
363
|
}
|
|
343
364
|
|
|
344
365
|
// 运行主程序
|
|
345
|
-
if (import.meta.url ===
|
|
346
|
-
main()
|
|
366
|
+
if (import.meta.url === new URL(process.argv[1], 'file:').href) {
|
|
367
|
+
main().catch(error => {
|
|
368
|
+
console.error(chalk.red('❌ 程序异常:'), error.message);
|
|
369
|
+
process.exit(1);
|
|
370
|
+
});
|
|
347
371
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "px2cc",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "CLI tool
|
|
3
|
+
"version": "2.0.1",
|
|
4
|
+
"description": "CLI tool that implements complete PromptX Action flow in Claude Code - role activation, dependency loading, cognition networks & memory systems",
|
|
5
5
|
"main": "cli.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"files": [
|
|
23
23
|
"cli.js",
|
|
24
24
|
"bin.js",
|
|
25
|
+
"src/",
|
|
25
26
|
"README.md",
|
|
26
27
|
"package.json"
|
|
27
28
|
],
|
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PromptXActionProcessor - 实现完整的PromptX Action流程
|
|
3
|
+
*
|
|
4
|
+
* 替代简单的parsePromptXRole函数,实现:
|
|
5
|
+
* 1. 角色加载器 (RoleLoader)
|
|
6
|
+
* 2. 依赖分析器 (DependencyAnalyzer)
|
|
7
|
+
* 3. 认知网络加载器 (CognitionLoader)
|
|
8
|
+
* 4. 三层组装器 (LayerAssembler)
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { resource } from '@promptx/core';
|
|
12
|
+
import fs from 'fs/promises';
|
|
13
|
+
import path from 'path';
|
|
14
|
+
import os from 'os';
|
|
15
|
+
import chalk from 'chalk';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 角色加载器 - 替代PromptX的ResourceManager
|
|
19
|
+
*/
|
|
20
|
+
class RoleLoader {
|
|
21
|
+
constructor(resourceManager) {
|
|
22
|
+
this.resourceManager = resourceManager;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 加载角色定义
|
|
27
|
+
* @param {string} roleId - 角色ID
|
|
28
|
+
* @returns {Object} 角色信息
|
|
29
|
+
*/
|
|
30
|
+
async loadRole(roleId) {
|
|
31
|
+
console.log(chalk.cyan(`📖 加载角色定义: ${roleId}`));
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
// 确保ResourceManager已初始化
|
|
35
|
+
if (!this.resourceManager.initialized) {
|
|
36
|
+
await this.resourceManager.initializeWithNewArchitecture();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// 加载角色资源
|
|
40
|
+
const result = await this.resourceManager.loadResource(`@role://${roleId}`);
|
|
41
|
+
|
|
42
|
+
if (!result || !result.success || !result.content) {
|
|
43
|
+
throw new Error(`无法加载角色 ${roleId} 的内容`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 解析DPML内容
|
|
47
|
+
const parsedContent = this.parseDPMLContent(result.content);
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
id: roleId,
|
|
51
|
+
raw: result.content,
|
|
52
|
+
sections: parsedContent,
|
|
53
|
+
metadata: result.metadata || {}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error(chalk.red(`❌ 角色加载失败: ${error.message}`));
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* 解析DPML角色文档
|
|
64
|
+
* @param {string} content - 原始内容
|
|
65
|
+
* @returns {Object} 解析后的sections
|
|
66
|
+
*/
|
|
67
|
+
parseDPMLContent(content) {
|
|
68
|
+
const sections = {};
|
|
69
|
+
|
|
70
|
+
// 解析 <role> 标签
|
|
71
|
+
const roleMatch = content.match(/<role>([\s\S]*?)<\/role>/);
|
|
72
|
+
if (roleMatch) {
|
|
73
|
+
const roleContent = roleMatch[1];
|
|
74
|
+
|
|
75
|
+
// 提取各个部分
|
|
76
|
+
sections.personality = this.extractSection(roleContent, 'personality');
|
|
77
|
+
sections.principle = this.extractSection(roleContent, 'principle');
|
|
78
|
+
sections.knowledge = this.extractSection(roleContent, 'knowledge');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return sections;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* 提取XML标签内容
|
|
86
|
+
* @param {string} content - 内容
|
|
87
|
+
* @param {string} tagName - 标签名
|
|
88
|
+
* @returns {string|null} 提取的内容
|
|
89
|
+
*/
|
|
90
|
+
extractSection(content, tagName) {
|
|
91
|
+
const regex = new RegExp(`<${tagName}>([\\s\\S]*?)<\\/${tagName}>`, 'i');
|
|
92
|
+
const match = content.match(regex);
|
|
93
|
+
return match ? match[1].trim() : null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* 依赖分析器 - 分析和加载资源依赖
|
|
99
|
+
*/
|
|
100
|
+
class DependencyAnalyzer {
|
|
101
|
+
constructor(resourceManager) {
|
|
102
|
+
this.resourceManager = resourceManager;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* 分析角色依赖
|
|
107
|
+
* @param {Object} roleInfo - 角色信息
|
|
108
|
+
* @returns {Object} 依赖资源
|
|
109
|
+
*/
|
|
110
|
+
async analyzeDependencies(roleInfo) {
|
|
111
|
+
console.log(chalk.cyan(`🔍 分析资源依赖...`));
|
|
112
|
+
|
|
113
|
+
const dependencies = {
|
|
114
|
+
thoughts: [],
|
|
115
|
+
executions: [],
|
|
116
|
+
knowledges: []
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
if (!roleInfo.sections) {
|
|
120
|
+
return dependencies;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// 收集所有资源引用
|
|
124
|
+
const allRefs = this.extractResourceReferences(roleInfo.sections);
|
|
125
|
+
|
|
126
|
+
console.log(chalk.gray(` 发现 ${allRefs.length} 个资源引用`));
|
|
127
|
+
|
|
128
|
+
// 并发加载所有依赖
|
|
129
|
+
const loadPromises = allRefs.map(ref => this.loadDependency(ref));
|
|
130
|
+
const results = await Promise.allSettled(loadPromises);
|
|
131
|
+
|
|
132
|
+
// 分类处理结果
|
|
133
|
+
results.forEach((result, index) => {
|
|
134
|
+
if (result.status === 'fulfilled' && result.value) {
|
|
135
|
+
const ref = allRefs[index];
|
|
136
|
+
const content = result.value;
|
|
137
|
+
|
|
138
|
+
switch (ref.protocol) {
|
|
139
|
+
case 'thought':
|
|
140
|
+
dependencies.thoughts.push({ id: ref.resource, content });
|
|
141
|
+
break;
|
|
142
|
+
case 'execution':
|
|
143
|
+
dependencies.executions.push({ id: ref.resource, content });
|
|
144
|
+
break;
|
|
145
|
+
case 'knowledge':
|
|
146
|
+
dependencies.knowledges.push({ id: ref.resource, content });
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
console.log(chalk.green(`✅ 依赖分析完成: thoughts=${dependencies.thoughts.length}, executions=${dependencies.executions.length}, knowledges=${dependencies.knowledges.length}`));
|
|
153
|
+
|
|
154
|
+
return dependencies;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* 提取资源引用
|
|
159
|
+
* @param {Object} sections - 角色sections
|
|
160
|
+
* @returns {Array} 引用列表
|
|
161
|
+
*/
|
|
162
|
+
extractResourceReferences(sections) {
|
|
163
|
+
const refs = [];
|
|
164
|
+
|
|
165
|
+
const extractFromText = (text) => {
|
|
166
|
+
if (!text) return [];
|
|
167
|
+
// 匹配 @protocol://resource 格式
|
|
168
|
+
const matches = text.matchAll(/@([^:]+):\/\/([^\\s\\>\\<]+)/g);
|
|
169
|
+
return Array.from(matches).map(match => ({
|
|
170
|
+
protocol: match[1],
|
|
171
|
+
resource: match[2]
|
|
172
|
+
}));
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
// 从所有sections中提取引用
|
|
176
|
+
Object.values(sections).forEach(section => {
|
|
177
|
+
refs.push(...extractFromText(section));
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
return refs;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* 加载单个依赖
|
|
185
|
+
* @param {Object} ref - 引用对象
|
|
186
|
+
* @returns {Promise<string>} 内容
|
|
187
|
+
*/
|
|
188
|
+
async loadDependency(ref) {
|
|
189
|
+
try {
|
|
190
|
+
const resourceUrl = `@${ref.protocol}://${ref.resource}`;
|
|
191
|
+
const result = await this.resourceManager.loadResource(resourceUrl);
|
|
192
|
+
|
|
193
|
+
if (result && result.success && result.content) {
|
|
194
|
+
return result.content;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
console.warn(chalk.yellow(`⚠️ 无法加载依赖: ${resourceUrl}`));
|
|
198
|
+
return null;
|
|
199
|
+
} catch (error) {
|
|
200
|
+
console.warn(chalk.yellow(`⚠️ 依赖加载失败: @${ref.protocol}://${ref.resource} - ${error.message}`));
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* 认知网络加载器 - 加载PromptX认知数据
|
|
208
|
+
*/
|
|
209
|
+
class CognitionLoader {
|
|
210
|
+
constructor() {
|
|
211
|
+
this.basePath = path.join(os.homedir(), '.promptx', 'cognition');
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* 检查认知网络状态
|
|
216
|
+
* @param {string} roleId - 角色ID
|
|
217
|
+
* @returns {Object} 认知网络状态信息
|
|
218
|
+
*/
|
|
219
|
+
async loadCognitionNetwork(roleId) {
|
|
220
|
+
console.log(chalk.cyan(`🧠 检查认知网络状态: ${roleId}`));
|
|
221
|
+
|
|
222
|
+
try {
|
|
223
|
+
const networkFilePath = path.join(this.basePath, roleId, 'network.json');
|
|
224
|
+
|
|
225
|
+
// 检查文件是否存在
|
|
226
|
+
try {
|
|
227
|
+
await fs.access(networkFilePath);
|
|
228
|
+
} catch (error) {
|
|
229
|
+
console.log(chalk.gray(` 未找到认知网络文件: ${roleId}`));
|
|
230
|
+
return {
|
|
231
|
+
hasNetwork: false,
|
|
232
|
+
networkPath: networkFilePath,
|
|
233
|
+
status: 'not_found'
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// 读取网络数据基本信息(不生成静态mindmap)
|
|
238
|
+
const networkData = JSON.parse(await fs.readFile(networkFilePath, 'utf8'));
|
|
239
|
+
const stats = this.getNetworkStats(networkData);
|
|
240
|
+
|
|
241
|
+
console.log(chalk.green(`✅ 认知网络检查完成: ${stats.nodeCount} 个节点, ${stats.connectionCount} 个连接`));
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
hasNetwork: true,
|
|
245
|
+
networkPath: networkFilePath,
|
|
246
|
+
status: 'active',
|
|
247
|
+
stats,
|
|
248
|
+
lastModified: networkData.timestamp || 'unknown'
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
} catch (error) {
|
|
252
|
+
console.warn(chalk.yellow(`⚠️ 认知网络检查失败: ${error.message}`));
|
|
253
|
+
return {
|
|
254
|
+
hasNetwork: false,
|
|
255
|
+
networkPath: null,
|
|
256
|
+
status: 'error',
|
|
257
|
+
error: error.message
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* 获取网络统计信息
|
|
264
|
+
* @param {Object} networkData - 网络数据
|
|
265
|
+
* @returns {Object} 统计信息
|
|
266
|
+
*/
|
|
267
|
+
getNetworkStats(networkData) {
|
|
268
|
+
const cues = networkData.cues || {};
|
|
269
|
+
const nodeCount = Object.keys(cues).length;
|
|
270
|
+
let connectionCount = 0;
|
|
271
|
+
|
|
272
|
+
// 统计连接数
|
|
273
|
+
Object.values(cues).forEach(cue => {
|
|
274
|
+
connectionCount += (cue.connections || []).length;
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// 找到最活跃的概念
|
|
278
|
+
const mostActiveCue = Object.entries(cues).reduce((max, [word, cue]) => {
|
|
279
|
+
const totalWeight = (cue.connections || []).reduce((sum, conn) => sum + (conn.weight || 0), 0);
|
|
280
|
+
return totalWeight > (max.totalWeight || 0) ? { word, totalWeight } : max;
|
|
281
|
+
}, { word: null, totalWeight: 0 });
|
|
282
|
+
|
|
283
|
+
return {
|
|
284
|
+
nodeCount,
|
|
285
|
+
connectionCount,
|
|
286
|
+
mostActiveCue: mostActiveCue.word,
|
|
287
|
+
version: networkData.version,
|
|
288
|
+
hasConnections: connectionCount > 0
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* 三层组装器 - 组装最终输出内容
|
|
295
|
+
*/
|
|
296
|
+
class LayerAssembler {
|
|
297
|
+
/**
|
|
298
|
+
* 组装完整内容
|
|
299
|
+
* @param {Object} roleInfo - 角色信息
|
|
300
|
+
* @param {Object} dependencies - 依赖资源
|
|
301
|
+
* @param {Object} cognitionData - 认知数据
|
|
302
|
+
* @param {string} mode - 模式 (command|subagent)
|
|
303
|
+
* @returns {string} 组装后的内容
|
|
304
|
+
*/
|
|
305
|
+
assembleContent(roleInfo, dependencies, cognitionData, mode = 'command') {
|
|
306
|
+
const parts = [];
|
|
307
|
+
|
|
308
|
+
// 标题部分
|
|
309
|
+
parts.push(`# 🧠 [Consciousness Prime] ${roleInfo.id}${mode === 'subagent' ? '专业助手' : '角色已激活'}`);
|
|
310
|
+
parts.push('');
|
|
311
|
+
|
|
312
|
+
// CognitionLayer - 动态认知网络状态
|
|
313
|
+
parts.push('## 💭 Hippocampus网络');
|
|
314
|
+
|
|
315
|
+
if (cognitionData.hasNetwork) {
|
|
316
|
+
parts.push(`**认知网络状态**: ${cognitionData.status === 'active' ? '🟢 激活' : '🔴 未激活'}`);
|
|
317
|
+
|
|
318
|
+
if (cognitionData.stats) {
|
|
319
|
+
parts.push(`**基础统计**: ${cognitionData.stats.nodeCount} 个概念节点,${cognitionData.stats.connectionCount} 个关联连接`);
|
|
320
|
+
|
|
321
|
+
if (cognitionData.stats.mostActiveCue) {
|
|
322
|
+
parts.push(`**核心概念**: ${cognitionData.stats.mostActiveCue}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
parts.push('');
|
|
327
|
+
parts.push('🔄 **动态认知网络**: 网络状态随着你的学习和记忆而实时进化');
|
|
328
|
+
parts.push('- 使用PromptX `recall` 工具查看当前激活的记忆网络');
|
|
329
|
+
parts.push('- 使用PromptX `remember` 工具将新经验编织到认知网络中');
|
|
330
|
+
parts.push('- 每次交互都会调整概念间的关联强度');
|
|
331
|
+
|
|
332
|
+
} else {
|
|
333
|
+
parts.push('🌱 **初始状态**: 认知网络尚未建立');
|
|
334
|
+
parts.push('- 开始使用PromptX工具与该角色互动');
|
|
335
|
+
parts.push('- 系统会自动建立和完善认知网络');
|
|
336
|
+
parts.push('- 随着经验积累,网络会变得越来越丰富');
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
parts.push('');
|
|
340
|
+
|
|
341
|
+
// RoleLayer - 角色定义
|
|
342
|
+
if (roleInfo.sections.personality) {
|
|
343
|
+
parts.push('## 🎭 角色人格');
|
|
344
|
+
parts.push(this.cleanContent(roleInfo.sections.personality));
|
|
345
|
+
parts.push('');
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if (roleInfo.sections.principle) {
|
|
349
|
+
parts.push('## 🔧 工作原则');
|
|
350
|
+
parts.push(this.cleanContent(roleInfo.sections.principle));
|
|
351
|
+
parts.push('');
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
if (roleInfo.sections.knowledge) {
|
|
355
|
+
parts.push('## 📚 专业知识');
|
|
356
|
+
parts.push(this.cleanContent(roleInfo.sections.knowledge));
|
|
357
|
+
parts.push('');
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// 依赖资源
|
|
361
|
+
if (dependencies.thoughts.length > 0) {
|
|
362
|
+
parts.push('## 💡 思维模式');
|
|
363
|
+
dependencies.thoughts.forEach(thought => {
|
|
364
|
+
parts.push(`### ${thought.id}`);
|
|
365
|
+
parts.push(this.cleanContent(thought.content));
|
|
366
|
+
parts.push('');
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (dependencies.executions.length > 0) {
|
|
371
|
+
parts.push('## ⚡ 执行技能');
|
|
372
|
+
dependencies.executions.forEach(execution => {
|
|
373
|
+
parts.push(`### ${execution.id}`);
|
|
374
|
+
parts.push(this.cleanContent(execution.content));
|
|
375
|
+
parts.push('');
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// StateLayer - 状态信息
|
|
380
|
+
parts.push('---');
|
|
381
|
+
parts.push('');
|
|
382
|
+
|
|
383
|
+
if (mode === 'command') {
|
|
384
|
+
parts.push(`🎉 ${roleInfo.id}角色激活完成!我现在以该角色身份为你服务。`);
|
|
385
|
+
} else {
|
|
386
|
+
parts.push('## 🤖 助手说明');
|
|
387
|
+
parts.push(`我是基于PromptX ${roleInfo.id}角色的专业AI助手。我会:`);
|
|
388
|
+
parts.push(`- 始终保持${roleInfo.id}的专业身份和思维模式`);
|
|
389
|
+
parts.push('- 利用完整的PromptX工具生态提供专业服务');
|
|
390
|
+
parts.push('- 在我们的对话过程中持续学习和记忆');
|
|
391
|
+
parts.push('');
|
|
392
|
+
parts.push('请告诉我你需要什么帮助?');
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
parts.push('');
|
|
396
|
+
parts.push('💡 **可用的PromptX工具生态**:');
|
|
397
|
+
parts.push('- 使用PromptX的 `recall` 工具激活相关记忆和经验');
|
|
398
|
+
parts.push('- 使用PromptX的 `remember` 工具保存新的学习成果');
|
|
399
|
+
parts.push('- 使用PromptX的 `learn` 工具学习新的资源和知识');
|
|
400
|
+
parts.push('- 使用PromptX的 `toolx` 工具执行专业工具');
|
|
401
|
+
parts.push('- 具体工具名称取决于你的MCP配置');
|
|
402
|
+
parts.push('');
|
|
403
|
+
|
|
404
|
+
if (mode === 'command') {
|
|
405
|
+
parts.push('现在开始处理用户需求。');
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
return parts.join('\n');
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* 清理内容格式
|
|
413
|
+
* @param {string} content - 原始内容
|
|
414
|
+
* @returns {string} 清理后的内容
|
|
415
|
+
*/
|
|
416
|
+
cleanContent(content) {
|
|
417
|
+
if (!content) return '';
|
|
418
|
+
|
|
419
|
+
return content
|
|
420
|
+
// 移除PromptX资源引用标签(但保留引用内容的展开结果)
|
|
421
|
+
.replace(/<reference[^>]*>/g, '')
|
|
422
|
+
.replace(/<\/reference>/g, '')
|
|
423
|
+
// 清理多余空行
|
|
424
|
+
.replace(/\n\s*\n\s*\n/g, '\n\n')
|
|
425
|
+
// 移除开头结尾空白
|
|
426
|
+
.trim();
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* PromptX Action处理器主类
|
|
432
|
+
*/
|
|
433
|
+
export class PromptXActionProcessor {
|
|
434
|
+
constructor() {
|
|
435
|
+
this.resourceManager = resource.getGlobalResourceManager();
|
|
436
|
+
this.roleLoader = new RoleLoader(this.resourceManager);
|
|
437
|
+
this.dependencyAnalyzer = new DependencyAnalyzer(this.resourceManager);
|
|
438
|
+
this.cognitionLoader = new CognitionLoader();
|
|
439
|
+
this.layerAssembler = new LayerAssembler();
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* 执行完整的PromptX Action流程
|
|
444
|
+
* @param {string} roleId - 角色ID
|
|
445
|
+
* @param {string} mode - 模式 (command|subagent)
|
|
446
|
+
* @returns {string} 处理后的内容
|
|
447
|
+
*/
|
|
448
|
+
async processRole(roleId, mode = 'command') {
|
|
449
|
+
try {
|
|
450
|
+
console.log(chalk.blue(`\n🎭 开始执行 ${roleId} 的 PromptX Action 流程 (${mode} 模式)`));
|
|
451
|
+
|
|
452
|
+
// 1. 加载角色定义
|
|
453
|
+
const roleInfo = await this.roleLoader.loadRole(roleId);
|
|
454
|
+
|
|
455
|
+
// 2. 分析依赖资源
|
|
456
|
+
const dependencies = await this.dependencyAnalyzer.analyzeDependencies(roleInfo);
|
|
457
|
+
|
|
458
|
+
// 3. 加载认知网络
|
|
459
|
+
const cognitionData = await this.cognitionLoader.loadCognitionNetwork(roleId);
|
|
460
|
+
|
|
461
|
+
// 4. 三层组装
|
|
462
|
+
const content = this.layerAssembler.assembleContent(roleInfo, dependencies, cognitionData, mode);
|
|
463
|
+
|
|
464
|
+
console.log(chalk.green(`✅ PromptX Action 流程完成!`));
|
|
465
|
+
|
|
466
|
+
return content;
|
|
467
|
+
|
|
468
|
+
} catch (error) {
|
|
469
|
+
console.error(chalk.red(`❌ PromptX Action 流程失败: ${error.message}`));
|
|
470
|
+
throw error;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|