autosnippet 3.0.11 → 3.0.13
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/cli.js +64 -1
- package/config/default.json +9 -0
- package/dashboard/dist/assets/{index-I2ySoCmF.js → index-Bnm26ulL.js} +47 -47
- package/dashboard/dist/index.html +1 -1
- package/lib/cli/SetupService.js +92 -5
- package/lib/cli/UpgradeService.js +14 -5
- package/lib/core/discovery/GenericDiscoverer.js +4 -28
- package/lib/external/mcp/handlers/bootstrap/base-dimensions.js +246 -0
- package/lib/external/mcp/handlers/bootstrap/pipeline/checkpoint.js +80 -0
- package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-configs.js +275 -0
- package/lib/external/mcp/handlers/bootstrap/pipeline/noAiFallback.js +600 -0
- package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +125 -342
- package/lib/external/mcp/handlers/bootstrap/refine.js +362 -0
- package/lib/external/mcp/handlers/bootstrap.js +6 -590
- package/lib/external/mcp/handlers/browse.js +119 -9
- package/lib/external/mcp/handlers/guard.js +25 -6
- package/lib/external/mcp/handlers/search.js +56 -24
- package/lib/http/routes/guardRules.js +9 -17
- package/lib/injection/ServiceContainer.js +12 -3
- package/lib/platform/ios/xcode/XcodeImportResolver.js +434 -0
- package/lib/platform/ios/xcode/XcodeIntegration.js +40 -659
- package/lib/platform/ios/xcode/XcodeWriteUtils.js +220 -0
- package/lib/service/chat/ChatAgent.js +39 -418
- package/lib/service/chat/ChatAgentPrompts.js +149 -0
- package/lib/service/chat/ChatAgentTasks.js +297 -0
- package/lib/service/chat/tools/_shared.js +61 -0
- package/lib/service/chat/tools/ai-analysis.js +284 -0
- package/lib/service/chat/tools/ast-graph.js +681 -0
- package/lib/service/chat/tools/composite.js +496 -0
- package/lib/service/chat/tools/guard.js +265 -0
- package/lib/service/chat/tools/index.js +250 -0
- package/lib/service/chat/tools/infrastructure.js +222 -0
- package/lib/service/chat/tools/knowledge-graph.js +234 -0
- package/lib/service/chat/tools/lifecycle.js +469 -0
- package/lib/service/chat/tools/project-access.js +923 -0
- package/lib/service/chat/tools/query.js +264 -0
- package/lib/service/chat/tools.js +14 -3994
- package/lib/service/cursor/AgentInstructionsGenerator.js +395 -0
- package/lib/service/cursor/CursorDeliveryPipeline.js +70 -11
- package/lib/service/cursor/FileProtection.js +116 -0
- package/lib/service/cursor/KnowledgeCompressor.js +61 -11
- package/lib/service/cursor/SkillsSyncer.js +5 -3
- package/lib/service/cursor/TopicClassifier.js +19 -3
- package/lib/service/guard/ExclusionManager.js +26 -2
- package/lib/service/guard/GuardCheckEngine.js +38 -370
- package/lib/service/guard/GuardCodeChecks.js +362 -0
- package/lib/service/guard/GuardCrossFileChecks.js +307 -0
- package/lib/service/guard/GuardPatternUtils.js +180 -0
- package/lib/service/guard/GuardService.js +80 -38
- package/lib/service/module/ModuleService.js +1 -0
- package/lib/service/search/SearchEngine.js +10 -2
- package/lib/service/wiki/WikiGenerator.js +226 -1532
- package/lib/service/wiki/WikiRenderers.js +1878 -0
- package/lib/service/wiki/WikiUtils.js +907 -0
- package/lib/shared/LanguageService.js +299 -0
- package/package.json +1 -1
|
@@ -0,0 +1,681 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ast-graph.js — AST 结构化分析 + Agent Memory 工具 (10)
|
|
3
|
+
*
|
|
4
|
+
* 44. get_project_overview 项目 AST 概览
|
|
5
|
+
* 45. get_class_hierarchy 类继承层级
|
|
6
|
+
* 46. get_class_info 类详细信息
|
|
7
|
+
* 47. get_protocol_info 协议详细信息
|
|
8
|
+
* 48. get_method_overrides 方法覆写查询
|
|
9
|
+
* 49. get_category_map Category 扩展映射
|
|
10
|
+
* 50. get_previous_analysis 前序维度分析结果
|
|
11
|
+
* 51. note_finding 记录关键发现
|
|
12
|
+
* 52. get_previous_evidence 检索前序维度证据
|
|
13
|
+
* 53. query_code_graph 查询代码实体图谱
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
// ════════════════════════════════════════════════════════════
|
|
17
|
+
// AST 结构化分析 (7) — v3.0 AI-First Bootstrap AST 工具
|
|
18
|
+
// ════════════════════════════════════════════════════════════
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 辅助: 安全获取 ProjectGraph 实例
|
|
22
|
+
* @param {object} ctx
|
|
23
|
+
* @returns {import('../../core/ast/ProjectGraph.js').default|null}
|
|
24
|
+
*/
|
|
25
|
+
function _getProjectGraph(ctx) {
|
|
26
|
+
try {
|
|
27
|
+
return ctx.container?.get('projectGraph') || null;
|
|
28
|
+
} catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ────────────────────────────────────────────────────────────
|
|
34
|
+
// 44. get_project_overview — 项目 AST 概览
|
|
35
|
+
// ────────────────────────────────────────────────────────────
|
|
36
|
+
export const getProjectOverview = {
|
|
37
|
+
name: 'get_project_overview',
|
|
38
|
+
description:
|
|
39
|
+
'获取项目的整体结构概览:文件统计、模块列表、入口点、类/协议/Category 数量。' +
|
|
40
|
+
'适用场景:了解项目规模和架构布局,规划探索路径。',
|
|
41
|
+
parameters: {
|
|
42
|
+
type: 'object',
|
|
43
|
+
properties: {},
|
|
44
|
+
},
|
|
45
|
+
handler: async (_params, ctx) => {
|
|
46
|
+
const graph = _getProjectGraph(ctx);
|
|
47
|
+
if (!graph) {
|
|
48
|
+
return 'AST 分析不可用 — ProjectGraph 未构建。请检查 tree-sitter 是否已安装。';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const o = graph.getOverview();
|
|
52
|
+
const lines = [
|
|
53
|
+
`📊 项目 AST 概览 (构建耗时 ${o.buildTimeMs}ms)`,
|
|
54
|
+
``,
|
|
55
|
+
`文件: ${o.totalFiles} | 类: ${o.totalClasses} | 协议: ${o.totalProtocols} | Category: ${o.totalCategories} | 方法: ${o.totalMethods}`,
|
|
56
|
+
``,
|
|
57
|
+
`── 模块 ──`,
|
|
58
|
+
];
|
|
59
|
+
for (const mod of o.topLevelModules) {
|
|
60
|
+
const count = o.classesPerModule[mod] || 0;
|
|
61
|
+
lines.push(` ${mod}/ — ${count} 个类`);
|
|
62
|
+
}
|
|
63
|
+
if (o.entryPoints.length > 0) {
|
|
64
|
+
lines.push(``, `── 入口点 ──`);
|
|
65
|
+
for (const ep of o.entryPoints) {
|
|
66
|
+
lines.push(` ${ep}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return lines.join('\n');
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// ────────────────────────────────────────────────────────────
|
|
74
|
+
// 45. get_class_hierarchy — 类继承层级
|
|
75
|
+
// ────────────────────────────────────────────────────────────
|
|
76
|
+
export const getClassHierarchy = {
|
|
77
|
+
name: 'get_class_hierarchy',
|
|
78
|
+
description:
|
|
79
|
+
'查看指定类的继承链(向上到根类)和直接子类列表。' +
|
|
80
|
+
'传入 className 查看指定类,不传则返回项目中所有根类及其子树。',
|
|
81
|
+
parameters: {
|
|
82
|
+
type: 'object',
|
|
83
|
+
properties: {
|
|
84
|
+
className: { type: 'string', description: '类名 (可选, 不填则返回完整层级)' },
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
handler: async (params, ctx) => {
|
|
88
|
+
const graph = _getProjectGraph(ctx);
|
|
89
|
+
if (!graph) {
|
|
90
|
+
return 'AST 分析不可用 — ProjectGraph 未构建。';
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const className = params.className || params.class_name;
|
|
94
|
+
if (className) {
|
|
95
|
+
const chain = graph.getInheritanceChain(className);
|
|
96
|
+
const subs = graph.getSubclasses(className);
|
|
97
|
+
if (chain.length === 0) {
|
|
98
|
+
return `未找到类 ${className}`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const lines = [`🔗 ${className} 继承链:`, ` ${chain.join(' → ')}`];
|
|
102
|
+
if (subs.length > 0) {
|
|
103
|
+
lines.push(``, `直接子类 (${subs.length}):`);
|
|
104
|
+
for (const s of subs) {
|
|
105
|
+
lines.push(` ├── ${s}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return lines.join('\n');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// 全量: 找出所有根类 (没有父类或父类不在项目中的类)
|
|
112
|
+
const allClasses = graph.getAllClassNames();
|
|
113
|
+
const roots = allClasses.filter((c) => {
|
|
114
|
+
const chain = graph.getInheritanceChain(c);
|
|
115
|
+
return chain.length <= 1 || !allClasses.includes(chain[1]);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const lines = [`🌳 项目类层级 (${allClasses.length} 个类, ${roots.length} 棵树)`];
|
|
119
|
+
for (const root of roots.slice(0, 30)) {
|
|
120
|
+
const descendants = graph.getAllDescendants(root);
|
|
121
|
+
lines.push(` ${root} (${descendants.length} 个后代)`);
|
|
122
|
+
for (const d of descendants.slice(0, 5)) {
|
|
123
|
+
lines.push(` └── ${d}`);
|
|
124
|
+
}
|
|
125
|
+
if (descendants.length > 5) {
|
|
126
|
+
lines.push(` ... 还有 ${descendants.length - 5} 个`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (roots.length > 30) {
|
|
130
|
+
lines.push(`... 还有 ${roots.length - 30} 棵树`);
|
|
131
|
+
}
|
|
132
|
+
return lines.join('\n');
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
// ────────────────────────────────────────────────────────────
|
|
137
|
+
// 46. get_class_info — 类详细信息
|
|
138
|
+
// ────────────────────────────────────────────────────────────
|
|
139
|
+
export const getClassInfo = {
|
|
140
|
+
name: 'get_class_info',
|
|
141
|
+
description: '获取指定类的详细信息: 属性、方法签名、导入、继承关系、Category 扩展。',
|
|
142
|
+
parameters: {
|
|
143
|
+
type: 'object',
|
|
144
|
+
properties: {
|
|
145
|
+
className: { type: 'string', description: '类名 (必填)' },
|
|
146
|
+
},
|
|
147
|
+
required: ['className'],
|
|
148
|
+
},
|
|
149
|
+
handler: async (params, ctx) => {
|
|
150
|
+
const graph = _getProjectGraph(ctx);
|
|
151
|
+
if (!graph) {
|
|
152
|
+
return 'AST 分析不可用 — ProjectGraph 未构建。';
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const className = params.className || params.class_name;
|
|
156
|
+
const info = graph.getClassInfo(className);
|
|
157
|
+
if (!info) {
|
|
158
|
+
return `未找到类 "${className}"。可以使用 get_project_overview 查看项目中的所有类。`;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const chain = graph.getInheritanceChain(className);
|
|
162
|
+
const cats = graph.getCategoryExtensions(className);
|
|
163
|
+
const subs = graph.getSubclasses(className);
|
|
164
|
+
|
|
165
|
+
const lines = [
|
|
166
|
+
`📦 ${info.name}`,
|
|
167
|
+
`文件: ${info.filePath}:${info.line}`,
|
|
168
|
+
`继承: ${chain.join(' → ')}`,
|
|
169
|
+
];
|
|
170
|
+
|
|
171
|
+
if (info.protocols.length > 0) {
|
|
172
|
+
lines.push(`遵循: <${info.protocols.join(', ')}>`);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (info.properties.length > 0) {
|
|
176
|
+
lines.push(``, `── 属性 (${info.properties.length}) ──`);
|
|
177
|
+
for (const p of info.properties) {
|
|
178
|
+
const attrs = p.attributes.length > 0 ? ` (${p.attributes.join(', ')})` : '';
|
|
179
|
+
lines.push(` ${p.name}: ${p.type}${attrs}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (info.methods.length > 0) {
|
|
184
|
+
lines.push(``, `── 方法 (${info.methods.length}) ──`);
|
|
185
|
+
const classMethods = info.methods.filter((m) => m.isClassMethod);
|
|
186
|
+
const instanceMethods = info.methods.filter((m) => !m.isClassMethod);
|
|
187
|
+
for (const m of classMethods) {
|
|
188
|
+
const cx = m.complexity > 3 ? ` [复杂度:${m.complexity}]` : '';
|
|
189
|
+
lines.push(` + ${m.selector} → ${m.returnType}${cx}`);
|
|
190
|
+
}
|
|
191
|
+
for (const m of instanceMethods) {
|
|
192
|
+
const cx = m.complexity > 3 ? ` [复杂度:${m.complexity}]` : '';
|
|
193
|
+
lines.push(` - ${m.selector} → ${m.returnType}${cx}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (cats.length > 0) {
|
|
198
|
+
lines.push(``, `── Category 扩展 (${cats.length}) ──`);
|
|
199
|
+
for (const cat of cats) {
|
|
200
|
+
const methodNames = cat.methods.map((m) => m.selector).join(', ');
|
|
201
|
+
lines.push(` ${info.name}(${cat.categoryName}) — ${cat.filePath} — [${methodNames}]`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (subs.length > 0) {
|
|
206
|
+
lines.push(``, `── 直接子类 (${subs.length}) ──`);
|
|
207
|
+
for (const s of subs) {
|
|
208
|
+
lines.push(` ${s}`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return lines.join('\n');
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
// ────────────────────────────────────────────────────────────
|
|
217
|
+
// 47. get_protocol_info — 协议详细信息
|
|
218
|
+
// ────────────────────────────────────────────────────────────
|
|
219
|
+
export const getProtocolInfo = {
|
|
220
|
+
name: 'get_protocol_info',
|
|
221
|
+
description: '获取指定协议的定义(必选/可选方法)及所有遵循该协议的类。',
|
|
222
|
+
parameters: {
|
|
223
|
+
type: 'object',
|
|
224
|
+
properties: {
|
|
225
|
+
protocolName: { type: 'string', description: '协议名 (必填)' },
|
|
226
|
+
},
|
|
227
|
+
required: ['protocolName'],
|
|
228
|
+
},
|
|
229
|
+
handler: async (params, ctx) => {
|
|
230
|
+
const graph = _getProjectGraph(ctx);
|
|
231
|
+
if (!graph) {
|
|
232
|
+
return 'AST 分析不可用 — ProjectGraph 未构建。';
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const protocolName = params.protocolName || params.protocol_name;
|
|
236
|
+
const info = graph.getProtocolInfo(protocolName);
|
|
237
|
+
if (!info) {
|
|
238
|
+
return `未找到协议 "${protocolName}"。可以使用 get_project_overview 查看项目中的所有协议。`;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const lines = [`📋 @protocol ${info.name}`, `文件: ${info.filePath}:${info.line}`];
|
|
242
|
+
|
|
243
|
+
if (info.inherits.length > 0) {
|
|
244
|
+
lines.push(`继承: <${info.inherits.join(', ')}>`);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (info.requiredMethods.length > 0) {
|
|
248
|
+
lines.push(``, `── @required (${info.requiredMethods.length}) ──`);
|
|
249
|
+
for (const m of info.requiredMethods) {
|
|
250
|
+
lines.push(` ${m.isClassMethod ? '+' : '-'} ${m.selector} → ${m.returnType}`);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (info.optionalMethods.length > 0) {
|
|
255
|
+
lines.push(``, `── @optional (${info.optionalMethods.length}) ──`);
|
|
256
|
+
for (const m of info.optionalMethods) {
|
|
257
|
+
lines.push(` ${m.isClassMethod ? '+' : '-'} ${m.selector} → ${m.returnType}`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (info.conformers.length > 0) {
|
|
262
|
+
lines.push(``, `── 遵循者 (${info.conformers.length}) ──`);
|
|
263
|
+
for (const c of info.conformers) {
|
|
264
|
+
lines.push(` ${c}`);
|
|
265
|
+
}
|
|
266
|
+
} else {
|
|
267
|
+
lines.push(``, `⚠️ 暂未发现遵循此协议的类`);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return lines.join('\n');
|
|
271
|
+
},
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
// ────────────────────────────────────────────────────────────
|
|
275
|
+
// 48. get_method_overrides — 方法覆写查询
|
|
276
|
+
// ────────────────────────────────────────────────────────────
|
|
277
|
+
export const getMethodOverrides = {
|
|
278
|
+
name: 'get_method_overrides',
|
|
279
|
+
description: '查找覆写了指定方法的所有子类。适用于理解方法在继承树中的多态行为。',
|
|
280
|
+
parameters: {
|
|
281
|
+
type: 'object',
|
|
282
|
+
properties: {
|
|
283
|
+
className: { type: 'string', description: '定义该方法的基类名 (必填)' },
|
|
284
|
+
methodName: { type: 'string', description: '方法名或 selector (必填)' },
|
|
285
|
+
},
|
|
286
|
+
required: ['className', 'methodName'],
|
|
287
|
+
},
|
|
288
|
+
handler: async (params, ctx) => {
|
|
289
|
+
const graph = _getProjectGraph(ctx);
|
|
290
|
+
if (!graph) {
|
|
291
|
+
return 'AST 分析不可用 — ProjectGraph 未构建。';
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const className = params.className || params.class_name;
|
|
295
|
+
const methodName = params.methodName || params.method_name;
|
|
296
|
+
const overrides = graph.getMethodOverrides(className, methodName);
|
|
297
|
+
|
|
298
|
+
if (overrides.length === 0) {
|
|
299
|
+
return `"${className}.${methodName}" 没有在任何子类中被覆写。`;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const lines = [`🔀 ${className}.${methodName} 的覆写 (${overrides.length} 处):`];
|
|
303
|
+
for (const o of overrides) {
|
|
304
|
+
const cx = o.method.complexity > 3 ? ` [复杂度:${o.method.complexity}]` : '';
|
|
305
|
+
lines.push(` ${o.className} — ${o.filePath}:${o.method.line}${cx}`);
|
|
306
|
+
}
|
|
307
|
+
return lines.join('\n');
|
|
308
|
+
},
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
// ────────────────────────────────────────────────────────────
|
|
312
|
+
// 49. get_category_map — Category 扩展映射
|
|
313
|
+
// ────────────────────────────────────────────────────────────
|
|
314
|
+
export const getCategoryMap = {
|
|
315
|
+
name: 'get_category_map',
|
|
316
|
+
description:
|
|
317
|
+
'获取指定类或整个项目的 ObjC Category 扩展映射。Category 是 ObjC 的核心模式,了解它有助于发现功能划分。',
|
|
318
|
+
parameters: {
|
|
319
|
+
type: 'object',
|
|
320
|
+
properties: {
|
|
321
|
+
className: {
|
|
322
|
+
type: 'string',
|
|
323
|
+
description: '类名 — 可选, 不填则返回整个项目中有 Category 的类列表',
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
handler: async (params, ctx) => {
|
|
328
|
+
const graph = _getProjectGraph(ctx);
|
|
329
|
+
if (!graph) {
|
|
330
|
+
return 'AST 分析不可用 — ProjectGraph 未构建。';
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const className = params.className || params.class_name;
|
|
334
|
+
if (className) {
|
|
335
|
+
const cats = graph.getCategoryExtensions(className);
|
|
336
|
+
if (cats.length === 0) {
|
|
337
|
+
return `"${className}" 没有 Category 扩展。`;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const lines = [`📂 ${className} 的 Category 扩展 (${cats.length}):`];
|
|
341
|
+
for (const cat of cats) {
|
|
342
|
+
lines.push(` ${className}(${cat.categoryName}) — ${cat.filePath}:${cat.line}`);
|
|
343
|
+
for (const m of cat.methods) {
|
|
344
|
+
lines.push(` ${m.isClassMethod ? '+' : '-'} ${m.selector}`);
|
|
345
|
+
}
|
|
346
|
+
if (cat.protocols.length > 0) {
|
|
347
|
+
lines.push(` 遵循: <${cat.protocols.join(', ')}>`);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return lines.join('\n');
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// 全量概览
|
|
354
|
+
const allClasses = graph.getAllClassNames();
|
|
355
|
+
const withCats = allClasses
|
|
356
|
+
.map((c) => ({ name: c, cats: graph.getCategoryExtensions(c) }))
|
|
357
|
+
.filter((x) => x.cats.length > 0)
|
|
358
|
+
.sort((a, b) => b.cats.length - a.cats.length);
|
|
359
|
+
|
|
360
|
+
if (withCats.length === 0) {
|
|
361
|
+
return '项目中没有发现 Category 扩展。';
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const lines = [`📂 项目 Category 概览 (${withCats.length} 个类有 Category):`];
|
|
365
|
+
for (const { name, cats } of withCats.slice(0, 30)) {
|
|
366
|
+
const catNames = cats.map((c) => c.categoryName).join(', ');
|
|
367
|
+
lines.push(` ${name} — ${cats.length} 个: (${catNames})`);
|
|
368
|
+
}
|
|
369
|
+
if (withCats.length > 30) {
|
|
370
|
+
lines.push(`... 还有 ${withCats.length - 30} 个类`);
|
|
371
|
+
}
|
|
372
|
+
return lines.join('\n');
|
|
373
|
+
},
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
// ────────────────────────────────────────────────────────────
|
|
377
|
+
// 50. get_previous_analysis — 前序维度分析结果 (可选)
|
|
378
|
+
// ────────────────────────────────────────────────────────────
|
|
379
|
+
|
|
380
|
+
export const getPreviousAnalysis = {
|
|
381
|
+
name: 'get_previous_analysis',
|
|
382
|
+
description:
|
|
383
|
+
'获取前序维度的分析摘要。在 bootstrap 中,每个维度可能有前面维度的分析结果可用。' +
|
|
384
|
+
'调用此工具可以获取之前维度产出的候选标题、设计决策等上下文,避免重复分析。' +
|
|
385
|
+
'注意: 只有在你认为前序上下文对当前任务有帮助时才调用。',
|
|
386
|
+
parameters: {
|
|
387
|
+
type: 'object',
|
|
388
|
+
properties: {},
|
|
389
|
+
},
|
|
390
|
+
handler: async (_params, ctx) => {
|
|
391
|
+
// 从 ctx._dimensionMeta 读取前序分析
|
|
392
|
+
const meta = ctx._dimensionMeta;
|
|
393
|
+
if (!meta || !meta.previousAnalysis) {
|
|
394
|
+
return '没有前序维度的分析结果可用。';
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
const prev = meta.previousAnalysis;
|
|
398
|
+
if (typeof prev === 'string') {
|
|
399
|
+
return prev;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// 格式化前序分析
|
|
403
|
+
const lines = ['📋 前序维度分析摘要:'];
|
|
404
|
+
if (Array.isArray(prev)) {
|
|
405
|
+
for (const item of prev) {
|
|
406
|
+
if (typeof item === 'string') {
|
|
407
|
+
lines.push(` ${item}`);
|
|
408
|
+
} else if (item.dimension && item.summary) {
|
|
409
|
+
lines.push(``, `── ${item.dimension} ──`);
|
|
410
|
+
lines.push(` ${item.summary}`);
|
|
411
|
+
if (item.candidateTitles?.length > 0) {
|
|
412
|
+
lines.push(` 已提交候选: ${item.candidateTitles.join(', ')}`);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
} else if (typeof prev === 'object') {
|
|
417
|
+
for (const [key, value] of Object.entries(prev)) {
|
|
418
|
+
lines.push(` ${key}: ${typeof value === 'string' ? value : JSON.stringify(value)}`);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return lines.join('\n');
|
|
422
|
+
},
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
// ────────────────────────────────────────────────────────────
|
|
426
|
+
// 51. note_finding — 记录关键发现到工作记忆 (Scratchpad)
|
|
427
|
+
// ────────────────────────────────────────────────────────────
|
|
428
|
+
export const noteFinding = {
|
|
429
|
+
name: 'note_finding',
|
|
430
|
+
description:
|
|
431
|
+
'记录一个关键发现到工作记忆的 Scratchpad。在分析过程中发现重要模式、设计决策或事实时调用。' +
|
|
432
|
+
'这些发现会在上下文窗口压缩后依然保留,确保分析后期不会遗忘早期重要发现。' +
|
|
433
|
+
'建议在发现关键架构模式、核心类职责、重要设计约束时调用。',
|
|
434
|
+
parameters: {
|
|
435
|
+
type: 'object',
|
|
436
|
+
properties: {
|
|
437
|
+
finding: {
|
|
438
|
+
type: 'string',
|
|
439
|
+
description:
|
|
440
|
+
'关键发现描述 (≤150 字)。应是具体、可验证的陈述,例如 "BDNetworkManager 使用单例模式,所有请求通过其发起"',
|
|
441
|
+
},
|
|
442
|
+
evidence: {
|
|
443
|
+
type: 'string',
|
|
444
|
+
description: '支持证据 (文件路径:行号),例如 "BDNetworkManager.m:45"',
|
|
445
|
+
},
|
|
446
|
+
importance: {
|
|
447
|
+
type: 'number',
|
|
448
|
+
description: '重要性评分 1-10。8+ = 影响全局架构,5-7 = 常见模式,1-4 = 细节备注',
|
|
449
|
+
},
|
|
450
|
+
},
|
|
451
|
+
required: ['finding'],
|
|
452
|
+
},
|
|
453
|
+
handler: async (params, ctx) => {
|
|
454
|
+
const workingMemory = ctx._workingMemory;
|
|
455
|
+
if (!workingMemory) {
|
|
456
|
+
return '⚠ 工作记忆未初始化 (仅在 bootstrap 分析期间可用)';
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
const finding = params.finding || '';
|
|
460
|
+
const evidence = params.evidence || '';
|
|
461
|
+
const importance = params.importance || 5;
|
|
462
|
+
const round = ctx._currentRound || 0;
|
|
463
|
+
|
|
464
|
+
workingMemory.noteKeyFinding(finding, evidence, importance, round);
|
|
465
|
+
|
|
466
|
+
return `📌 已记录发现 [${importance}/10]: "${finding.substring(0, 80)}" — 当前共 ${workingMemory.scratchpadSize} 条关键发现`;
|
|
467
|
+
},
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
// ────────────────────────────────────────────────────────────
|
|
471
|
+
// 52. get_previous_evidence — 检索前序维度的代码证据
|
|
472
|
+
// ────────────────────────────────────────────────────────────
|
|
473
|
+
export const getPreviousEvidence = {
|
|
474
|
+
name: 'get_previous_evidence',
|
|
475
|
+
description:
|
|
476
|
+
'获取前序维度对特定文件/类/模式的分析证据。避免重复搜索和读取已经被其他维度分析过的内容。' +
|
|
477
|
+
'当你要搜索某个类名或文件时,先调用此工具看前序维度是否已有发现。',
|
|
478
|
+
parameters: {
|
|
479
|
+
type: 'object',
|
|
480
|
+
properties: {
|
|
481
|
+
query: {
|
|
482
|
+
type: 'string',
|
|
483
|
+
description: '搜索查询 (文件名、类名、模式名、关键词)',
|
|
484
|
+
},
|
|
485
|
+
dimId: {
|
|
486
|
+
type: 'string',
|
|
487
|
+
description: '指定维度 ID (可选,默认搜索所有前序维度)',
|
|
488
|
+
},
|
|
489
|
+
},
|
|
490
|
+
required: ['query'],
|
|
491
|
+
},
|
|
492
|
+
handler: async (params, ctx) => {
|
|
493
|
+
const episodicMemory = ctx._episodicMemory;
|
|
494
|
+
if (!episodicMemory) {
|
|
495
|
+
return '没有前序维度的证据可用。';
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
const results = episodicMemory.searchEvidence(params.query, params.dimId || undefined);
|
|
499
|
+
|
|
500
|
+
if (results.length === 0) {
|
|
501
|
+
return `没有找到与 "${params.query}" 相关的前序证据。建议自行搜索。`;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
const lines = [`📋 前序维度证据 (匹配 "${params.query}", ${results.length} 条):`];
|
|
505
|
+
for (const r of results.slice(0, 8)) {
|
|
506
|
+
lines.push(` 📄 ${r.filePath}`);
|
|
507
|
+
lines.push(
|
|
508
|
+
` [${r.evidence.dimId}] [${r.evidence.importance || 5}/10] ${r.evidence.finding}`
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
if (results.length > 8) {
|
|
512
|
+
lines.push(` …还有 ${results.length - 8} 条证据`);
|
|
513
|
+
}
|
|
514
|
+
return lines.join('\n');
|
|
515
|
+
},
|
|
516
|
+
};
|
|
517
|
+
|
|
518
|
+
// ────────────────────────────────────────────────────────────
|
|
519
|
+
// 53. query_code_graph — 查询代码实体图谱
|
|
520
|
+
// ────────────────────────────────────────────────────────────
|
|
521
|
+
export const queryCodeGraph = {
|
|
522
|
+
name: 'query_code_graph',
|
|
523
|
+
description:
|
|
524
|
+
'查询代码实体图谱 (Code Entity Graph)。可查询类继承链、协议遵循者、实体搜索、影响分析等。' +
|
|
525
|
+
'图谱包含从 AST 提取的类、协议、Category、模块、设计模式及其关系。',
|
|
526
|
+
parameters: {
|
|
527
|
+
type: 'object',
|
|
528
|
+
properties: {
|
|
529
|
+
action: {
|
|
530
|
+
type: 'string',
|
|
531
|
+
enum: [
|
|
532
|
+
'search',
|
|
533
|
+
'inheritance_chain',
|
|
534
|
+
'descendants',
|
|
535
|
+
'conformances',
|
|
536
|
+
'impact',
|
|
537
|
+
'topology',
|
|
538
|
+
'entity_edges',
|
|
539
|
+
],
|
|
540
|
+
description:
|
|
541
|
+
'查询动作: search=搜索实体, inheritance_chain=继承链, descendants=子类/遵循者, conformances=协议遵循, impact=影响分析, topology=拓扑概览, entity_edges=实体的所有边',
|
|
542
|
+
},
|
|
543
|
+
entity_id: {
|
|
544
|
+
type: 'string',
|
|
545
|
+
description: '实体 ID (类名/协议名)。search 时为搜索关键词。',
|
|
546
|
+
},
|
|
547
|
+
entity_type: {
|
|
548
|
+
type: 'string',
|
|
549
|
+
enum: ['class', 'protocol', 'category', 'module', 'pattern'],
|
|
550
|
+
description: '实体类型过滤 (可选)',
|
|
551
|
+
},
|
|
552
|
+
max_depth: {
|
|
553
|
+
type: 'number',
|
|
554
|
+
description: '遍历深度 (默认 3)',
|
|
555
|
+
},
|
|
556
|
+
},
|
|
557
|
+
required: ['action', 'entity_id'],
|
|
558
|
+
},
|
|
559
|
+
handler: async (params, ctx) => {
|
|
560
|
+
try {
|
|
561
|
+
const { CodeEntityGraph } = await import('./../../service/knowledge/CodeEntityGraph.js');
|
|
562
|
+
const db = ctx?.container?.get('database');
|
|
563
|
+
if (!db) {
|
|
564
|
+
return '代码实体图谱不可用: 数据库未初始化';
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
const projectRoot = ctx?.projectRoot || process.env.ASD_PROJECT_DIR || '';
|
|
568
|
+
const ceg = new CodeEntityGraph(db, { projectRoot });
|
|
569
|
+
const maxDepth = params.max_depth || 3;
|
|
570
|
+
|
|
571
|
+
switch (params.action) {
|
|
572
|
+
case 'search': {
|
|
573
|
+
const results = ceg.searchEntities(params.entity_id, {
|
|
574
|
+
type: params.entity_type,
|
|
575
|
+
limit: 15,
|
|
576
|
+
});
|
|
577
|
+
if (results.length === 0) {
|
|
578
|
+
return `未找到匹配 "${params.entity_id}" 的代码实体。`;
|
|
579
|
+
}
|
|
580
|
+
const lines = [`🔍 代码实体搜索 "${params.entity_id}" (${results.length} 条):`];
|
|
581
|
+
for (const e of results) {
|
|
582
|
+
lines.push(
|
|
583
|
+
` • ${e.entityType}: \`${e.name}\`${e.filePath ? ` (${e.filePath}:${e.line || '?'})` : ''}${e.superclass ? ` → ${e.superclass}` : ''}`
|
|
584
|
+
);
|
|
585
|
+
}
|
|
586
|
+
return lines.join('\n');
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
case 'inheritance_chain': {
|
|
590
|
+
const chain = ceg.getInheritanceChain(params.entity_id, maxDepth);
|
|
591
|
+
if (chain.length <= 1) {
|
|
592
|
+
return `\`${params.entity_id}\` 没有已知的继承关系。`;
|
|
593
|
+
}
|
|
594
|
+
return `📐 继承链: \`${chain.join(' → ')}\``;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
case 'descendants': {
|
|
598
|
+
const type = params.entity_type || 'class';
|
|
599
|
+
const desc = ceg.getDescendants(params.entity_id, type, maxDepth);
|
|
600
|
+
if (desc.length === 0) {
|
|
601
|
+
return `\`${params.entity_id}\` 没有已知的子类/遵循者。`;
|
|
602
|
+
}
|
|
603
|
+
const lines = [`📊 ${params.entity_id} 的后代 (${desc.length}):`];
|
|
604
|
+
for (const d of desc.slice(0, 20)) {
|
|
605
|
+
lines.push(` ${' '.repeat(d.depth - 1)}└─ \`${d.id}\` (${d.type}, ${d.relation})`);
|
|
606
|
+
}
|
|
607
|
+
return lines.join('\n');
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
case 'conformances': {
|
|
611
|
+
const protos = ceg.getConformances(params.entity_id);
|
|
612
|
+
if (protos.length === 0) {
|
|
613
|
+
return `\`${params.entity_id}\` 没有已知的协议遵循。`;
|
|
614
|
+
}
|
|
615
|
+
return `📋 \`${params.entity_id}\` 遵循: ${protos.map((p) => `\`${p}\``).join(', ')}`;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
case 'impact': {
|
|
619
|
+
const type = params.entity_type || 'class';
|
|
620
|
+
const impact = ceg.getImpactRadius(params.entity_id, type, maxDepth);
|
|
621
|
+
if (impact.length === 0) {
|
|
622
|
+
return `修改 \`${params.entity_id}\` 没有检测到直接影响。`;
|
|
623
|
+
}
|
|
624
|
+
const lines = [`⚡ 修改 \`${params.entity_id}\` 的影响范围 (${impact.length}):`];
|
|
625
|
+
for (const i of impact.slice(0, 20)) {
|
|
626
|
+
lines.push(` ${' '.repeat(i.depth - 1)}⬆ \`${i.id}\` (${i.type}, via ${i.relation})`);
|
|
627
|
+
}
|
|
628
|
+
return lines.join('\n');
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
case 'topology': {
|
|
632
|
+
const topo = ceg.getTopology();
|
|
633
|
+
if (topo.totalEntities === 0) {
|
|
634
|
+
return '代码实体图谱为空。需先执行 Bootstrap。';
|
|
635
|
+
}
|
|
636
|
+
const lines = ['📈 代码实体图谱概览:'];
|
|
637
|
+
lines.push(' 实体:');
|
|
638
|
+
for (const [type, count] of Object.entries(topo.entities)) {
|
|
639
|
+
lines.push(` • ${type}: ${count}`);
|
|
640
|
+
}
|
|
641
|
+
lines.push(` 总边数: ${topo.totalEdges}`);
|
|
642
|
+
if (topo.hotNodes.length > 0) {
|
|
643
|
+
lines.push(' 核心实体 (入度最高):');
|
|
644
|
+
for (const n of topo.hotNodes.slice(0, 8)) {
|
|
645
|
+
lines.push(` • \`${n.id}\` (${n.type}, 入度=${n.inDegree})`);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
return lines.join('\n');
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
case 'entity_edges': {
|
|
652
|
+
const type = params.entity_type || 'class';
|
|
653
|
+
const edges = ceg.getEntityEdges(params.entity_id, type);
|
|
654
|
+
const total = edges.outgoing.length + edges.incoming.length;
|
|
655
|
+
if (total === 0) {
|
|
656
|
+
return `\`${params.entity_id}\` 没有已知的图谱边。`;
|
|
657
|
+
}
|
|
658
|
+
const lines = [`🔗 \`${params.entity_id}\` 的关系 (${total} 条):`];
|
|
659
|
+
if (edges.outgoing.length > 0) {
|
|
660
|
+
lines.push(' 出边:');
|
|
661
|
+
for (const e of edges.outgoing.slice(0, 10)) {
|
|
662
|
+
lines.push(` → \`${e.toId}\` (${e.toType}, ${e.relation})`);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
if (edges.incoming.length > 0) {
|
|
666
|
+
lines.push(' 入边:');
|
|
667
|
+
for (const e of edges.incoming.slice(0, 10)) {
|
|
668
|
+
lines.push(` ← \`${e.fromId}\` (${e.fromType}, ${e.relation})`);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
return lines.join('\n');
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
default:
|
|
675
|
+
return `未知动作: ${params.action}`;
|
|
676
|
+
}
|
|
677
|
+
} catch (err) {
|
|
678
|
+
return `代码实体图谱查询失败: ${err.message}`;
|
|
679
|
+
}
|
|
680
|
+
},
|
|
681
|
+
};
|