autosnippet 3.2.7 → 3.2.9
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 +13 -5
- package/dashboard/dist/assets/index-BTAsOZv2.js +128 -0
- package/dashboard/dist/assets/index-C_72Ct98.css +1 -0
- package/dashboard/dist/index.html +2 -2
- package/lib/cli/AiScanService.js +26 -29
- package/lib/cli/SetupService.js +1 -1
- package/lib/core/AstAnalyzer.js +27 -5
- package/lib/core/analysis/CallEdgeResolver.js +402 -0
- package/lib/core/analysis/CallGraphAnalyzer.js +367 -0
- package/lib/core/analysis/CallSiteExtractor.js +629 -0
- package/lib/core/analysis/DataFlowInferrer.js +57 -0
- package/lib/core/analysis/ImportPathResolver.js +189 -0
- package/lib/core/analysis/ImportRecord.js +105 -0
- package/lib/core/analysis/SymbolTableBuilder.js +211 -0
- package/lib/core/ast/ProjectGraph.js +8 -0
- package/lib/core/ast/lang-dart.js +352 -5
- package/lib/core/ast/lang-go.js +212 -10
- package/lib/core/ast/lang-java.js +205 -1
- package/lib/core/ast/lang-kotlin.js +330 -1
- package/lib/core/ast/lang-python.js +31 -2
- package/lib/core/ast/lang-rust.js +284 -3
- package/lib/core/ast/lang-swift.js +180 -1
- package/lib/core/ast/lang-typescript.js +290 -1
- package/lib/core/discovery/index.js +2 -2
- package/lib/external/ai/AiProvider.js +66 -172
- package/lib/external/ai/providers/GoogleGeminiProvider.js +23 -1
- package/lib/external/mcp/McpServer.js +1 -0
- package/lib/external/mcp/handlers/bootstrap/BootstrapSession.js +1 -1
- package/lib/external/mcp/handlers/bootstrap/ExternalSubmissionTracker.js +3 -3
- package/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.js +22 -1
- package/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.js +1 -1
- package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-configs.js +2 -1
- package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-context.js +8 -8
- package/lib/external/mcp/handlers/bootstrap/pipeline/noAiFallback.js +1 -1
- package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +311 -162
- package/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +102 -7
- package/lib/external/mcp/handlers/bootstrap/shared/dimension-sop.js +1 -1
- package/lib/external/mcp/handlers/bootstrap-external.js +9 -2
- package/lib/external/mcp/handlers/bootstrap-internal.js +19 -8
- package/lib/external/mcp/handlers/consolidated.js +9 -0
- package/lib/external/mcp/handlers/dimension-complete-external.js +6 -6
- package/lib/external/mcp/handlers/guard.js +3 -3
- package/lib/external/mcp/handlers/structure.js +62 -0
- package/lib/external/mcp/handlers/wiki-external.js +66 -3
- package/lib/external/mcp/tools.js +36 -1
- package/lib/http/HttpServer.js +1 -1
- package/lib/http/middleware/requestLogger.js +1 -0
- package/lib/http/routes/ai.js +240 -35
- package/lib/http/routes/candidates.js +2 -3
- package/lib/http/routes/extract.js +13 -11
- package/lib/http/routes/modules.js +2 -2
- package/lib/http/routes/recipes.js +9 -5
- package/lib/http/routes/remote.js +149 -270
- package/lib/http/routes/violations.js +0 -54
- package/lib/http/utils/sse-sessions.js +1 -1
- package/lib/infrastructure/logging/Logger.js +5 -4
- package/lib/infrastructure/monitoring/PerformanceMonitor.js +3 -2
- package/lib/injection/ServiceContainer.js +70 -28
- package/lib/platform/ScreenCaptureService.js +177 -0
- package/lib/platform/ios/index.js +2 -2
- package/lib/platform/ios/routes/spm.js +2 -2
- package/lib/platform/ios/spm/PackageSwiftParser.js +14 -3
- package/lib/platform/ios/spm/SpmDiscoverer.js +123 -17
- package/lib/platform/ios/spm/{SpmService.js → SpmHelper.js} +43 -675
- package/lib/platform/ios/xcode/XcodeWriteUtils.js +1 -1
- package/lib/service/agent/AgentEventBus.js +207 -0
- package/lib/service/agent/AgentFactory.js +490 -0
- package/lib/service/agent/AgentMessage.js +240 -0
- package/lib/service/agent/AgentRouter.js +228 -0
- package/lib/service/agent/AgentRuntime.js +1016 -0
- package/lib/service/agent/AgentState.js +217 -0
- package/lib/service/agent/IntentClassifier.js +331 -0
- package/lib/service/agent/LarkTransport.js +389 -0
- package/lib/service/agent/capabilities.js +408 -0
- package/lib/service/{chat → agent/context}/ContextWindow.js +37 -12
- package/lib/service/{chat → agent/context}/ExplorationTracker.js +77 -22
- package/lib/service/{chat → agent/core}/ChatAgentPrompts.js +14 -2
- package/lib/service/agent/core/LoopContext.js +170 -0
- package/lib/service/agent/core/MessageAdapter.js +223 -0
- package/lib/service/agent/core/ToolExecutionPipeline.js +376 -0
- package/lib/service/{chat → agent/domain}/ChatAgentTasks.js +19 -98
- package/lib/service/{chat → agent/domain}/EpisodicConsolidator.js +7 -7
- package/lib/service/{chat → agent/domain}/EvidenceCollector.js +4 -2
- package/lib/service/{chat/AnalystAgent.js → agent/domain/insight-analyst.js} +37 -172
- package/lib/service/{chat/HandoffProtocol.js → agent/domain/insight-gate.js} +91 -123
- package/lib/service/agent/domain/insight-producer.js +267 -0
- package/lib/service/agent/domain/scan-prompts.js +105 -0
- package/lib/service/agent/forced-summary.js +266 -0
- package/lib/service/agent/index.js +91 -0
- package/lib/service/{chat → agent}/memory/ActiveContext.js +3 -1
- package/lib/service/{chat → agent}/memory/MemoryCoordinator.js +7 -7
- package/lib/service/{chat/ProjectSemanticMemory.js → agent/memory/PersistentMemory.js} +359 -89
- package/lib/service/{chat → agent}/memory/SessionStore.js +5 -4
- package/lib/service/{chat → agent}/memory/index.js +1 -1
- package/lib/service/agent/policies.js +442 -0
- package/lib/service/agent/presets.js +303 -0
- package/lib/service/agent/strategies.js +717 -0
- package/lib/service/{chat → agent/tools}/ToolRegistry.js +3 -3
- package/lib/service/agent/tools/ai-analysis.js +75 -0
- package/lib/service/{chat → agent}/tools/ast-graph.js +229 -32
- package/lib/service/{chat → agent}/tools/composite.js +2 -1
- package/lib/service/{chat → agent}/tools/guard.js +1 -121
- package/lib/service/{chat → agent}/tools/index.js +33 -22
- package/lib/service/{chat → agent}/tools/infrastructure.js +6 -1
- package/lib/service/agent/tools/knowledge-graph.js +112 -0
- package/lib/service/agent/tools/scan-recipe.js +189 -0
- package/lib/service/agent/tools/system-interaction.js +476 -0
- package/lib/service/automation/DirectiveDetector.js +0 -1
- package/lib/service/automation/FileWatcher.js +0 -8
- package/lib/service/automation/handlers/CreateHandler.js +7 -3
- package/lib/service/automation/handlers/DraftHandler.js +7 -6
- package/lib/service/cursor/CursorDeliveryPipeline.js +167 -1
- package/lib/service/knowledge/CodeEntityGraph.js +327 -2
- package/lib/service/knowledge/KnowledgeService.js +5 -1
- package/lib/service/module/ModuleService.js +49 -73
- package/lib/service/skills/SignalCollector.js +26 -19
- package/lib/service/snippet/codecs/VSCodeCodec.js +1 -1
- package/lib/service/wiki/WikiGenerator.js +1 -1
- package/lib/shared/FieldSpec.js +1 -1
- package/lib/shared/PathGuard.js +1 -1
- package/lib/shared/StyleGuide.js +1 -1
- package/package.json +4 -1
- package/resources/native-ui/screenshot.swift +228 -0
- package/dashboard/dist/assets/index-BaGY7kJI.css +0 -1
- package/dashboard/dist/assets/index-DfHY_3ln.js +0 -128
- package/lib/core/discovery/SpmDiscoverer.js +0 -5
- package/lib/external/mcp/handlers/bootstrap/pipeline/EpisodicMemory.js +0 -749
- package/lib/external/mcp/handlers/bootstrap/pipeline/ToolResultCache.js +0 -277
- package/lib/http/routes/spm.js +0 -5
- package/lib/infrastructure/external/XcodeAutomation.js +0 -15
- package/lib/service/chat/ChatAgent.js +0 -1602
- package/lib/service/chat/Memory.js +0 -161
- package/lib/service/chat/ProducerAgent.js +0 -431
- package/lib/service/chat/ReasoningTrace.js +0 -523
- package/lib/service/chat/TaskPipeline.js +0 -357
- package/lib/service/chat/WorkingMemory.js +0 -357
- package/lib/service/chat/memory/PersistentMemory.js +0 -450
- package/lib/service/chat/tools/ai-analysis.js +0 -267
- package/lib/service/chat/tools/knowledge-graph.js +0 -234
- package/lib/service/chat/tools.js +0 -18
- package/lib/service/snippet/PlaceholderConverter.js +0 -5
- package/lib/service/snippet/codecs/XcodeCodec.js +0 -5
- /package/lib/service/{chat → agent}/ConversationStore.js +0 -0
- /package/lib/service/{chat → agent}/tools/_shared.js +0 -0
- /package/lib/service/{chat → agent}/tools/lifecycle.js +0 -0
- /package/lib/service/{chat → agent}/tools/project-access.js +0 -0
- /package/lib/service/{chat → agent}/tools/query.js +0 -0
|
@@ -4,14 +4,12 @@
|
|
|
4
4
|
* 从各子模块导入所有工具,按原始顺序组装 ALL_TOOLS 数组并导出。
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
// ── AI 分析类 (
|
|
7
|
+
// ── AI 分析类 (2) ──
|
|
8
8
|
import {
|
|
9
9
|
enrichCandidate,
|
|
10
|
-
extractRecipes,
|
|
11
10
|
refineBootstrapCandidates,
|
|
12
|
-
summarizeCode,
|
|
13
11
|
} from './ai-analysis.js';
|
|
14
|
-
// ── AST 结构化分析 + Agent Memory (
|
|
12
|
+
// ── AST 结构化分析 + Agent Memory (11) ──
|
|
15
13
|
import {
|
|
16
14
|
getCategoryMap,
|
|
17
15
|
getClassHierarchy,
|
|
@@ -22,6 +20,7 @@ import {
|
|
|
22
20
|
getProjectOverview,
|
|
23
21
|
getProtocolInfo,
|
|
24
22
|
noteFinding,
|
|
23
|
+
queryCallGraph,
|
|
25
24
|
queryCodeGraph,
|
|
26
25
|
} from './ast-graph.js';
|
|
27
26
|
// ── 组合工具 + 元工具 (6) ──
|
|
@@ -34,10 +33,8 @@ import {
|
|
|
34
33
|
submitWithCheck,
|
|
35
34
|
} from './composite.js';
|
|
36
35
|
|
|
37
|
-
// ── Guard 安全类 (
|
|
36
|
+
// ── Guard 安全类 (4) ──
|
|
38
37
|
import {
|
|
39
|
-
aiTranslate,
|
|
40
|
-
generateGuardRule,
|
|
41
38
|
getRecommendations,
|
|
42
39
|
guardCheckCode,
|
|
43
40
|
listGuardRules,
|
|
@@ -53,8 +50,16 @@ import {
|
|
|
53
50
|
rebuildIndex,
|
|
54
51
|
suggestSkills,
|
|
55
52
|
} from './infrastructure.js';
|
|
56
|
-
// ── 知识图谱类 (
|
|
57
|
-
import { addGraphEdge, checkDuplicate
|
|
53
|
+
// ── 知识图谱类 (2) ──
|
|
54
|
+
import { addGraphEdge, checkDuplicate } from './knowledge-graph.js';
|
|
55
|
+
// ── 扫描 Recipe 收集 (1) ──
|
|
56
|
+
import { collectScanRecipe } from './scan-recipe.js';
|
|
57
|
+
// ── 系统交互类 (3) ──
|
|
58
|
+
import {
|
|
59
|
+
getEnvironmentInfo,
|
|
60
|
+
runSafeCommand,
|
|
61
|
+
writeProjectFile,
|
|
62
|
+
} from './system-interaction.js';
|
|
58
63
|
// ── 生命周期操作类 (11) ──
|
|
59
64
|
import {
|
|
60
65
|
approveCandidate,
|
|
@@ -103,20 +108,15 @@ export {
|
|
|
103
108
|
searchKnowledge,
|
|
104
109
|
getRelatedRecipes,
|
|
105
110
|
// AI 分析类
|
|
106
|
-
summarizeCode,
|
|
107
|
-
extractRecipes,
|
|
108
111
|
enrichCandidate,
|
|
109
112
|
refineBootstrapCandidates,
|
|
110
113
|
// Guard 安全类
|
|
111
114
|
listGuardRules,
|
|
112
115
|
getRecommendations,
|
|
113
|
-
aiTranslate,
|
|
114
116
|
guardCheckCode,
|
|
115
117
|
queryViolations,
|
|
116
|
-
generateGuardRule,
|
|
117
118
|
// 知识图谱类
|
|
118
119
|
checkDuplicate,
|
|
119
|
-
discoverRelations,
|
|
120
120
|
addGraphEdge,
|
|
121
121
|
// 生命周期操作类
|
|
122
122
|
submitCandidate,
|
|
@@ -158,6 +158,14 @@ export {
|
|
|
158
158
|
getPreviousEvidence,
|
|
159
159
|
// 代码实体图谱
|
|
160
160
|
queryCodeGraph,
|
|
161
|
+
// 调用图查询 (Phase 5)
|
|
162
|
+
queryCallGraph,
|
|
163
|
+
// 扫描 Recipe 收集
|
|
164
|
+
collectScanRecipe,
|
|
165
|
+
// 系统交互类
|
|
166
|
+
runSafeCommand,
|
|
167
|
+
writeProjectFile,
|
|
168
|
+
getEnvironmentInfo,
|
|
161
169
|
};
|
|
162
170
|
|
|
163
171
|
// ── ALL_TOOLS 数组(与原始 tools.js 顺序一致)──
|
|
@@ -177,16 +185,12 @@ export const ALL_TOOLS = [
|
|
|
177
185
|
getRelatedRecipes,
|
|
178
186
|
listGuardRules,
|
|
179
187
|
getRecommendations,
|
|
180
|
-
// AI 分析类 (
|
|
181
|
-
summarizeCode,
|
|
182
|
-
extractRecipes,
|
|
188
|
+
// AI 分析类 (2)
|
|
183
189
|
enrichCandidate,
|
|
184
190
|
refineBootstrapCandidates,
|
|
185
|
-
|
|
186
|
-
// Guard 安全类 (3)
|
|
191
|
+
// Guard 安全类 (2)
|
|
187
192
|
guardCheckCode,
|
|
188
193
|
queryViolations,
|
|
189
|
-
generateGuardRule,
|
|
190
194
|
// 生命周期操作类 (7)
|
|
191
195
|
submitCandidate,
|
|
192
196
|
saveDocument,
|
|
@@ -200,9 +204,8 @@ export const ALL_TOOLS = [
|
|
|
200
204
|
qualityScore,
|
|
201
205
|
validateCandidate,
|
|
202
206
|
getFeedbackStats,
|
|
203
|
-
// 知识图谱类 (
|
|
207
|
+
// 知识图谱类 (2)
|
|
204
208
|
checkDuplicate,
|
|
205
|
-
discoverRelations,
|
|
206
209
|
addGraphEdge,
|
|
207
210
|
// 基础设施类 (3)
|
|
208
211
|
graphImpactAnalysis,
|
|
@@ -234,6 +237,14 @@ export const ALL_TOOLS = [
|
|
|
234
237
|
getPreviousEvidence,
|
|
235
238
|
// 代码实体图谱 (1) — Phase E
|
|
236
239
|
queryCodeGraph,
|
|
240
|
+
// 调用图查询 (1) — Phase 5
|
|
241
|
+
queryCallGraph,
|
|
242
|
+
// 系统交互 (3) — Agent 终端/文件写入/环境探测
|
|
243
|
+
runSafeCommand,
|
|
244
|
+
writeProjectFile,
|
|
245
|
+
getEnvironmentInfo,
|
|
246
|
+
// 扫描 Recipe 收集 (1) — scanKnowledge produce 阶段专用
|
|
247
|
+
collectScanRecipe,
|
|
237
248
|
];
|
|
238
249
|
|
|
239
250
|
export default ALL_TOOLS;
|
|
@@ -157,7 +157,7 @@ export const createSkillTool = {
|
|
|
157
157
|
},
|
|
158
158
|
handler: async (params, ctx) => {
|
|
159
159
|
const { createSkill } = await import('../../../external/mcp/handlers/skill.js');
|
|
160
|
-
// 根据
|
|
160
|
+
// 根据 Agent 的 source 推断 createdBy
|
|
161
161
|
const createdBy = ctx?.source === 'system' ? 'system-ai' : 'user-ai';
|
|
162
162
|
const raw = createSkill(null, { ...params, createdBy });
|
|
163
163
|
try {
|
|
@@ -206,6 +206,10 @@ export const bootstrapKnowledgeTool = {
|
|
|
206
206
|
type: 'boolean',
|
|
207
207
|
description: '是否加载 Skills 增强维度定义(推荐开启),默认 true',
|
|
208
208
|
},
|
|
209
|
+
skipAsyncFill: {
|
|
210
|
+
type: 'boolean',
|
|
211
|
+
description: '跳过异步 AI 填充(CLI 非 --wait 模式下使用,避免 DB 断连)',
|
|
212
|
+
},
|
|
209
213
|
},
|
|
210
214
|
},
|
|
211
215
|
handler: async (params, ctx) => {
|
|
@@ -218,6 +222,7 @@ export const bootstrapKnowledgeTool = {
|
|
|
218
222
|
skipGuard: params.skipGuard || false,
|
|
219
223
|
contentMaxLines: params.contentMaxLines || 120,
|
|
220
224
|
loadSkills: params.loadSkills ?? true,
|
|
225
|
+
skipAsyncFill: params.skipAsyncFill || false,
|
|
221
226
|
}
|
|
222
227
|
);
|
|
223
228
|
// bootstrapKnowledge 返回 envelope JSON string,解析提取 data
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* knowledge-graph.js — 知识图谱类工具 (2)
|
|
3
|
+
*
|
|
4
|
+
* 10. check_duplicate 候选查重
|
|
5
|
+
* 12. add_graph_edge 手动添加图谱边
|
|
6
|
+
*
|
|
7
|
+
* 注意: discover_relations 已删除。
|
|
8
|
+
* 关系发现由 Agent LLM 直接推理完成,利用通用工具(search_knowledge, query_code_graph 等)。
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { findSimilarRecipes } from '../../candidate/SimilarityService.js';
|
|
12
|
+
|
|
13
|
+
// ────────────────────────────────────────────────────────────
|
|
14
|
+
// 10. check_duplicate
|
|
15
|
+
// ────────────────────────────────────────────────────────────
|
|
16
|
+
export const checkDuplicate = {
|
|
17
|
+
name: 'check_duplicate',
|
|
18
|
+
description:
|
|
19
|
+
'候选查重 — 检测候选代码是否与已有 Recipe 重复(基于标题/摘要/代码的 Jaccard 相似度)。',
|
|
20
|
+
parameters: {
|
|
21
|
+
type: 'object',
|
|
22
|
+
properties: {
|
|
23
|
+
candidate: { type: 'object', description: '候选对象 { title, summary, code, usageGuide }' },
|
|
24
|
+
candidateId: { type: 'string', description: '或提供候选 ID,从数据库读取' },
|
|
25
|
+
projectRoot: { type: 'string', description: '项目根目录(可选,默认当前项目)' },
|
|
26
|
+
threshold: { type: 'number', description: '相似度阈值,默认 0.5' },
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
handler: async (params, ctx) => {
|
|
30
|
+
let cand = params.candidate;
|
|
31
|
+
const projectRoot = params.projectRoot || ctx.projectRoot;
|
|
32
|
+
const threshold = params.threshold ?? 0.5;
|
|
33
|
+
|
|
34
|
+
// 如果提供 candidateId,从数据库读取条目信息
|
|
35
|
+
if (!cand && params.candidateId) {
|
|
36
|
+
try {
|
|
37
|
+
const knowledgeService = ctx.container.get('knowledgeService');
|
|
38
|
+
const found = await knowledgeService.get(params.candidateId);
|
|
39
|
+
if (found) {
|
|
40
|
+
const json = typeof found.toJSON === 'function' ? found.toJSON() : found;
|
|
41
|
+
cand = {
|
|
42
|
+
title: json.title || '',
|
|
43
|
+
summary: json.description || '',
|
|
44
|
+
code: json.content?.pattern || '',
|
|
45
|
+
usageGuide: '',
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
} catch {
|
|
49
|
+
/* ignore */
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!cand) {
|
|
54
|
+
return { similar: [], message: 'No candidate provided' };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const similar = findSimilarRecipes(projectRoot, cand, {
|
|
58
|
+
threshold,
|
|
59
|
+
topK: 10,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
similar,
|
|
64
|
+
hasDuplicate: similar.some((s) => s.similarity >= 0.7),
|
|
65
|
+
highestSimilarity: similar.length > 0 ? similar[0].similarity : 0,
|
|
66
|
+
_meta: {
|
|
67
|
+
confidence: similar.length === 0 ? 'none' : similar[0].similarity >= 0.7 ? 'high' : 'low',
|
|
68
|
+
hint:
|
|
69
|
+
similar.length === 0
|
|
70
|
+
? '未发现相似 Recipe,可放心提交。'
|
|
71
|
+
: similar[0].similarity >= 0.7
|
|
72
|
+
? '发现高度相似 Recipe,建议人工审核是否重复。'
|
|
73
|
+
: '有低相似度匹配,大概率不是重复。',
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// ────────────────────────────────────────────────────────────
|
|
80
|
+
// 12. add_graph_edge
|
|
81
|
+
// ────────────────────────────────────────────────────────────
|
|
82
|
+
export const addGraphEdge = {
|
|
83
|
+
name: 'add_graph_edge',
|
|
84
|
+
description: '手动添加知识图谱关系边(从 A 到 B 的关系)。',
|
|
85
|
+
parameters: {
|
|
86
|
+
type: 'object',
|
|
87
|
+
properties: {
|
|
88
|
+
fromId: { type: 'string', description: '源节点 ID' },
|
|
89
|
+
fromType: { type: 'string', description: '源节点类型 (recipe/candidate)' },
|
|
90
|
+
toId: { type: 'string', description: '目标节点 ID' },
|
|
91
|
+
toType: { type: 'string', description: '目标节点类型 (recipe/candidate)' },
|
|
92
|
+
relation: {
|
|
93
|
+
type: 'string',
|
|
94
|
+
description:
|
|
95
|
+
'关系类型 (requires/extends/enforces/depends_on/inherits/implements/calls/prerequisite)',
|
|
96
|
+
},
|
|
97
|
+
weight: { type: 'number', description: '权重 0-1,默认 1.0' },
|
|
98
|
+
},
|
|
99
|
+
required: ['fromId', 'fromType', 'toId', 'toType', 'relation'],
|
|
100
|
+
},
|
|
101
|
+
handler: async (params, ctx) => {
|
|
102
|
+
const kgService = ctx.container.get('knowledgeGraphService');
|
|
103
|
+
return kgService.addEdge(
|
|
104
|
+
params.fromId,
|
|
105
|
+
params.fromType,
|
|
106
|
+
params.toId,
|
|
107
|
+
params.toType,
|
|
108
|
+
params.relation,
|
|
109
|
+
{ weight: params.weight || 1.0, source: 'manual' }
|
|
110
|
+
);
|
|
111
|
+
},
|
|
112
|
+
};
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scan-recipe.js — 扫描专用 Recipe 收集工具
|
|
3
|
+
*
|
|
4
|
+
* 与冷启动 submit_knowledge 使用完全相同的字段 schema,
|
|
5
|
+
* 但不入库 — 仅做本地验证 + 内存收集。
|
|
6
|
+
*
|
|
7
|
+
* 扫描 Produce 阶段 LLM 调用此工具逐个提交 Recipe,
|
|
8
|
+
* 执行完成后由 AgentFactory.scanKnowledge() 从 toolCalls 中提取。
|
|
9
|
+
*
|
|
10
|
+
* 设计原因:
|
|
11
|
+
* - 冷启动 Producer 通过 submit_knowledge 工具逐个提交候选(工具驱动)
|
|
12
|
+
* - 扫描 Produce 之前是纯 JSON 文本输出,LLM 容易 hallucinate 错误工具调用
|
|
13
|
+
* - 统一为工具驱动模式:相同 schema → 相同字段质量 → 相同下游消费
|
|
14
|
+
*
|
|
15
|
+
* @module scan-recipe
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
// ── collect_scan_recipe ──────────────────────────────────────
|
|
19
|
+
|
|
20
|
+
export const collectScanRecipe = {
|
|
21
|
+
name: 'collect_scan_recipe',
|
|
22
|
+
description:
|
|
23
|
+
'提交一条扫描发现的知识候选(Recipe)。每个独立的代码模式/设计模式/最佳实践应单独调用此工具提交。\n' +
|
|
24
|
+
'所有必填字段必须在单次调用中一次性提供。\n' +
|
|
25
|
+
'⚠️ content 必须是对象: { "pattern": "代码片段", "markdown": "项目特写正文≥200字", "rationale": "设计原理" }\n' +
|
|
26
|
+
'⚠️ reasoning 必须是对象: { "whyStandard": "原因", "sources": ["file.ts"], "confidence": 0.85 }',
|
|
27
|
+
parameters: {
|
|
28
|
+
type: 'object',
|
|
29
|
+
properties: {
|
|
30
|
+
// ── 基本信息 ──
|
|
31
|
+
title: { type: 'string', description: '中文标题(≤20字,使用项目真实类名)' },
|
|
32
|
+
language: { type: 'string', description: '编程语言(小写)' },
|
|
33
|
+
description: { type: 'string', description: '中文简述 ≤80 字,引用真实类名' },
|
|
34
|
+
tags: { type: 'array', items: { type: 'string' }, description: '标签列表' },
|
|
35
|
+
|
|
36
|
+
// ── 内容(V3 content 子对象) ──
|
|
37
|
+
content: {
|
|
38
|
+
type: 'object',
|
|
39
|
+
description:
|
|
40
|
+
'{ markdown: "项目特写 Markdown(≥200字)", pattern: "核心代码 3-8 行", rationale: "设计原理(必填)" }',
|
|
41
|
+
properties: {
|
|
42
|
+
pattern: { type: 'string', description: '核心代码片段' },
|
|
43
|
+
markdown: { type: 'string', description: 'Markdown 正文(≥200字符)' },
|
|
44
|
+
rationale: { type: 'string', description: '设计原理说明(必填)' },
|
|
45
|
+
},
|
|
46
|
+
required: ['rationale'],
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
// ── Cursor 交付(必填)──
|
|
50
|
+
kind: {
|
|
51
|
+
type: 'string',
|
|
52
|
+
enum: ['rule', 'pattern', 'fact'],
|
|
53
|
+
description: 'rule=规则 | pattern=模板 | fact=参考',
|
|
54
|
+
},
|
|
55
|
+
category: {
|
|
56
|
+
type: 'string',
|
|
57
|
+
description: '分类: View / Service / Tool / Model / Network / Storage / UI / Utility',
|
|
58
|
+
},
|
|
59
|
+
trigger: { type: 'string', description: '触发关键词(@前缀,kebab-case)' },
|
|
60
|
+
doClause: { type: 'string', description: '正向指令(英文祈使句 ≤60 tokens)' },
|
|
61
|
+
dontClause: { type: 'string', description: '反向约束(描述禁止的做法)' },
|
|
62
|
+
whenClause: { type: 'string', description: '触发场景(描述何时适用)' },
|
|
63
|
+
coreCode: { type: 'string', description: '精华代码骨架(3-8行,语法完整)' },
|
|
64
|
+
|
|
65
|
+
// ── 结构化字段 ──
|
|
66
|
+
headers: {
|
|
67
|
+
type: 'array',
|
|
68
|
+
items: { type: 'string' },
|
|
69
|
+
description: '完整 import/include 语句数组',
|
|
70
|
+
},
|
|
71
|
+
usageGuide: { type: 'string', description: '使用指南(何时/如何使用)' },
|
|
72
|
+
knowledgeType: {
|
|
73
|
+
type: 'string',
|
|
74
|
+
description: 'code-pattern / architecture / best-practice / code-standard / data-flow / solution 等',
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
// ── 推理 ──
|
|
78
|
+
reasoning: {
|
|
79
|
+
type: 'object',
|
|
80
|
+
description: '{ whyStandard: "原因", sources: ["file.ts"], confidence: 0.85 }',
|
|
81
|
+
properties: {
|
|
82
|
+
whyStandard: { type: 'string', description: '为什么这是标准做法(必填)' },
|
|
83
|
+
sources: { type: 'array', items: { type: 'string' }, description: '参考的文件路径数组(必填)' },
|
|
84
|
+
confidence: { type: 'number', description: '置信度 0.0-1.0' },
|
|
85
|
+
},
|
|
86
|
+
required: ['whyStandard', 'sources'],
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
// ── 可选 ──
|
|
90
|
+
complexity: { type: 'string', enum: ['beginner', 'intermediate', 'advanced'] },
|
|
91
|
+
scope: { type: 'string', enum: ['universal', 'project-specific', 'target-specific'] },
|
|
92
|
+
},
|
|
93
|
+
required: [
|
|
94
|
+
'title', 'language', 'content', 'kind',
|
|
95
|
+
'doClause', 'dontClause', 'whenClause', 'coreCode',
|
|
96
|
+
'category', 'trigger', 'description',
|
|
97
|
+
'headers', 'usageGuide', 'knowledgeType', 'reasoning',
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Handler — 本地验证 + 内存收集(不入库)
|
|
103
|
+
*
|
|
104
|
+
* 验证通过后返回 { status: 'collected', recipe: {...} },
|
|
105
|
+
* AgentFactory.scanKnowledge() 从 toolCalls 结果中提取 recipes。
|
|
106
|
+
*/
|
|
107
|
+
handler: async (params, _ctx) => {
|
|
108
|
+
// ── 基本验证 ──
|
|
109
|
+
const errors = [];
|
|
110
|
+
|
|
111
|
+
if (!params.title || params.title.trim().length === 0) {
|
|
112
|
+
errors.push('title 不能为空');
|
|
113
|
+
}
|
|
114
|
+
if (!params.content || typeof params.content !== 'object') {
|
|
115
|
+
errors.push('content 必须是对象');
|
|
116
|
+
} else if (!params.content.rationale) {
|
|
117
|
+
errors.push('content.rationale (设计原理) 是必填字段');
|
|
118
|
+
}
|
|
119
|
+
if (!params.reasoning || typeof params.reasoning !== 'object') {
|
|
120
|
+
errors.push('reasoning 必须是对象');
|
|
121
|
+
} else {
|
|
122
|
+
if (!params.reasoning.whyStandard) errors.push('reasoning.whyStandard 是必填字段');
|
|
123
|
+
if (!Array.isArray(params.reasoning.sources) || params.reasoning.sources.length === 0) {
|
|
124
|
+
errors.push('reasoning.sources 必须是非空数组');
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (!params.kind || !['rule', 'pattern', 'fact'].includes(params.kind)) {
|
|
128
|
+
errors.push('kind 必须是 rule / pattern / fact 之一');
|
|
129
|
+
}
|
|
130
|
+
if (!params.trigger || !params.trigger.startsWith('@')) {
|
|
131
|
+
errors.push('trigger 必须以 @ 开头');
|
|
132
|
+
}
|
|
133
|
+
if (!params.coreCode || params.coreCode.trim().length < 10) {
|
|
134
|
+
errors.push('coreCode 必须提供有意义的代码骨架(≥10字符)');
|
|
135
|
+
}
|
|
136
|
+
if (!params.doClause) {
|
|
137
|
+
errors.push('doClause (正向指令) 是必填字段');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (errors.length > 0) {
|
|
141
|
+
return {
|
|
142
|
+
status: 'rejected',
|
|
143
|
+
error: errors.join('\n'),
|
|
144
|
+
hint: '请根据错误信息调整内容后重新提交。',
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// ── 构建标准化 Recipe 对象 ──
|
|
149
|
+
const contentObj = params.content || {};
|
|
150
|
+
const reasoning = params.reasoning || {};
|
|
151
|
+
|
|
152
|
+
const recipe = {
|
|
153
|
+
title: params.title.trim(),
|
|
154
|
+
language: params.language || '',
|
|
155
|
+
description: params.description || '',
|
|
156
|
+
tags: params.tags || [],
|
|
157
|
+
content: {
|
|
158
|
+
pattern: contentObj.pattern || '',
|
|
159
|
+
markdown: contentObj.markdown || '',
|
|
160
|
+
rationale: contentObj.rationale || '',
|
|
161
|
+
},
|
|
162
|
+
kind: params.kind,
|
|
163
|
+
category: params.category || 'Utility',
|
|
164
|
+
trigger: params.trigger,
|
|
165
|
+
doClause: params.doClause || '',
|
|
166
|
+
dontClause: params.dontClause || '',
|
|
167
|
+
whenClause: params.whenClause || '',
|
|
168
|
+
coreCode: params.coreCode || '',
|
|
169
|
+
headers: params.headers || [],
|
|
170
|
+
usageGuide: params.usageGuide || '',
|
|
171
|
+
knowledgeType: params.knowledgeType || 'code-pattern',
|
|
172
|
+
reasoning: {
|
|
173
|
+
whyStandard: reasoning.whyStandard || '',
|
|
174
|
+
sources: reasoning.sources || [],
|
|
175
|
+
confidence: reasoning.confidence ?? 0.8,
|
|
176
|
+
},
|
|
177
|
+
complexity: params.complexity || 'intermediate',
|
|
178
|
+
scope: params.scope || 'project-specific',
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
return {
|
|
182
|
+
status: 'collected',
|
|
183
|
+
title: recipe.title,
|
|
184
|
+
recipe,
|
|
185
|
+
};
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
export default collectScanRecipe;
|