px2cc 2.2.3 → 2.2.5
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/bin.js +1 -1
- package/cli.js +15 -5
- package/package.json +1 -1
- package/src/PromptXActionProcessor.js +121 -30
package/bin.js
CHANGED
package/cli.js
CHANGED
|
@@ -186,11 +186,17 @@ async function showRoleMenu(systemRoles, userRoles, availableServers) {
|
|
|
186
186
|
},
|
|
187
187
|
{
|
|
188
188
|
name: `⚙️ Command - 通过 /${roleAnswer.selectedRole.role} 调用`,
|
|
189
|
-
value: 'commands',
|
|
189
|
+
value: 'commands',
|
|
190
190
|
short: 'Command'
|
|
191
191
|
}
|
|
192
192
|
]
|
|
193
193
|
},
|
|
194
|
+
{
|
|
195
|
+
type: 'confirm',
|
|
196
|
+
name: 'includeKnowledge',
|
|
197
|
+
message: '是否包含专业知识(Knowledge)?(知识内容可能较多,会增加文件大小)',
|
|
198
|
+
default: true
|
|
199
|
+
},
|
|
194
200
|
{
|
|
195
201
|
type: 'confirm',
|
|
196
202
|
name: 'customName',
|
|
@@ -246,6 +252,7 @@ async function showRoleMenu(systemRoles, userRoles, availableServers) {
|
|
|
246
252
|
return {
|
|
247
253
|
selectedRole: roleAnswer.selectedRole,
|
|
248
254
|
installType: typeAnswer.installType,
|
|
255
|
+
includeKnowledge: typeAnswer.includeKnowledge,
|
|
249
256
|
confirm: confirmAnswer.confirm,
|
|
250
257
|
customName: customName,
|
|
251
258
|
selectedTools: selectedTools
|
|
@@ -268,7 +275,7 @@ function checkDirectory() {
|
|
|
268
275
|
}
|
|
269
276
|
|
|
270
277
|
// 安装角色
|
|
271
|
-
async function installRole(selectedRole, installType, claudeDir, selectedTools, customName = '') {
|
|
278
|
+
async function installRole(selectedRole, installType, claudeDir, selectedTools, customName = '', includeKnowledge = true) {
|
|
272
279
|
const roleName = selectedRole.role;
|
|
273
280
|
const results = {};
|
|
274
281
|
|
|
@@ -276,7 +283,7 @@ async function installRole(selectedRole, installType, claudeDir, selectedTools,
|
|
|
276
283
|
// 使用新的PromptXActionProcessor执行完整的action流程
|
|
277
284
|
const processor = new PromptXActionProcessor();
|
|
278
285
|
const mode = installType === 'agents' ? 'subagent' : 'command';
|
|
279
|
-
const processedContent = await processor.processRole(roleName, mode);
|
|
286
|
+
const processedContent = await processor.processRole(roleName, mode, { includeKnowledge });
|
|
280
287
|
|
|
281
288
|
// 根据安装模式创建相应文件
|
|
282
289
|
const finalName = customName || (installType === 'agents' ? `${roleName}-agent` : roleName);
|
|
@@ -376,7 +383,7 @@ export async function main() {
|
|
|
376
383
|
console.log(`📊 发现 ${chalk.bold(systemRoles.length)} 个系统角色,${chalk.bold(userRoles.length)} 个用户角色\n`);
|
|
377
384
|
|
|
378
385
|
// 显示角色选择
|
|
379
|
-
const { selectedRole, installType, confirm, selectedTools, customName } = await showRoleMenu(systemRoles, userRoles, availableServers);
|
|
386
|
+
const { selectedRole, installType, includeKnowledge, confirm, selectedTools, customName } = await showRoleMenu(systemRoles, userRoles, availableServers);
|
|
380
387
|
|
|
381
388
|
if (!confirm) {
|
|
382
389
|
console.log(chalk.yellow('\n👋 安装已取消'));
|
|
@@ -387,9 +394,12 @@ export async function main() {
|
|
|
387
394
|
const claudeDir = checkDirectory();
|
|
388
395
|
|
|
389
396
|
console.log(chalk.blue(`\n🎭 开始安装角色: ${selectedRole.role} (${installType})`));
|
|
397
|
+
if (!includeKnowledge) {
|
|
398
|
+
console.log(chalk.gray(' 📚 不包含专业知识(Knowledge)'));
|
|
399
|
+
}
|
|
390
400
|
|
|
391
401
|
// 安装角色
|
|
392
|
-
const result = await installRole(selectedRole, installType, claudeDir, selectedTools, customName);
|
|
402
|
+
const result = await installRole(selectedRole, installType, claudeDir, selectedTools, customName, includeKnowledge);
|
|
393
403
|
|
|
394
404
|
console.log(chalk.green.bold('\n✅ 角色安装完成!'));
|
|
395
405
|
console.log(`\n📄 生成的文件:`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "px2cc",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.5",
|
|
4
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",
|
|
@@ -60,38 +60,80 @@ class RoleLoader {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
|
-
* 解析DPML
|
|
63
|
+
* 解析DPML角色文档(支持新旧两种格式)
|
|
64
64
|
* @param {string} content - 原始内容
|
|
65
65
|
* @returns {Object} 解析后的sections
|
|
66
66
|
*/
|
|
67
67
|
parseDPMLContent(content) {
|
|
68
68
|
const sections = {};
|
|
69
69
|
|
|
70
|
-
//
|
|
70
|
+
// 尝试旧格式:<role>...</role> 包裹的 XML 格式
|
|
71
71
|
const roleMatch = content.match(/<role>([\s\S]*?)<\/role>/);
|
|
72
72
|
if (roleMatch) {
|
|
73
73
|
const roleContent = roleMatch[1];
|
|
74
74
|
|
|
75
75
|
// 提取各个部分
|
|
76
|
-
sections.personality = this.
|
|
77
|
-
sections.principle = this.
|
|
78
|
-
sections.knowledge = this.
|
|
76
|
+
sections.personality = this.extractXMLSection(roleContent, 'personality');
|
|
77
|
+
sections.principle = this.extractXMLSection(roleContent, 'principle');
|
|
78
|
+
sections.knowledge = this.extractXMLSection(roleContent, 'knowledge');
|
|
79
|
+
|
|
80
|
+
// 如果成功提取到内容,返回
|
|
81
|
+
if (sections.personality || sections.principle || sections.knowledge) {
|
|
82
|
+
return sections;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 尝试新格式:<role id="..."> 开头的 Markdown 格式
|
|
87
|
+
const newRoleMatch = content.match(/<role\s+id="[^"]*">/);
|
|
88
|
+
if (newRoleMatch || !roleMatch) {
|
|
89
|
+
// 新格式:直接使用整个内容作为角色定义
|
|
90
|
+
// 移除 <role id="..."> 和 </role> 标签
|
|
91
|
+
let cleanContent = content
|
|
92
|
+
.replace(/<role\s+id="[^"]*">\s*/g, '')
|
|
93
|
+
.replace(/<\/role>\s*$/g, '')
|
|
94
|
+
.trim();
|
|
95
|
+
|
|
96
|
+
// 将整个 Markdown 内容作为角色定义
|
|
97
|
+
sections.fullContent = cleanContent;
|
|
98
|
+
|
|
99
|
+
// 尝试从 Markdown 中提取结构化内容
|
|
100
|
+
sections.personality = this.extractMarkdownSection(cleanContent, ['核心定位', '角色定位', '人格', '身份']);
|
|
101
|
+
sections.principle = this.extractMarkdownSection(cleanContent, ['核心能力', '工作原则', '原则', '方法论']);
|
|
102
|
+
sections.knowledge = this.extractMarkdownSection(cleanContent, ['专业知识', '知识体系', '领域知识']);
|
|
79
103
|
}
|
|
80
104
|
|
|
81
105
|
return sections;
|
|
82
106
|
}
|
|
83
107
|
|
|
84
108
|
/**
|
|
85
|
-
* 提取XML
|
|
109
|
+
* 提取XML标签内容(旧格式)
|
|
86
110
|
* @param {string} content - 内容
|
|
87
111
|
* @param {string} tagName - 标签名
|
|
88
112
|
* @returns {string|null} 提取的内容
|
|
89
113
|
*/
|
|
90
|
-
|
|
114
|
+
extractXMLSection(content, tagName) {
|
|
91
115
|
const regex = new RegExp(`<${tagName}>([\\s\\S]*?)<\\/${tagName}>`, 'i');
|
|
92
116
|
const match = content.match(regex);
|
|
93
117
|
return match ? match[1].trim() : null;
|
|
94
118
|
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* 从 Markdown 内容中提取指定标题下的内容(新格式)
|
|
122
|
+
* @param {string} content - Markdown 内容
|
|
123
|
+
* @param {Array<string>} headingKeywords - 可能的标题关键词
|
|
124
|
+
* @returns {string|null} 提取的内容
|
|
125
|
+
*/
|
|
126
|
+
extractMarkdownSection(content, headingKeywords) {
|
|
127
|
+
for (const keyword of headingKeywords) {
|
|
128
|
+
// 匹配 ## 或 ### 开头的标题
|
|
129
|
+
const regex = new RegExp(`^##\\s*${keyword}[^\\n]*\\n([\\s\\S]*?)(?=^##\\s|$)`, 'im');
|
|
130
|
+
const match = content.match(regex);
|
|
131
|
+
if (match) {
|
|
132
|
+
return match[1].trim();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
95
137
|
}
|
|
96
138
|
|
|
97
139
|
/**
|
|
@@ -116,12 +158,12 @@ class DependencyAnalyzer {
|
|
|
116
158
|
knowledges: []
|
|
117
159
|
};
|
|
118
160
|
|
|
119
|
-
if (!roleInfo.sections) {
|
|
161
|
+
if (!roleInfo.sections && !roleInfo.raw) {
|
|
120
162
|
return dependencies;
|
|
121
163
|
}
|
|
122
164
|
|
|
123
|
-
//
|
|
124
|
-
const allRefs = this.extractResourceReferences(roleInfo.sections);
|
|
165
|
+
// 收集所有资源引用(从 sections 和原始内容中提取)
|
|
166
|
+
const allRefs = this.extractResourceReferences(roleInfo.sections, roleInfo.raw);
|
|
125
167
|
|
|
126
168
|
console.log(chalk.gray(` 发现 ${allRefs.length} 个资源引用`));
|
|
127
169
|
|
|
@@ -157,10 +199,12 @@ class DependencyAnalyzer {
|
|
|
157
199
|
/**
|
|
158
200
|
* 提取资源引用
|
|
159
201
|
* @param {Object} sections - 角色sections
|
|
202
|
+
* @param {string} rawContent - 原始内容
|
|
160
203
|
* @returns {Array} 引用列表
|
|
161
204
|
*/
|
|
162
|
-
extractResourceReferences(sections) {
|
|
205
|
+
extractResourceReferences(sections, rawContent) {
|
|
163
206
|
const refs = [];
|
|
207
|
+
const seenRefs = new Set(); // 用于去重
|
|
164
208
|
|
|
165
209
|
const extractFromText = (text) => {
|
|
166
210
|
if (!text) return [];
|
|
@@ -172,10 +216,25 @@ class DependencyAnalyzer {
|
|
|
172
216
|
}));
|
|
173
217
|
};
|
|
174
218
|
|
|
219
|
+
const addRef = (ref) => {
|
|
220
|
+
const key = `${ref.protocol}://${ref.resource}`;
|
|
221
|
+
if (!seenRefs.has(key)) {
|
|
222
|
+
seenRefs.add(key);
|
|
223
|
+
refs.push(ref);
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
|
|
175
227
|
// 从所有sections中提取引用
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
228
|
+
if (sections) {
|
|
229
|
+
Object.values(sections).forEach(section => {
|
|
230
|
+
extractFromText(section).forEach(addRef);
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// 从原始内容中提取引用(确保不遗漏)
|
|
235
|
+
if (rawContent) {
|
|
236
|
+
extractFromText(rawContent).forEach(addRef);
|
|
237
|
+
}
|
|
179
238
|
|
|
180
239
|
return refs;
|
|
181
240
|
}
|
|
@@ -260,9 +319,12 @@ class LayerAssembler {
|
|
|
260
319
|
* @param {Object} dependencies - 依赖资源
|
|
261
320
|
* @param {Object} cognitionData - 认知数据
|
|
262
321
|
* @param {string} mode - 模式 (command|subagent)
|
|
322
|
+
* @param {Object} options - 选项
|
|
323
|
+
* @param {boolean} options.includeKnowledge - 是否包含知识内容
|
|
263
324
|
* @returns {string} 组装后的内容
|
|
264
325
|
*/
|
|
265
|
-
assembleContent(roleInfo, dependencies, cognitionData, mode = 'command') {
|
|
326
|
+
assembleContent(roleInfo, dependencies, cognitionData, mode = 'command', options = {}) {
|
|
327
|
+
const { includeKnowledge = true } = options;
|
|
266
328
|
const parts = [];
|
|
267
329
|
|
|
268
330
|
// 标题部分
|
|
@@ -294,22 +356,30 @@ class LayerAssembler {
|
|
|
294
356
|
parts.push('');
|
|
295
357
|
|
|
296
358
|
// RoleLayer - 角色定义
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
parts.push(
|
|
359
|
+
// 如果有完整的 Markdown 内容(新格式),直接使用
|
|
360
|
+
if (roleInfo.sections.fullContent) {
|
|
361
|
+
parts.push('## 🎭 角色定义');
|
|
362
|
+
parts.push(this.cleanContent(roleInfo.sections.fullContent));
|
|
300
363
|
parts.push('');
|
|
301
|
-
}
|
|
364
|
+
} else {
|
|
365
|
+
// 旧格式:分别展示各个部分
|
|
366
|
+
if (roleInfo.sections.personality) {
|
|
367
|
+
parts.push('## 🎭 角色人格');
|
|
368
|
+
parts.push(this.cleanContent(roleInfo.sections.personality));
|
|
369
|
+
parts.push('');
|
|
370
|
+
}
|
|
302
371
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
372
|
+
if (roleInfo.sections.principle) {
|
|
373
|
+
parts.push('## 🔧 工作原则');
|
|
374
|
+
parts.push(this.cleanContent(roleInfo.sections.principle));
|
|
375
|
+
parts.push('');
|
|
376
|
+
}
|
|
308
377
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
378
|
+
if (roleInfo.sections.knowledge) {
|
|
379
|
+
parts.push('## 📚 专业知识');
|
|
380
|
+
parts.push(this.cleanContent(roleInfo.sections.knowledge));
|
|
381
|
+
parts.push('');
|
|
382
|
+
}
|
|
313
383
|
}
|
|
314
384
|
|
|
315
385
|
// 依赖资源
|
|
@@ -331,6 +401,20 @@ class LayerAssembler {
|
|
|
331
401
|
});
|
|
332
402
|
}
|
|
333
403
|
|
|
404
|
+
if (includeKnowledge && dependencies.knowledges.length > 0) {
|
|
405
|
+
parts.push('## 📚 专业知识');
|
|
406
|
+
dependencies.knowledges.forEach(knowledge => {
|
|
407
|
+
parts.push(`### ${knowledge.id}`);
|
|
408
|
+
parts.push(this.cleanContent(knowledge.content));
|
|
409
|
+
parts.push('');
|
|
410
|
+
});
|
|
411
|
+
} else if (!includeKnowledge && dependencies.knowledges.length > 0) {
|
|
412
|
+
parts.push('## 📚 专业知识');
|
|
413
|
+
parts.push(`> ℹ️ 该角色包含 ${dependencies.knowledges.length} 个知识模块,已按用户选择跳过加载。`);
|
|
414
|
+
parts.push(`> 知识模块: ${dependencies.knowledges.map(k => k.id).join(', ')}`);
|
|
415
|
+
parts.push('');
|
|
416
|
+
}
|
|
417
|
+
|
|
334
418
|
// StateLayer - 状态信息
|
|
335
419
|
parts.push('---');
|
|
336
420
|
parts.push('');
|
|
@@ -402,11 +486,18 @@ export class PromptXActionProcessor {
|
|
|
402
486
|
* 执行完整的PromptX Action流程
|
|
403
487
|
* @param {string} roleId - 角色ID
|
|
404
488
|
* @param {string} mode - 模式 (command|subagent)
|
|
489
|
+
* @param {Object} options - 选项
|
|
490
|
+
* @param {boolean} options.includeKnowledge - 是否包含知识内容(默认true)
|
|
405
491
|
* @returns {string} 处理后的内容
|
|
406
492
|
*/
|
|
407
|
-
async processRole(roleId, mode = 'command') {
|
|
493
|
+
async processRole(roleId, mode = 'command', options = {}) {
|
|
494
|
+
const { includeKnowledge = true } = options;
|
|
495
|
+
|
|
408
496
|
try {
|
|
409
497
|
console.log(chalk.blue(`\n🎭 开始执行 ${roleId} 的 PromptX Action 流程 (${mode} 模式)`));
|
|
498
|
+
if (!includeKnowledge) {
|
|
499
|
+
console.log(chalk.gray(` 📚 跳过知识内容加载`));
|
|
500
|
+
}
|
|
410
501
|
|
|
411
502
|
// 1. 加载角色定义
|
|
412
503
|
const roleInfo = await this.roleLoader.loadRole(roleId);
|
|
@@ -418,7 +509,7 @@ export class PromptXActionProcessor {
|
|
|
418
509
|
const cognitionData = await this.cognitionLoader.checkNetworkExists(roleId);
|
|
419
510
|
|
|
420
511
|
// 4. 三层组装
|
|
421
|
-
const content = this.layerAssembler.assembleContent(roleInfo, dependencies, cognitionData, mode);
|
|
512
|
+
const content = this.layerAssembler.assembleContent(roleInfo, dependencies, cognitionData, mode, { includeKnowledge });
|
|
422
513
|
|
|
423
514
|
console.log(chalk.green(`✅ PromptX Action 流程完成!`));
|
|
424
515
|
|