autosnippet 3.2.8 → 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.
Files changed (113) hide show
  1. package/bin/cli.js +6 -5
  2. package/dashboard/dist/assets/index-BTAsOZv2.js +128 -0
  3. package/dashboard/dist/assets/index-C_72Ct98.css +1 -0
  4. package/dashboard/dist/index.html +2 -2
  5. package/lib/cli/AiScanService.js +23 -26
  6. package/lib/cli/SetupService.js +1 -1
  7. package/lib/core/AstAnalyzer.js +1 -1
  8. package/lib/core/discovery/index.js +2 -2
  9. package/lib/external/ai/AiProvider.js +66 -172
  10. package/lib/external/ai/providers/GoogleGeminiProvider.js +23 -1
  11. package/lib/external/mcp/handlers/bootstrap/BootstrapSession.js +1 -1
  12. package/lib/external/mcp/handlers/bootstrap/ExternalSubmissionTracker.js +3 -3
  13. package/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.js +1 -1
  14. package/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.js +1 -1
  15. package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-context.js +8 -8
  16. package/lib/external/mcp/handlers/bootstrap/pipeline/noAiFallback.js +1 -1
  17. package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +287 -204
  18. package/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +7 -6
  19. package/lib/external/mcp/handlers/bootstrap/shared/dimension-sop.js +1 -1
  20. package/lib/external/mcp/handlers/bootstrap-internal.js +2 -2
  21. package/lib/external/mcp/handlers/dimension-complete-external.js +6 -6
  22. package/lib/http/HttpServer.js +1 -1
  23. package/lib/http/middleware/requestLogger.js +1 -0
  24. package/lib/http/routes/ai.js +240 -35
  25. package/lib/http/routes/candidates.js +2 -3
  26. package/lib/http/routes/extract.js +13 -11
  27. package/lib/http/routes/modules.js +2 -2
  28. package/lib/http/routes/recipes.js +9 -5
  29. package/lib/http/routes/remote.js +134 -255
  30. package/lib/http/routes/violations.js +0 -54
  31. package/lib/http/utils/sse-sessions.js +1 -1
  32. package/lib/infrastructure/logging/Logger.js +5 -4
  33. package/lib/infrastructure/monitoring/PerformanceMonitor.js +3 -2
  34. package/lib/injection/ServiceContainer.js +64 -17
  35. package/lib/platform/ScreenCaptureService.js +177 -0
  36. package/lib/platform/ios/routes/spm.js +2 -2
  37. package/lib/service/agent/AgentEventBus.js +207 -0
  38. package/lib/service/agent/AgentFactory.js +490 -0
  39. package/lib/service/agent/AgentMessage.js +240 -0
  40. package/lib/service/agent/AgentRouter.js +228 -0
  41. package/lib/service/agent/AgentRuntime.js +1016 -0
  42. package/lib/service/agent/AgentState.js +217 -0
  43. package/lib/service/agent/IntentClassifier.js +331 -0
  44. package/lib/service/agent/LarkTransport.js +389 -0
  45. package/lib/service/agent/capabilities.js +408 -0
  46. package/lib/service/{chat → agent/context}/ContextWindow.js +37 -12
  47. package/lib/service/{chat → agent/context}/ExplorationTracker.js +25 -14
  48. package/lib/service/{chat → agent/core}/ChatAgentPrompts.js +1 -1
  49. package/lib/service/agent/core/LoopContext.js +170 -0
  50. package/lib/service/agent/core/MessageAdapter.js +223 -0
  51. package/lib/service/agent/core/ToolExecutionPipeline.js +376 -0
  52. package/lib/service/{chat → agent/domain}/ChatAgentTasks.js +19 -98
  53. package/lib/service/{chat → agent/domain}/EpisodicConsolidator.js +7 -7
  54. package/lib/service/{chat → agent/domain}/EvidenceCollector.js +4 -2
  55. package/lib/service/{chat/AnalystAgent.js → agent/domain/insight-analyst.js} +37 -172
  56. package/lib/service/{chat/HandoffProtocol.js → agent/domain/insight-gate.js} +85 -135
  57. package/lib/service/agent/domain/insight-producer.js +267 -0
  58. package/lib/service/agent/domain/scan-prompts.js +105 -0
  59. package/lib/service/agent/forced-summary.js +266 -0
  60. package/lib/service/agent/index.js +91 -0
  61. package/lib/service/{chat → agent}/memory/MemoryCoordinator.js +7 -7
  62. package/lib/service/{chat/ProjectSemanticMemory.js → agent/memory/PersistentMemory.js} +359 -89
  63. package/lib/service/{chat → agent}/memory/SessionStore.js +1 -1
  64. package/lib/service/{chat → agent}/memory/index.js +1 -1
  65. package/lib/service/agent/policies.js +442 -0
  66. package/lib/service/agent/presets.js +303 -0
  67. package/lib/service/agent/strategies.js +717 -0
  68. package/lib/service/{chat → agent/tools}/ToolRegistry.js +3 -3
  69. package/lib/service/agent/tools/ai-analysis.js +75 -0
  70. package/lib/service/{chat → agent}/tools/composite.js +2 -1
  71. package/lib/service/{chat → agent}/tools/guard.js +1 -121
  72. package/lib/service/{chat → agent}/tools/index.js +27 -21
  73. package/lib/service/{chat → agent}/tools/infrastructure.js +1 -1
  74. package/lib/service/agent/tools/knowledge-graph.js +112 -0
  75. package/lib/service/agent/tools/scan-recipe.js +189 -0
  76. package/lib/service/agent/tools/system-interaction.js +476 -0
  77. package/lib/service/automation/DirectiveDetector.js +0 -1
  78. package/lib/service/automation/FileWatcher.js +0 -8
  79. package/lib/service/automation/handlers/CreateHandler.js +7 -3
  80. package/lib/service/automation/handlers/DraftHandler.js +7 -6
  81. package/lib/service/module/ModuleService.js +40 -73
  82. package/lib/service/skills/SignalCollector.js +26 -19
  83. package/lib/service/snippet/codecs/VSCodeCodec.js +1 -1
  84. package/lib/shared/FieldSpec.js +1 -1
  85. package/lib/shared/StyleGuide.js +1 -1
  86. package/package.json +4 -1
  87. package/resources/native-ui/screenshot.swift +228 -0
  88. package/dashboard/dist/assets/index-D5jiDBQG.css +0 -1
  89. package/dashboard/dist/assets/index-e5OKj-Ni.js +0 -128
  90. package/lib/core/discovery/SpmDiscoverer.js +0 -5
  91. package/lib/external/mcp/handlers/bootstrap/pipeline/EpisodicMemory.js +0 -750
  92. package/lib/external/mcp/handlers/bootstrap/pipeline/ToolResultCache.js +0 -277
  93. package/lib/http/routes/spm.js +0 -5
  94. package/lib/infrastructure/external/XcodeAutomation.js +0 -15
  95. package/lib/service/chat/ChatAgent.js +0 -1602
  96. package/lib/service/chat/Memory.js +0 -161
  97. package/lib/service/chat/ProducerAgent.js +0 -431
  98. package/lib/service/chat/ReasoningTrace.js +0 -523
  99. package/lib/service/chat/TaskPipeline.js +0 -357
  100. package/lib/service/chat/WorkingMemory.js +0 -359
  101. package/lib/service/chat/memory/PersistentMemory.js +0 -450
  102. package/lib/service/chat/tools/ai-analysis.js +0 -267
  103. package/lib/service/chat/tools/knowledge-graph.js +0 -234
  104. package/lib/service/chat/tools.js +0 -18
  105. package/lib/service/snippet/PlaceholderConverter.js +0 -5
  106. package/lib/service/snippet/codecs/XcodeCodec.js +0 -5
  107. /package/lib/service/{chat → agent}/ConversationStore.js +0 -0
  108. /package/lib/service/{chat → agent}/memory/ActiveContext.js +0 -0
  109. /package/lib/service/{chat → agent}/tools/_shared.js +0 -0
  110. /package/lib/service/{chat → agent}/tools/ast-graph.js +0 -0
  111. /package/lib/service/{chat → agent}/tools/lifecycle.js +0 -0
  112. /package/lib/service/{chat → agent}/tools/project-access.js +0 -0
  113. /package/lib/service/{chat → agent}/tools/query.js +0 -0
