yuangs 5.45.0 → 5.48.0
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/dist/commands/git/auto.js +63 -243
- package/dist/commands/git/auto.js.map +1 -1
- package/dist/commands/git/plan.d.ts +0 -3
- package/dist/commands/git/plan.js +55 -182
- package/dist/commands/git/plan.js.map +1 -1
- package/dist/core/kernel/ASTParser.d.ts +79 -5
- package/dist/core/kernel/ASTParser.js +312 -44
- package/dist/core/kernel/ASTParser.js.map +1 -1
- package/dist/core/kernel/FastScanner.js +5 -6
- package/dist/core/kernel/FastScanner.js.map +1 -1
- package/dist/core/workflows/AutoWorkflow.d.ts +21 -0
- package/dist/core/workflows/AutoWorkflow.js +200 -0
- package/dist/core/workflows/AutoWorkflow.js.map +1 -0
- package/dist/core/workflows/ConstraintEngine.d.ts +35 -0
- package/dist/core/workflows/ConstraintEngine.js +109 -0
- package/dist/core/workflows/ConstraintEngine.js.map +1 -0
- package/dist/core/workflows/GitWorkflowSession.d.ts +46 -0
- package/dist/core/workflows/GitWorkflowSession.js +221 -0
- package/dist/core/workflows/GitWorkflowSession.js.map +1 -0
- package/dist/core/workflows/PlanWorkflow.d.ts +14 -0
- package/dist/core/workflows/PlanWorkflow.js +214 -0
- package/dist/core/workflows/PlanWorkflow.js.map +1 -0
- package/dist/core/workflows/ReviewWorkflow.d.ts +17 -0
- package/dist/core/workflows/ReviewWorkflow.js +112 -0
- package/dist/core/workflows/ReviewWorkflow.js.map +1 -0
- package/dist/core/workflows/index.d.ts +6 -0
- package/dist/core/workflows/index.js +23 -0
- package/dist/core/workflows/index.js.map +1 -0
- package/dist/core/workflows/types.d.ts +159 -0
- package/dist/core/workflows/types.js +116 -0
- package/dist/core/workflows/types.js.map +1 -0
- package/package.json +1 -1
|
@@ -10,14 +10,11 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
10
10
|
const path_1 = __importDefault(require("path"));
|
|
11
11
|
const GitService_1 = require("../../core/git/GitService");
|
|
12
12
|
const llm_1 = require("../../agent/llm");
|
|
13
|
-
const
|
|
14
|
-
const
|
|
13
|
+
const workflows_1 = require("../../core/workflows");
|
|
14
|
+
const CapabilityLevel_1 = require("../../core/capability/CapabilityLevel");
|
|
15
15
|
const utils_1 = require("./utils");
|
|
16
16
|
const DEFAULT_PLAN_PROMPT = '分析项目现状并规划下一步开发任务';
|
|
17
17
|
const METADATA_PREFIX = '>';
|
|
18
|
-
/**
|
|
19
|
-
* 解析用户指令(优先级:命令行 > todo.md > 默认值)
|
|
20
|
-
*/
|
|
21
18
|
async function resolveUserPrompt(cliPrompt, todoPath) {
|
|
22
19
|
if (cliPrompt) {
|
|
23
20
|
return { prompt: cliPrompt, fromFile: false };
|
|
@@ -25,14 +22,11 @@ async function resolveUserPrompt(cliPrompt, todoPath) {
|
|
|
25
22
|
try {
|
|
26
23
|
await fs_1.default.promises.access(todoPath, fs_1.default.constants.F_OK);
|
|
27
24
|
const content = await fs_1.default.promises.readFile(todoPath, 'utf8');
|
|
28
|
-
// 过滤掉文件开头由 yuangs 生成的元数据行(连续的 > 开头的行)
|
|
29
25
|
const lines = content.split('\n');
|
|
30
26
|
let startIndex = 0;
|
|
31
|
-
// 跳过开头连续的元数据行
|
|
32
27
|
while (startIndex < lines.length && lines[startIndex].trim().startsWith(METADATA_PREFIX)) {
|
|
33
28
|
startIndex++;
|
|
34
29
|
}
|
|
35
|
-
// 跳过元数据后的空行
|
|
36
30
|
while (startIndex < lines.length && lines[startIndex].trim() === '') {
|
|
37
31
|
startIndex++;
|
|
38
32
|
}
|
|
@@ -48,9 +42,6 @@ async function resolveUserPrompt(cliPrompt, todoPath) {
|
|
|
48
42
|
}
|
|
49
43
|
return { prompt: DEFAULT_PLAN_PROMPT, fromFile: false };
|
|
50
44
|
}
|
|
51
|
-
/**
|
|
52
|
-
* 注册 git plan 命令
|
|
53
|
-
*/
|
|
54
45
|
function registerPlanCommand(gitCmd) {
|
|
55
46
|
gitCmd
|
|
56
47
|
.command('plan [prompt...]')
|
|
@@ -63,7 +54,6 @@ function registerPlanCommand(gitCmd) {
|
|
|
63
54
|
const maxRounds = parseInt(options.rounds) || 2;
|
|
64
55
|
const todoPath = path_1.default.join(process.cwd(), 'todo.md');
|
|
65
56
|
const { prompt: userPrompt, fromFile } = await resolveUserPrompt(cliPrompt, todoPath);
|
|
66
|
-
// 使用主 spinner 管理整体状态
|
|
67
57
|
const spinner = (0, ora_1.default)(fromFile ? '正在从 todo.md 读取并初始化分析规划...' : '正在初始化分析规划...').start();
|
|
68
58
|
try {
|
|
69
59
|
const gitService = new GitService_1.GitService();
|
|
@@ -71,186 +61,69 @@ function registerPlanCommand(gitCmd) {
|
|
|
71
61
|
spinner.fail('当前目录不是 Git 仓库');
|
|
72
62
|
return;
|
|
73
63
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
[用户需求]
|
|
90
|
-
${userPrompt}
|
|
91
|
-
`;
|
|
92
|
-
let currentPlan = ""; // 用于存储当前的方案草稿
|
|
93
|
-
let reviewComments = ""; // 用于存储审查意见
|
|
94
|
-
console.log(chalk_1.default.bold.cyan('\n🚀 启动双智能体协作引擎...\n'));
|
|
95
|
-
// --- 阶段 1: 架构师起草初稿 ---
|
|
96
|
-
spinner.start(`[架构师] ${ARCHITECT_MODEL} 正在起草初步方案...`);
|
|
97
|
-
const draftPrompt = [
|
|
98
|
-
{
|
|
99
|
-
role: 'system',
|
|
100
|
-
content: `你是一个资深软件架构师。请根据 Git 历史确保新功能与现有代码风格一致。
|
|
101
|
-
请基于用户需求输出一份初步的开发计划 (Draft Plan)。
|
|
102
|
-
包含:核心目标、修改文件列表、关键步骤。`
|
|
103
|
-
},
|
|
104
|
-
{ role: 'user', content: projectContext }
|
|
105
|
-
];
|
|
106
|
-
const draftRes = await (0, llm_1.runLLM)({
|
|
107
|
-
prompt: { messages: draftPrompt },
|
|
108
|
-
model: ARCHITECT_MODEL,
|
|
109
|
-
stream: false,
|
|
110
|
-
bypassRouter: true
|
|
64
|
+
spinner.succeed('Git 仓库验证通过');
|
|
65
|
+
const workflowConfig = {
|
|
66
|
+
sessionId: Date.now().toString(36) + Math.random().toString(36).substring(2, 11),
|
|
67
|
+
model: options.model || 'Assistant',
|
|
68
|
+
capability: CapabilityLevel_1.CapabilityLevel.SEMANTIC
|
|
69
|
+
};
|
|
70
|
+
const session = new workflows_1.GitWorkflowSession(workflowConfig);
|
|
71
|
+
const planWorkflow = new workflows_1.PlanWorkflow(gitService);
|
|
72
|
+
console.log(chalk_1.default.bold.cyan('\n🚀 启动工作流会话...\n'));
|
|
73
|
+
spinner.start('[工作流] 正在执行计划阶段...');
|
|
74
|
+
const result = await session.runPlan(async (input) => planWorkflow.run(input, session.getConfig()), {
|
|
75
|
+
userPrompt,
|
|
76
|
+
maxRounds,
|
|
77
|
+
architectModel: options.model,
|
|
78
|
+
reviewerModel: options.reviewerModel
|
|
111
79
|
});
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
role: 'system',
|
|
123
|
-
content: `你是一个严格的代码审查员和产品经理。
|
|
124
|
-
你的任务是找出架构师方案中的漏洞、遗漏、安全风险或逻辑错误。
|
|
125
|
-
请简明扼要地列出修改建议。不要重写计划,只给建议。`
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
role: 'user',
|
|
129
|
-
content: `
|
|
130
|
-
${projectContext}
|
|
131
|
-
|
|
132
|
-
[待评审的方案]
|
|
133
|
-
${currentPlan}
|
|
134
|
-
`
|
|
135
|
-
}
|
|
80
|
+
if (result.success && result.data) {
|
|
81
|
+
spinner.succeed('计划执行成功');
|
|
82
|
+
const filePath = path_1.default.join(process.cwd(), 'todo.md');
|
|
83
|
+
const metadataLines = [
|
|
84
|
+
`> 📅 Generated by Yuangs Git Plan at ${new Date().toLocaleString()}`,
|
|
85
|
+
`> 🎯 Context: ${userPrompt}`,
|
|
86
|
+
`> 🔧 Capability Level: ${(0, utils_1.getCapabilityLevelDisplay)(result.data.capability.minCapability)}`,
|
|
87
|
+
`> ⚙️ Estimated Time: ${result.data.estimatedTime}ms`,
|
|
88
|
+
`> 📊 Estimated Tokens: ${result.data.estimatedTokens}`,
|
|
89
|
+
'',
|
|
136
90
|
];
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
// Step B: 架构师 (Assistant) 修正
|
|
147
|
-
spinner.start(`[架构师] ${ARCHITECT_MODEL} 正在根据意见修订方案...`);
|
|
148
|
-
const refinePrompt = [
|
|
149
|
-
{
|
|
150
|
-
role: 'system',
|
|
151
|
-
content: `你是一个资深软件架构师。请根据审查员的意见优化你的开发计划。`
|
|
152
|
-
},
|
|
153
|
-
{
|
|
154
|
-
role: 'user',
|
|
155
|
-
content: `
|
|
156
|
-
这是你之前的方案:
|
|
157
|
-
${currentPlan}
|
|
158
|
-
|
|
159
|
-
审查员给出的意见:
|
|
160
|
-
${reviewComments}
|
|
161
|
-
|
|
162
|
-
请输出修正后的完整方案。`
|
|
163
|
-
}
|
|
164
|
-
];
|
|
165
|
-
const refineRes = await (0, llm_1.runLLM)({
|
|
166
|
-
prompt: { messages: refinePrompt },
|
|
167
|
-
model: ARCHITECT_MODEL,
|
|
168
|
-
stream: false,
|
|
169
|
-
bypassRouter: true
|
|
170
|
-
});
|
|
171
|
-
currentPlan = refineRes.rawText;
|
|
172
|
-
spinner.succeed(chalk_1.default.blue(`[架构师] 方案已修订`));
|
|
91
|
+
const fileOutput = metadataLines.join('\n') + result.data.todoMarkdown;
|
|
92
|
+
fs_1.default.writeFileSync(filePath, fileOutput);
|
|
93
|
+
console.log('');
|
|
94
|
+
console.log(chalk_1.default.green(`✅ 规划完成!文件已生成: ${chalk_1.default.bold('todo.md')}`));
|
|
95
|
+
console.log(chalk_1.default.gray(`👉 你可以使用 'code todo.md' 打开查看`));
|
|
96
|
+
console.log('');
|
|
97
|
+
console.log(chalk_1.default.bold.cyan('📊 会话摘要:'));
|
|
98
|
+
console.log(chalk_1.default.gray(session.getSummary()));
|
|
99
|
+
session.complete();
|
|
173
100
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
if (estimatedTotalLines === 0 && allFiles.length > 0) {
|
|
188
|
-
estimatedTotalLines = allFiles.length * constants_1.DIFF_ESTIMATION.LINES_PER_FILE_DEFAULT;
|
|
101
|
+
else {
|
|
102
|
+
spinner.fail('计划执行失败');
|
|
103
|
+
if (result.errors && result.errors.length > 0) {
|
|
104
|
+
console.log('');
|
|
105
|
+
console.log(chalk_1.default.bold.red('❌ 错误详情:'));
|
|
106
|
+
result.errors.forEach((error, index) => {
|
|
107
|
+
console.log(chalk_1.default.red(` ${index + 1}. [${error.kind}] ${error.message}`));
|
|
108
|
+
if (error.suggestions && error.suggestions.length > 0) {
|
|
109
|
+
error.suggestions.forEach(suggestion => {
|
|
110
|
+
console.log(chalk_1.default.yellow(` 💡 ${suggestion}`));
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
});
|
|
189
114
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
estimatedTotalLines = allFiles.length * constants_1.DIFF_ESTIMATION.LINES_PER_FILE_FALLBACK;
|
|
194
|
-
}
|
|
195
|
-
const costProfile = CostProfile_1.defaultCostProfileCalculator.calculate(allFiles, estimatedTotalLines);
|
|
196
|
-
const finalPrompt = [
|
|
197
|
-
{
|
|
198
|
-
role: 'system',
|
|
199
|
-
content: `你是一个技术文档专家。请将以下开发方案整理为一份标准的 todo.md 文档。
|
|
200
|
-
|
|
201
|
-
重要要求:
|
|
202
|
-
1. 格式清晰,使用 Markdown Checkbox (- [ ] )。
|
|
203
|
-
2. 包含 [目标]、[文件变更]、[详细步骤]。
|
|
204
|
-
3. 直接输出 Markdown 内容,不要使用 Markdown 代码块 (\`\`\`) 包裹。
|
|
205
|
-
4. 不要包含任何对话式前缀(如"好的"、"这是")或后缀(如"希望这对你有帮助")。
|
|
206
|
-
5. 开头直接输出内容,不要有任何问候语或开场白。
|
|
207
|
-
|
|
208
|
-
能力等级标注:
|
|
209
|
-
- SEMANTIC: 语义理解,需要理解代码意图和设计
|
|
210
|
-
- STRUCTURAL: 结构分析,需要理解代码结构和依赖关系
|
|
211
|
-
- LINE: 行级分析,需要理解具体代码行
|
|
212
|
-
- TEXT: 文本分析,只需要处理文本内容
|
|
213
|
-
- NONE: 无需智能分析
|
|
214
|
-
|
|
215
|
-
格式示例:
|
|
216
|
-
- [ ] 实现用户认证 [SEMANTIC]
|
|
217
|
-
- capability: SEMANTIC
|
|
218
|
-
- fallbackChain: [STRUCTURAL, LINE, TEXT, NONE]`
|
|
219
|
-
},
|
|
220
|
-
{
|
|
221
|
-
role: 'user',
|
|
222
|
-
content: currentPlan
|
|
115
|
+
if (result.summary) {
|
|
116
|
+
console.log('');
|
|
117
|
+
console.log(chalk_1.default.gray(`📝 ${result.summary}`));
|
|
223
118
|
}
|
|
224
|
-
|
|
225
|
-
const finalResponse = await (0, llm_1.runLLM)({
|
|
226
|
-
prompt: { messages: finalPrompt },
|
|
227
|
-
model: 'Assistant',
|
|
228
|
-
stream: false,
|
|
229
|
-
bypassRouter: true
|
|
230
|
-
});
|
|
231
|
-
const todoContent = finalResponse.rawText;
|
|
232
|
-
const filePath = path_1.default.join(process.cwd(), 'todo.md');
|
|
233
|
-
// 使用工具函数清理 LLM 输出
|
|
234
|
-
const cleanedContent = (0, utils_1.cleanLLMOutput)(todoContent);
|
|
235
|
-
// 添加能力元数据到文件头
|
|
236
|
-
const metadataLines = [
|
|
237
|
-
`> 📅 Generated by Yuangs Git Plan at ${new Date().toLocaleString()}`,
|
|
238
|
-
`> 🎯 Context: ${userPrompt}`,
|
|
239
|
-
`> 🔧 Capability Level: ${(0, utils_1.getCapabilityLevelDisplay)(costProfile.requiredCapability)}`,
|
|
240
|
-
`> ⚙️ Estimated Time: ${costProfile.estimatedTime}ms`,
|
|
241
|
-
`> 📊 Estimated Tokens: ${costProfile.estimatedTokens}`,
|
|
242
|
-
'',
|
|
243
|
-
];
|
|
244
|
-
const fileOutput = metadataLines.join('\n') + cleanedContent;
|
|
245
|
-
fs_1.default.writeFileSync(filePath, fileOutput);
|
|
246
|
-
spinner.succeed(chalk_1.default.green(`\n✅ 规划完成!文件已生成: ${chalk_1.default.bold('todo.md')}`));
|
|
247
|
-
console.log(chalk_1.default.gray(`👉 你可以使用 'code todo.md' 打开查看`));
|
|
119
|
+
}
|
|
248
120
|
}
|
|
249
121
|
catch (error) {
|
|
250
|
-
spinner.fail(chalk_1.default.red(
|
|
122
|
+
spinner.fail(chalk_1.default.red(`执行过程中出错: ${error.message}`));
|
|
251
123
|
if (error instanceof llm_1.AIError) {
|
|
252
124
|
console.error(chalk_1.default.red(`Status: ${error.statusCode}`));
|
|
253
125
|
}
|
|
126
|
+
process.exit(1);
|
|
254
127
|
}
|
|
255
128
|
});
|
|
256
129
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../src/commands/git/plan.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../src/commands/git/plan.ts"],"names":[],"mappings":";;;;;AAoDA,kDA0GC;AA7JD,kDAA0B;AAC1B,8CAAsB;AACtB,4CAAoB;AACpB,gDAAwB;AACxB,0DAAuD;AACvD,yCAA0C;AAC1C,oDAI8B;AAC9B,2EAAwE;AACxE,mCAAoD;AAEpD,MAAM,mBAAmB,GAAG,kBAAkB,CAAC;AAC/C,MAAM,eAAe,GAAG,GAAG,CAAC;AAE5B,KAAK,UAAU,iBAAiB,CAAC,SAAiB,EAAE,QAAgB;IAChE,IAAI,SAAS,EAAE,CAAC;QACZ,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAClD,CAAC;IAED,IAAI,CAAC;QACD,MAAM,YAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,YAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACtD,MAAM,OAAO,GAAG,MAAM,YAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAE7D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,UAAU,GAAG,CAAC,CAAC;QAEnB,OAAO,UAAU,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;YACvF,UAAU,EAAE,CAAC;QACjB,CAAC;QAED,OAAO,UAAU,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAClE,UAAU,EAAE,CAAC;QACjB,CAAC;QAED,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;QAE7D,IAAI,UAAU,EAAE,CAAC;YACb,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QAClD,CAAC;IACL,CAAC;IAAC,OAAO,CAAU,EAAE,CAAC;QAClB,IAAI,CAAC,YAAY,KAAK,IAAK,CAA2B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvE,OAAO,CAAC,IAAI,CAAC,eAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAClE,CAAC;IACL,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC5D,CAAC;AAED,SAAgB,mBAAmB,CAAC,MAAe;IAC/C,MAAM;SACD,OAAO,CAAC,kBAAkB,CAAC;SAC3B,WAAW,CAAC,+CAA+C,CAAC;SAC5D,MAAM,CAAC,uBAAuB,EAAE,MAAM,EAAE,GAAG,CAAC;SAC5C,MAAM,CAAC,qBAAqB,EAAE,OAAO,EAAE,WAAW,CAAC;SACnD,MAAM,CAAC,0BAA0B,EAAE,OAAO,EAAE,uBAAuB,CAAC;SACpE,MAAM,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE;QACnC,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAC/C,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;QAErD,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,MAAM,iBAAiB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAEtF,MAAM,OAAO,GAAG,IAAA,aAAG,EAAC,QAAQ,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,KAAK,EAAE,CAAC;QAErF,IAAI,CAAC;YACD,MAAM,UAAU,GAAG,IAAI,uBAAU,EAAE,CAAC;YAEpC,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,eAAe,EAAE,CAAC,EAAE,CAAC;gBACxC,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;gBAC9B,OAAO;YACX,CAAC;YAED,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YAE9B,MAAM,cAAc,GAAmB;gBACnC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC;gBAChF,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,WAAW;gBACnC,UAAU,EAAE,iCAAe,CAAC,QAAQ;aACvC,CAAC;YAEF,MAAM,OAAO,GAAG,IAAI,8BAAkB,CAAC,cAAc,CAAC,CAAC;YACvD,MAAM,YAAY,GAAG,IAAI,wBAAY,CAAC,UAAU,CAAC,CAAC;YAElD,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC;YAElD,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;YAEnC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAChC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,EAC7D;gBACI,UAAU;gBACV,SAAS;gBACT,cAAc,EAAE,OAAO,CAAC,KAAK;gBAC7B,aAAa,EAAE,OAAO,CAAC,aAAa;aACvC,CACJ,CAAC;YAEF,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;gBAChC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAE1B,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;gBAErD,MAAM,aAAa,GAAG;oBAClB,wCAAwC,IAAI,IAAI,EAAE,CAAC,cAAc,EAAE,EAAE;oBACrE,iBAAiB,UAAU,EAAE;oBAC7B,0BAA0B,IAAA,iCAAyB,EAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE;oBAC3F,yBAAyB,MAAM,CAAC,IAAI,CAAC,aAAa,IAAI;oBACtD,0BAA0B,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE;oBACvD,EAAE;iBACL,CAAC;gBAEF,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC;gBAEvE,YAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;gBAEvC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAChB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,iBAAiB,eAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;gBACnE,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC,CAAC;gBACxD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAChB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;gBACzC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;gBAE9C,OAAO,CAAC,QAAQ,EAAE,CAAC;YACvB,CAAC;iBAAM,CAAC;gBACJ,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAEvB,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC5C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;oBAChB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;oBACvC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;wBACnC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;wBAC3E,IAAI,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;4BACpD,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;gCACnC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,WAAW,UAAU,EAAE,CAAC,CAAC,CAAC;4BACvD,CAAC,CAAC,CAAC;wBACP,CAAC;oBACL,CAAC,CAAC,CAAC;gBACP,CAAC;gBAED,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;oBACjB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;oBAChB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;gBACpD,CAAC;YACL,CAAC;QACL,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YAClB,OAAO,CAAC,IAAI,CAAC,eAAK,CAAC,GAAG,CAAC,YAAY,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAErD,IAAI,KAAK,YAAY,aAAO,EAAE,CAAC;gBAC3B,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,WAAW,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;YAC5D,CAAC;YAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;IACL,CAAC,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Enhanced AST Parser for
|
|
2
|
+
* Enhanced AST Parser for Auditable Execution Kernel
|
|
3
3
|
*
|
|
4
|
-
* 增强版 AST
|
|
5
|
-
* 1.
|
|
4
|
+
* 增强版 AST 解析器,作为内核的 "事实提取器",支持:
|
|
5
|
+
* 1. 提取导出符号(函数、类、接口、类型别名、变量等)
|
|
6
6
|
* 2. 提取 JSDoc 注释和标签
|
|
7
|
-
* 3. 提供符号的完整元数据(名称、类型、JSDoc
|
|
7
|
+
* 3. 提供符号的完整元数据(名称、类型、JSDoc、行号、符号哈希等)
|
|
8
|
+
* 4. 支持嵌套结构(类中的方法、函数中的函数等)
|
|
9
|
+
* 5. 处理匿名函数和箭头函数
|
|
10
|
+
* 6. 生成符号哈希用于审计验证
|
|
11
|
+
* 7. 集成 TypeChecker 以支持跨文件类型解析
|
|
8
12
|
*
|
|
9
13
|
* 使用 TypeScript Compiler API 实现精确解析
|
|
10
14
|
*/
|
|
@@ -20,8 +24,36 @@ export interface SymbolMetadata {
|
|
|
20
24
|
jsDoc: string;
|
|
21
25
|
/** 起始行号(从1开始) */
|
|
22
26
|
startLine: number;
|
|
27
|
+
/** 结束行号(从1开始) */
|
|
28
|
+
endLine: number;
|
|
23
29
|
/** 是否已导出 */
|
|
24
30
|
isExported: boolean;
|
|
31
|
+
/** 符号内容的哈希值(用于审计验证) */
|
|
32
|
+
hash: string;
|
|
33
|
+
/** 符号的完整源码内容 */
|
|
34
|
+
content: string;
|
|
35
|
+
/** 访问修饰符(public, private, protected) */
|
|
36
|
+
accessibility?: 'public' | 'private' | 'protected';
|
|
37
|
+
/** 参数列表(如果是函数/方法) */
|
|
38
|
+
parameters?: ParameterInfo[];
|
|
39
|
+
/** 返回类型(如果是函数) */
|
|
40
|
+
returnType?: string;
|
|
41
|
+
/** 泛型参数(如果有) */
|
|
42
|
+
typeParameters?: string[];
|
|
43
|
+
/** 父级符号名称(用于嵌套结构) */
|
|
44
|
+
parentName?: string;
|
|
45
|
+
/** 是否是匿名函数 */
|
|
46
|
+
isAnonymous?: boolean;
|
|
47
|
+
/** 符号的完整路径(如:ClassName.methodName) */
|
|
48
|
+
fullPath?: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* 参数信息接口
|
|
52
|
+
*/
|
|
53
|
+
export interface ParameterInfo {
|
|
54
|
+
name: string;
|
|
55
|
+
type: string;
|
|
56
|
+
optional: boolean;
|
|
25
57
|
}
|
|
26
58
|
/**
|
|
27
59
|
* AST 解析结果
|
|
@@ -37,7 +69,7 @@ export interface ASTParseResult {
|
|
|
37
69
|
/**
|
|
38
70
|
* 增强版 AST 解析器
|
|
39
71
|
*
|
|
40
|
-
*
|
|
72
|
+
* 作为可审计执行内核的 "事实提取器",提供精确的符号提取能力
|
|
41
73
|
*/
|
|
42
74
|
export declare class EnhancedASTParser {
|
|
43
75
|
/**
|
|
@@ -60,8 +92,34 @@ export declare class EnhancedASTParser {
|
|
|
60
92
|
*
|
|
61
93
|
* @param node - AST 节点
|
|
62
94
|
* @param symbols - 符号列表(输出参数)
|
|
95
|
+
* @param parentStack - 父级符号栈(用于嵌套结构)
|
|
96
|
+
* @param typeChecker - TypeScript 类型检查器
|
|
63
97
|
*/
|
|
64
98
|
private visitAndExtractSymbols;
|
|
99
|
+
/**
|
|
100
|
+
* Extract modifier information (export, access modifiers) from a node
|
|
101
|
+
*/
|
|
102
|
+
private extractModifiers;
|
|
103
|
+
/**
|
|
104
|
+
* Extract symbol information from a node
|
|
105
|
+
*/
|
|
106
|
+
private extractSymbolInfo;
|
|
107
|
+
/**
|
|
108
|
+
* 判断是否应将符号推入父级栈
|
|
109
|
+
*/
|
|
110
|
+
private shouldPushToParentStack;
|
|
111
|
+
/**
|
|
112
|
+
* 生成匿名函数的唯一名称
|
|
113
|
+
*/
|
|
114
|
+
private generateAnonymousName;
|
|
115
|
+
/**
|
|
116
|
+
* 提取函数参数信息
|
|
117
|
+
*/
|
|
118
|
+
private extractParameters;
|
|
119
|
+
/**
|
|
120
|
+
* 提取类型信息
|
|
121
|
+
*/
|
|
122
|
+
private extractType;
|
|
65
123
|
/**
|
|
66
124
|
* 从节点提取 JSDoc 注释
|
|
67
125
|
*
|
|
@@ -69,6 +127,14 @@ export declare class EnhancedASTParser {
|
|
|
69
127
|
* @returns 提取的 JSDoc 文档字符串
|
|
70
128
|
*/
|
|
71
129
|
private extractJSDoc;
|
|
130
|
+
/**
|
|
131
|
+
* 计算内容的哈希值(用于审计验证)
|
|
132
|
+
*/
|
|
133
|
+
private calculateHash;
|
|
134
|
+
/**
|
|
135
|
+
* 规范化代码(移除空格和注释) using AST-based approach to avoid issues with string literals
|
|
136
|
+
*/
|
|
137
|
+
private normalizeCode;
|
|
72
138
|
/**
|
|
73
139
|
* 将 TypeScript 节点类型映射为可读字符串
|
|
74
140
|
*
|
|
@@ -83,4 +149,12 @@ export declare class EnhancedASTParser {
|
|
|
83
149
|
* @returns 导出符号名称数组
|
|
84
150
|
*/
|
|
85
151
|
getExportedSymbolNames(filePath: string): Promise<string[]>;
|
|
152
|
+
/**
|
|
153
|
+
* 比较两个解析结果,找出差异(用于审计目的)
|
|
154
|
+
*/
|
|
155
|
+
compareResults(oldResult: ASTParseResult, newResult: ASTParseResult): {
|
|
156
|
+
added: SymbolMetadata[];
|
|
157
|
+
removed: SymbolMetadata[];
|
|
158
|
+
modified: SymbolMetadata[];
|
|
159
|
+
};
|
|
86
160
|
}
|