px2cc 2.2.3 → 2.2.4
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/package.json +1 -1
- package/src/PromptXActionProcessor.js +94 -27
package/bin.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "px2cc",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.4",
|
|
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
|
}
|
|
@@ -294,22 +353,30 @@ class LayerAssembler {
|
|
|
294
353
|
parts.push('');
|
|
295
354
|
|
|
296
355
|
// RoleLayer - 角色定义
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
parts.push(
|
|
356
|
+
// 如果有完整的 Markdown 内容(新格式),直接使用
|
|
357
|
+
if (roleInfo.sections.fullContent) {
|
|
358
|
+
parts.push('## 🎭 角色定义');
|
|
359
|
+
parts.push(this.cleanContent(roleInfo.sections.fullContent));
|
|
300
360
|
parts.push('');
|
|
301
|
-
}
|
|
361
|
+
} else {
|
|
362
|
+
// 旧格式:分别展示各个部分
|
|
363
|
+
if (roleInfo.sections.personality) {
|
|
364
|
+
parts.push('## 🎭 角色人格');
|
|
365
|
+
parts.push(this.cleanContent(roleInfo.sections.personality));
|
|
366
|
+
parts.push('');
|
|
367
|
+
}
|
|
302
368
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
369
|
+
if (roleInfo.sections.principle) {
|
|
370
|
+
parts.push('## 🔧 工作原则');
|
|
371
|
+
parts.push(this.cleanContent(roleInfo.sections.principle));
|
|
372
|
+
parts.push('');
|
|
373
|
+
}
|
|
308
374
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
375
|
+
if (roleInfo.sections.knowledge) {
|
|
376
|
+
parts.push('## 📚 专业知识');
|
|
377
|
+
parts.push(this.cleanContent(roleInfo.sections.knowledge));
|
|
378
|
+
parts.push('');
|
|
379
|
+
}
|
|
313
380
|
}
|
|
314
381
|
|
|
315
382
|
// 依赖资源
|