@@ -1,16 +1,16 @@
1
1
  /**
2
2
  * ToolRegistry — 统一工具注册表
3
3
  *
4
- * 管理 ChatAgent 可调用的所有工具定义。
4
+ * 管理 Agent 可调用的所有工具定义。
5
5
  * 每个工具包含: name, description, parameters(JSON Schema), handler
6
6
  *
7
7
  * 设计原则:
8
8
  * - 所有 AI 能力均封装为 Tool,不再散落在各处
9
9
  * - Tool handler 仅做参数整理 + 调用已有 Service,不含业务逻辑
10
- * - 支持 programmatic 直接调用 (executeTool) Agent ReAct 循环调用
10
+ * - 支持 Agent ReAct 循环调用(通过 LLM 推理决定工具调用)
11
11
  */
12
12
 
13
- import Logger from '../../infrastructure/logging/Logger.js';
13
+ import Logger from '../../../infrastructure/logging/Logger.js';
14
14
 
15
15
  /**
16
16
  * AI 模型常见的参数命名变体 → schema 标准名映射
@@ -0,0 +1,75 @@
1
+ /**
2
+ * ai-analysis.js — AI 分析类工具 (2)
3
+ *
4
+ * 9. enrich_candidate 结构补齐
5
+ * 9b. refine_bootstrap_candidates 内容润色
6
+ *
7
+ * 注意: summarize_code / extract_recipes 已删除。
8
+ * 代码摘要和 Recipe 提取由 Agent LLM 直接推理完成,不再需要专用工具。
9
+ */
10
+
11
+ // ────────────────────────────────────────────────────────────
12
+ // 9. enrich_candidate
13
+ // ────────────────────────────────────────────────────────────
14
+ export const enrichCandidate = {
15
+ name: 'enrich_candidate',
16
+ description:
17
+ '① 结构补齐 — 自动填充缺失的结构性语义字段(rationale/knowledgeType/complexity/scope/steps/constraints)。批量处理,只填空不覆盖。建议在 refine_bootstrap_candidates 之前执行。',
18
+ parameters: {
19
+ type: 'object',
20
+ properties: {
21
+ candidateIds: {
22
+ type: 'array',
23
+ items: { type: 'string' },
24
+ description: '候选 ID 列表 (最多 20 个)',
25
+ },
26
+ },
27
+ required: ['candidateIds'],
28
+ },
29
+ handler: async (params, ctx) => {
30
+ if (!ctx.aiProvider) {
31
+ return { error: 'AI provider not available' };
32
+ }
33
+ // V3: 使用 MCP handler enrichCandidates 的逻辑
34
+ const { enrichCandidates: enrichFn } = await import('../../../external/mcp/handlers/candidate.js');
35
+ const result = await enrichFn(ctx, { candidateIds: params.candidateIds });
36
+ return result?.data || result;
37
+ },
38
+ };
39
+
40
+ // ────────────────────────────────────────────────────────────
41
+ // 9b. refine_bootstrap_candidates (Phase 6)
42
+ // ────────────────────────────────────────────────────────────
43
+ export const refineBootstrapCandidates = {
44
+ name: 'refine_bootstrap_candidates',
45
+ description:
46
+ '② 内容润色 — 逐条精炼 Bootstrap 候选的内容质量:改善 summary、补充架构 insight、推断 relations 关联、调整 confidence、丰富 tags。建议在 enrich_candidate 之后执行。',
47
+ parameters: {
48
+ type: 'object',
49
+ properties: {
50
+ candidateIds: {
51
+ type: 'array',
52
+ items: { type: 'string' },
53
+ description: '指定候选 ID 列表(可选,默认全部 bootstrap 候选)',
54
+ },
55
+ userPrompt: {
56
+ type: 'string',
57
+ description: '用户自定义润色提示词,指导 AI 润色方向(如"侧重描述线程安全注意事项")',
58
+ },
59
+ dryRun: { type: 'boolean', description: '仅预览 AI 润色结果,不写入数据库' },
60
+ },
61
+ },
62
+ handler: async (params, ctx) => {
63
+ if (!ctx.aiProvider) {
64
+ return { error: 'AI provider not available' };
65
+ }
66
+ // V3: 委托给 bootstrap handler 的 refine 逻辑
67
+ const { bootstrapRefine } = await import('../../../external/mcp/handlers/bootstrap-internal.js');
68
+ const result = await bootstrapRefine(ctx, {
69
+ candidateIds: params.candidateIds,
70
+ userPrompt: params.userPrompt,
71
+ dryRun: params.dryRun,
72
+ });
73
+ return result?.data || result;
74
+ },
75
+ };
@@ -160,7 +160,7 @@ export const submitWithCheck = {
160
160
  content: {
161
161
  type: 'object',
162
162
  description:
163
- '{ markdown: "项目特写 Markdown", pattern: "核心代码 3-8 行,必须语法完整(括号配对、不能以 } 开头或 { 结尾)" }',
163
+ '{ markdown: "项目特写 Markdown (≥200字符,含代码块)", rationale: "设计原理说明 (必填)", pattern: "核心代码 3-8 行,语法完整" }',
164
164
  },
165
165
  title: { type: 'string', description: '候选标题' },
166
166
  description: { type: 'string', description: '中文简述 ≤80 字' },
@@ -234,6 +234,7 @@ export const submitWithCheck = {
234
234
  ctx.logger?.info(`[submit_with_check] ✗ validator rejected: ${validResult.errors.join('; ')}`);
235
235
  return {
236
236
  submitted: false,
237
+ status: 'rejected',
237
238
  reason: 'validation_failed',
238
239
  errors: validResult.errors,
239
240
  warnings: validResult.warnings,
@@ -1,12 +1,10 @@
1
1
  /**
2
- * guard.js — Guard 安全类工具 (6)
2
+ * guard.js — Guard 安全类工具 (4)
3
3
  *
4
4
  * 7b. list_guard_rules 列出 Guard 规则
5
5
  * 8b. get_recommendations 获取推荐 Recipe
6
- * 12. ai_translate AI 翻译
7
6
  * 13. guard_check_code Guard 检查代码
8
7
  * 14. query_violations 查询违规历史
9
- * 15. generate_guard_rule AI 生成 Guard 规则
10
8
  */
11
9
 
12
10
  // ────────────────────────────────────────────────────────────
@@ -75,46 +73,6 @@ export const getRecommendations = {
75
73
  },
76
74
  };
77
75
 
78
- // ────────────────────────────────────────────────────────────
79
- // 12. ai_translate
80
- // ────────────────────────────────────────────────────────────
81
- export const aiTranslate = {
82
- name: 'ai_translate',
83
- description: 'AI 翻译 — 将中文 summary/usageGuide 翻译为英文。',
84
- parameters: {
85
- type: 'object',
86
- properties: {
87
- summary: { type: 'string', description: '中文摘要' },
88
- usageGuide: { type: 'string', description: '中文使用指南' },
89
- },
90
- },
91
- handler: async (params, ctx) => {
92
- if (!ctx.aiProvider) {
93
- return { error: 'AI provider not available' };
94
- }
95
- const { summary, usageGuide } = params;
96
- if (!summary && !usageGuide) {
97
- return { summaryEn: '', usageGuideEn: '' };
98
- }
99
-
100
- const systemPrompt =
101
- 'You are a technical translator. Translate from Chinese to English. Keep technical terms unchanged. Return ONLY valid JSON: { "summaryEn": "...", "usageGuideEn": "..." }.';
102
- const parts = [];
103
- if (summary) {
104
- parts.push(`summary: ${summary}`);
105
- }
106
- if (usageGuide) {
107
- parts.push(`usageGuide: ${usageGuide}`);
108
- }
109
-
110
- const parsed = await ctx.aiProvider.chatWithStructuredOutput(parts.join('\n'), {
111
- systemPrompt,
112
- temperature: 0.2,
113
- });
114
- return parsed || { summaryEn: summary || '', usageGuideEn: usageGuide || '' };
115
- },
116
- };
117
-
118
76
  // ────────────────────────────────────────────────────────────
119
77
  // 13. guard_check_code
120
78
  // ────────────────────────────────────────────────────────────
@@ -184,82 +142,4 @@ export const queryViolations = {
184
142
  },
185
143
  };
186
144
 
187
- // ────────────────────────────────────────────────────────────
188
- // 15. generate_guard_rule
189
- // ────────────────────────────────────────────────────────────
190
- export const generateGuardRule = {
191
- name: 'generate_guard_rule',
192
- description: 'AI 生成 Guard 规则 — 描述你想阻止的代码模式,AI 自动生成正则表达式和规则定义。',
193
- parameters: {
194
- type: 'object',
195
- properties: {
196
- description: {
197
- type: 'string',
198
- description: '规则描述(例如 "禁止在主线程使用同步网络请求")',
199
- },
200
- language: { type: 'string', description: '目标语言 (swift/objc 等)' },
201
- severity: { type: 'string', description: '严重程度 (error/warning/info),默认 warning' },
202
- autoCreate: { type: 'boolean', description: '是否自动创建到数据库,默认 false' },
203
- },
204
- required: ['description'],
205
- },
206
- handler: async (params, ctx) => {
207
- if (!ctx.aiProvider) {
208
- return { error: 'AI provider not available' };
209
- }
210
- const { description, language = 'swift', severity = 'warning', autoCreate = false } = params;
211
-
212
- const prompt = `Generate a Guard rule for this requirement:
213
- Description: ${description}
214
- Language: ${language}
215
- Severity: ${severity}
216
-
217
- Return ONLY valid JSON:
218
- {
219
- "name": "rule-name-kebab-case",
220
- "description": "One-line description in English",
221
- "description_cn": "一行中文描述",
222
- "pattern": "regex pattern for matching the problematic code",
223
- "languages": ["${language}"],
224
- "severity": "${severity}",
225
- "testCases": {
226
- "shouldMatch": ["code example that should trigger"],
227
- "shouldNotMatch": ["code example that should NOT trigger"]
228
- }
229
- }`;
230
-
231
- const rule = await ctx.aiProvider.chatWithStructuredOutput(prompt, { temperature: 0.2 });
232
- if (!rule) {
233
- return { error: 'Failed to parse AI response' };
234
- }
235
145
 
236
- // 验证正则表达式
237
- try {
238
- new RegExp(rule.pattern);
239
- } catch (e) {
240
- return { error: `Invalid regex pattern: ${e.message}`, rule };
241
- }
242
-
243
- // 自动创建
244
- if (autoCreate && rule.name && rule.pattern) {
245
- try {
246
- const guardService = ctx.container.get('guardService');
247
- const created = await guardService.createRule(
248
- {
249
- name: rule.name,
250
- description: rule.description || description,
251
- pattern: rule.pattern,
252
- languages: rule.languages || [language],
253
- severity: rule.severity || severity,
254
- },
255
- { userId: 'agent' }
256
- );
257
- return { rule, created: true, recipeId: created.id };
258
- } catch (err) {
259
- return { rule, created: false, error: err.message };
260
- }
261
- }
262
-
263
- return { rule, created: false };
264
- },
265
- };
@@ -4,12 +4,10 @@
4
4
  * 从各子模块导入所有工具,按原始顺序组装 ALL_TOOLS 数组并导出。
5
5
  */
6
6
 
7
- // ── AI 分析类 (4) ──
7
+ // ── AI 分析类 (2) ──
8
8
  import {
9
9
  enrichCandidate,
10
- extractRecipes,
11
10
  refineBootstrapCandidates,
12
- summarizeCode,
13
11
  } from './ai-analysis.js';
14
12
  // ── AST 结构化分析 + Agent Memory (11) ──
15
13
  import {
@@ -35,10 +33,8 @@ import {
35
33
  submitWithCheck,
36
34
  } from './composite.js';
37
35
 
38
- // ── Guard 安全类 (6) ──
36
+ // ── Guard 安全类 (4) ──
39
37
  import {
40
- aiTranslate,
41
- generateGuardRule,
42
38
  getRecommendations,
43
39
  guardCheckCode,
44
40
  listGuardRules,
@@ -54,8 +50,16 @@ import {
54
50
  rebuildIndex,
55
51
  suggestSkills,
56
52
  } from './infrastructure.js';
57
- // ── 知识图谱类 (3) ──
58
- import { addGraphEdge, checkDuplicate, discoverRelations } from './knowledge-graph.js';
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';
59
63
  // ── 生命周期操作类 (11) ──
60
64
  import {
61
65
  approveCandidate,
@@ -104,20 +108,15 @@ export {
104
108
  searchKnowledge,
105
109
  getRelatedRecipes,
106
110
  // AI 分析类
107
- summarizeCode,
108
- extractRecipes,
109
111
  enrichCandidate,
110
112
  refineBootstrapCandidates,
111
113
  // Guard 安全类
112
114
  listGuardRules,
113
115
  getRecommendations,
114
- aiTranslate,
115
116
  guardCheckCode,
116
117
  queryViolations,
117
- generateGuardRule,
118
118
  // 知识图谱类
119
119
  checkDuplicate,
120
- discoverRelations,
121
120
  addGraphEdge,
122
121
  // 生命周期操作类
123
122
  submitCandidate,
@@ -161,6 +160,12 @@ export {
161
160
  queryCodeGraph,
162
161
  // 调用图查询 (Phase 5)
163
162
  queryCallGraph,
163
+ // 扫描 Recipe 收集
164
+ collectScanRecipe,
165
+ // 系统交互类
166
+ runSafeCommand,
167
+ writeProjectFile,
168
+ getEnvironmentInfo,
164
169
  };
165
170
 
166
171
  // ── ALL_TOOLS 数组(与原始 tools.js 顺序一致)──
@@ -180,16 +185,12 @@ export const ALL_TOOLS = [
180
185
  getRelatedRecipes,
181
186
  listGuardRules,
182
187
  getRecommendations,
183
- // AI 分析类 (5)
184
- summarizeCode,
185
- extractRecipes,
188
+ // AI 分析类 (2)
186
189
  enrichCandidate,
187
190
  refineBootstrapCandidates,
188
- aiTranslate,
189
- // Guard 安全类 (3)
191
+ // Guard 安全类 (2)
190
192
  guardCheckCode,
191
193
  queryViolations,
192
- generateGuardRule,
193
194
  // 生命周期操作类 (7)
194
195
  submitCandidate,
195
196
  saveDocument,
@@ -203,9 +204,8 @@ export const ALL_TOOLS = [
203
204
  qualityScore,
204
205
  validateCandidate,
205
206
  getFeedbackStats,
206
- // 知识图谱类 (3)
207
+ // 知识图谱类 (2)
207
208
  checkDuplicate,
208
- discoverRelations,
209
209
  addGraphEdge,
210
210
  // 基础设施类 (3)
211
211
  graphImpactAnalysis,
@@ -239,6 +239,12 @@ export const ALL_TOOLS = [
239
239
  queryCodeGraph,
240
240
  // 调用图查询 (1) — Phase 5
241
241
  queryCallGraph,
242
+ // 系统交互 (3) — Agent 终端/文件写入/环境探测
243
+ runSafeCommand,
244
+ writeProjectFile,
245
+ getEnvironmentInfo,
246
+ // 扫描 Recipe 收集 (1) — scanKnowledge produce 阶段专用
247
+ collectScanRecipe,
242
248
  ];
243
249
 
244
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
- // 根据 ChatAgent 的 source 推断 createdBy
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 {
@@ -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
+ };