autosnippet 3.2.8 → 3.2.10

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 (114) 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/cli/deploy/FileManifest.js +1 -1
  8. package/lib/core/AstAnalyzer.js +1 -1
  9. package/lib/core/discovery/index.js +2 -2
  10. package/lib/external/ai/AiProvider.js +66 -172
  11. package/lib/external/ai/providers/GoogleGeminiProvider.js +29 -5
  12. package/lib/external/mcp/handlers/bootstrap/BootstrapSession.js +1 -1
  13. package/lib/external/mcp/handlers/bootstrap/ExternalSubmissionTracker.js +3 -3
  14. package/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.js +1 -1
  15. package/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.js +1 -1
  16. package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-context.js +8 -8
  17. package/lib/external/mcp/handlers/bootstrap/pipeline/noAiFallback.js +1 -1
  18. package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +291 -204
  19. package/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +7 -6
  20. package/lib/external/mcp/handlers/bootstrap/shared/dimension-sop.js +1 -1
  21. package/lib/external/mcp/handlers/bootstrap-internal.js +2 -2
  22. package/lib/external/mcp/handlers/dimension-complete-external.js +6 -6
  23. package/lib/http/HttpServer.js +1 -1
  24. package/lib/http/middleware/requestLogger.js +1 -0
  25. package/lib/http/routes/ai.js +240 -35
  26. package/lib/http/routes/candidates.js +2 -3
  27. package/lib/http/routes/extract.js +13 -11
  28. package/lib/http/routes/modules.js +2 -2
  29. package/lib/http/routes/recipes.js +5 -5
  30. package/lib/http/routes/remote.js +134 -255
  31. package/lib/http/routes/violations.js +0 -54
  32. package/lib/http/utils/sse-sessions.js +1 -1
  33. package/lib/infrastructure/logging/Logger.js +5 -4
  34. package/lib/infrastructure/monitoring/PerformanceMonitor.js +3 -2
  35. package/lib/injection/ServiceContainer.js +64 -17
  36. package/lib/platform/ScreenCaptureService.js +177 -0
  37. package/lib/platform/ios/routes/spm.js +2 -2
  38. package/lib/service/agent/AgentEventBus.js +207 -0
  39. package/lib/service/agent/AgentFactory.js +535 -0
  40. package/lib/service/agent/AgentMessage.js +240 -0
  41. package/lib/service/agent/AgentRouter.js +228 -0
  42. package/lib/service/agent/AgentRuntime.js +1056 -0
  43. package/lib/service/agent/AgentState.js +217 -0
  44. package/lib/service/agent/IntentClassifier.js +331 -0
  45. package/lib/service/agent/LarkTransport.js +389 -0
  46. package/lib/service/agent/capabilities.js +409 -0
  47. package/lib/service/{chat → agent/context}/ContextWindow.js +37 -12
  48. package/lib/service/{chat → agent/context}/ExplorationTracker.js +112 -33
  49. package/lib/service/{chat → agent/core}/ChatAgentPrompts.js +5 -3
  50. package/lib/service/agent/core/LoopContext.js +170 -0
  51. package/lib/service/agent/core/MessageAdapter.js +223 -0
  52. package/lib/service/agent/core/ToolExecutionPipeline.js +376 -0
  53. package/lib/service/{chat → agent/domain}/ChatAgentTasks.js +15 -98
  54. package/lib/service/{chat → agent/domain}/EpisodicConsolidator.js +7 -7
  55. package/lib/service/{chat → agent/domain}/EvidenceCollector.js +4 -2
  56. package/lib/service/{chat/AnalystAgent.js → agent/domain/insight-analyst.js} +37 -172
  57. package/lib/service/{chat/HandoffProtocol.js → agent/domain/insight-gate.js} +85 -135
  58. package/lib/service/agent/domain/insight-producer.js +270 -0
  59. package/lib/service/agent/domain/scan-prompts.js +444 -0
  60. package/lib/service/agent/forced-summary.js +266 -0
  61. package/lib/service/agent/index.js +91 -0
  62. package/lib/service/{chat → agent}/memory/ActiveContext.js +29 -1
  63. package/lib/service/{chat → agent}/memory/MemoryCoordinator.js +7 -7
  64. package/lib/service/{chat/ProjectSemanticMemory.js → agent/memory/PersistentMemory.js} +359 -89
  65. package/lib/service/{chat → agent}/memory/SessionStore.js +1 -1
  66. package/lib/service/{chat → agent}/memory/index.js +1 -1
  67. package/lib/service/agent/policies.js +442 -0
  68. package/lib/service/agent/presets.js +305 -0
  69. package/lib/service/agent/strategies.js +756 -0
  70. package/lib/service/{chat → agent/tools}/ToolRegistry.js +3 -3
  71. package/lib/service/agent/tools/ai-analysis.js +75 -0
  72. package/lib/service/{chat → agent}/tools/composite.js +2 -1
  73. package/lib/service/{chat → agent}/tools/guard.js +1 -121
  74. package/lib/service/{chat → agent}/tools/index.js +27 -21
  75. package/lib/service/{chat → agent}/tools/infrastructure.js +1 -1
  76. package/lib/service/agent/tools/knowledge-graph.js +112 -0
  77. package/lib/service/agent/tools/scan-recipe.js +189 -0
  78. package/lib/service/agent/tools/system-interaction.js +476 -0
  79. package/lib/service/automation/DirectiveDetector.js +0 -1
  80. package/lib/service/automation/FileWatcher.js +0 -8
  81. package/lib/service/automation/handlers/CreateHandler.js +7 -3
  82. package/lib/service/automation/handlers/DraftHandler.js +7 -6
  83. package/lib/service/module/ModuleService.js +40 -73
  84. package/lib/service/skills/SignalCollector.js +26 -19
  85. package/lib/service/snippet/codecs/VSCodeCodec.js +1 -1
  86. package/lib/shared/FieldSpec.js +1 -1
  87. package/lib/shared/StyleGuide.js +1 -1
  88. package/package.json +4 -1
  89. package/resources/native-ui/screenshot.swift +228 -0
  90. package/dashboard/dist/assets/index-D5jiDBQG.css +0 -1
  91. package/dashboard/dist/assets/index-e5OKj-Ni.js +0 -128
  92. package/lib/core/discovery/SpmDiscoverer.js +0 -5
  93. package/lib/external/mcp/handlers/bootstrap/pipeline/EpisodicMemory.js +0 -750
  94. package/lib/external/mcp/handlers/bootstrap/pipeline/ToolResultCache.js +0 -277
  95. package/lib/http/routes/spm.js +0 -5
  96. package/lib/infrastructure/external/XcodeAutomation.js +0 -15
  97. package/lib/service/chat/ChatAgent.js +0 -1602
  98. package/lib/service/chat/Memory.js +0 -161
  99. package/lib/service/chat/ProducerAgent.js +0 -431
  100. package/lib/service/chat/ReasoningTrace.js +0 -523
  101. package/lib/service/chat/TaskPipeline.js +0 -357
  102. package/lib/service/chat/WorkingMemory.js +0 -359
  103. package/lib/service/chat/memory/PersistentMemory.js +0 -450
  104. package/lib/service/chat/tools/ai-analysis.js +0 -267
  105. package/lib/service/chat/tools/knowledge-graph.js +0 -234
  106. package/lib/service/chat/tools.js +0 -18
  107. package/lib/service/snippet/PlaceholderConverter.js +0 -5
  108. package/lib/service/snippet/codecs/XcodeCodec.js +0 -5
  109. /package/lib/service/{chat → agent}/ConversationStore.js +0 -0
  110. /package/lib/service/{chat → agent}/tools/_shared.js +0 -0
  111. /package/lib/service/{chat → agent}/tools/ast-graph.js +0 -0
  112. /package/lib/service/{chat → agent}/tools/lifecycle.js +0 -0
  113. /package/lib/service/{chat → agent}/tools/project-access.js +0 -0
  114. /package/lib/service/{chat → agent}/tools/query.js +0 -0
@@ -1,267 +0,0 @@
1
- /**
2
- * ai-analysis.js — AI 分析类工具 (4)
3
- *
4
- * 7. summarize_code AI 代码摘要
5
- * 8. extract_recipes 从源码批量提取 Recipe
6
- * 9. enrich_candidate 结构补齐
7
- * 9b. refine_bootstrap_candidates 内容润色
8
- */
9
-
10
- // ────────────────────────────────────────────────────────────
11
- // 7. summarize_code
12
- // ────────────────────────────────────────────────────────────
13
- export const summarizeCode = {
14
- name: 'summarize_code',
15
- description: 'AI 代码摘要 — 分析代码片段并生成结构化摘要(包含功能描述、关键 API、使用建议)。',
16
- parameters: {
17
- type: 'object',
18
- properties: {
19
- code: { type: 'string', description: '代码内容' },
20
- language: { type: 'string', description: '编程语言' },
21
- },
22
- required: ['code'],
23
- },
24
- handler: async (params, ctx) => {
25
- if (!ctx.aiProvider) {
26
- return { error: 'AI provider not available' };
27
- }
28
- return ctx.aiProvider.summarize(params.code, params.language);
29
- },
30
- };
31
-
32
- // ────────────────────────────────────────────────────────────
33
- // 8. extract_recipes
34
- // ────────────────────────────────────────────────────────────
35
- export const extractRecipes = {
36
- name: 'extract_recipes',
37
- description:
38
- '从源码文件中批量提取可复用的 Recipe 结构(代码标准、设计模式、最佳实践)。支持自动 provider fallback。',
39
- parameters: {
40
- type: 'object',
41
- properties: {
42
- targetName: { type: 'string', description: 'SPM Target / 模块名称' },
43
- files: {
44
- type: 'array',
45
- items: {
46
- type: 'object',
47
- properties: { name: { type: 'string' }, content: { type: 'string' } },
48
- },
49
- description: '文件数组 [{name, content}]',
50
- },
51
- },
52
- required: ['targetName', 'files'],
53
- },
54
- handler: async (params, ctx) => {
55
- if (!ctx.aiProvider) {
56
- return { error: 'AI provider not available' };
57
- }
58
- const { targetName, files, comprehensive } = params;
59
-
60
- // AST 代码结构分析(如可用),注入到 AI 提取 prompt
61
- let astContext = null;
62
- try {
63
- const { analyzeProject, generateContextForAgent, isAvailable } = await import(
64
- '../../../core/AstAnalyzer.js'
65
- );
66
- if (isAvailable()) {
67
- const sourceFiles = files
68
- .filter((f) => /\.(m|mm|h|swift|js|ts|jsx|tsx)$/.test(f.name || ''))
69
- .map((f) => ({ path: f.name, source: f.content }));
70
- if (sourceFiles.length > 0) {
71
- const langProfile2 = ctx.aiProvider._detectLanguageProfile?.(files);
72
- const lang = langProfile2?.primaryLanguage === 'swift' ? 'swift' : 'objc';
73
- const summary = analyzeProject(sourceFiles, lang);
74
- astContext = generateContextForAgent(summary);
75
- }
76
- }
77
- } catch {
78
- /* AST not available, proceed without */
79
- }
80
-
81
- const extractOpts = {};
82
- if (astContext) {
83
- extractOpts.astContext = astContext;
84
- }
85
- if (comprehensive) {
86
- extractOpts.comprehensive = true;
87
- }
88
- // 传递用户语言偏好,让 AI 输出匹配用户语言
89
- if (ctx.lang && ctx.lang !== 'en') {
90
- extractOpts.lang = ctx.lang;
91
- }
92
-
93
- // 首选:使用当前 aiProvider
94
- let recipes;
95
- let fallbackUsed;
96
- try {
97
- recipes = await ctx.aiProvider.extractRecipes(targetName, files, extractOpts);
98
- } catch (primaryErr) {
99
- // 尝试 fallback(如果 AiFactory 可用)
100
- let recovered = false;
101
- try {
102
- const aiFactory = ctx.container?.singletons?._aiFactory;
103
- if (aiFactory?.isGeoOrProviderError?.(primaryErr)) {
104
- const currentProvider = (process.env.ASD_AI_PROVIDER || 'google').toLowerCase();
105
- const fallbacks = aiFactory.getAvailableFallbacks(currentProvider);
106
- for (const fbName of fallbacks) {
107
- try {
108
- const fbProvider = aiFactory.createProvider({ provider: fbName });
109
- recipes = await fbProvider.extractRecipes(targetName, files, extractOpts);
110
- fallbackUsed = fbName;
111
- recovered = true;
112
- break;
113
- } catch {
114
- /* next fallback */
115
- }
116
- }
117
- }
118
- } catch {
119
- /* AiFactory not available */
120
- }
121
- if (!recovered) {
122
- throw primaryErr;
123
- }
124
- }
125
-
126
- if (!Array.isArray(recipes)) {
127
- recipes = [];
128
- }
129
- if (recipes.length === 0) {
130
- ctx.logger?.warn?.(
131
- `[extract_recipes] AI returned 0 recipes for ${targetName} (${files.length} files)`
132
- );
133
- }
134
-
135
- // ── V3 直透:AI 已输出完整 V3 结构,仅做来源标记 + 程序化评分/标签 ──
136
- let qualityScorer = null;
137
- let recipeExtractor = null;
138
- try {
139
- qualityScorer = ctx.container?.get?.('qualityScorer');
140
- } catch {
141
- /* not available */
142
- }
143
- try {
144
- recipeExtractor = ctx.container?.get?.('recipeExtractor');
145
- } catch {
146
- /* not available */
147
- }
148
-
149
- for (const recipe of recipes) {
150
- // 来源 & 生命周期(非 AI 职责)
151
- recipe.source = recipe.source || 'ai-scan';
152
- recipe.lifecycle = recipe.lifecycle || 'pending';
153
-
154
- // RecipeExtractor 语义标签增强(程序化补充,不替代 AI tags)
155
- const codeText = recipe.content?.pattern || '';
156
- if (recipeExtractor && codeText) {
157
- try {
158
- const extracted = recipeExtractor.extractFromContent(
159
- codeText,
160
- `${recipe.title || 'unknown'}.${recipe.language || 'unknown'}`,
161
- ''
162
- );
163
- if (extracted.semanticTags?.length > 0) {
164
- recipe.tags = [...new Set([...(recipe.tags || []), ...extracted.semanticTags])];
165
- }
166
- if (
167
- (!recipe.category || recipe.category === 'Utility') &&
168
- extracted.category &&
169
- extracted.category !== 'general'
170
- ) {
171
- recipe.category = extracted.category;
172
- }
173
- } catch {
174
- /* best effort */
175
- }
176
- }
177
-
178
- // QualityScorer 评分 → quality 结构化
179
- if (qualityScorer) {
180
- try {
181
- const scoreResult = qualityScorer.score(recipe);
182
- recipe.quality = {
183
- completeness: 0,
184
- adaptation: 0,
185
- documentation: 0,
186
- overall: scoreResult.score ?? 0,
187
- grade: scoreResult.grade || '',
188
- };
189
- } catch {
190
- /* best effort */
191
- }
192
- }
193
- }
194
-
195
- const result = { targetName, extracted: recipes.length, recipes };
196
- if (fallbackUsed) {
197
- result.fallbackUsed = fallbackUsed;
198
- }
199
- return result;
200
- },
201
- };
202
-
203
- // ────────────────────────────────────────────────────────────
204
- // 9. enrich_candidate
205
- // ────────────────────────────────────────────────────────────
206
- export const enrichCandidate = {
207
- name: 'enrich_candidate',
208
- description:
209
- '① 结构补齐 — 自动填充缺失的结构性语义字段(rationale/knowledgeType/complexity/scope/steps/constraints)。批量处理,只填空不覆盖。建议在 refine_bootstrap_candidates 之前执行。',
210
- parameters: {
211
- type: 'object',
212
- properties: {
213
- candidateIds: {
214
- type: 'array',
215
- items: { type: 'string' },
216
- description: '候选 ID 列表 (最多 20 个)',
217
- },
218
- },
219
- required: ['candidateIds'],
220
- },
221
- handler: async (params, ctx) => {
222
- if (!ctx.aiProvider) {
223
- return { error: 'AI provider not available' };
224
- }
225
- // V3: 使用 MCP handler enrichCandidates 的逻辑
226
- const { enrichCandidates: enrichFn } = await import('../../../external/mcp/handlers/candidate.js');
227
- const result = await enrichFn(ctx, { candidateIds: params.candidateIds });
228
- return result?.data || result;
229
- },
230
- };
231
-
232
- // ────────────────────────────────────────────────────────────
233
- // 9b. refine_bootstrap_candidates (Phase 6)
234
- // ────────────────────────────────────────────────────────────
235
- export const refineBootstrapCandidates = {
236
- name: 'refine_bootstrap_candidates',
237
- description:
238
- '② 内容润色 — 逐条精炼 Bootstrap 候选的内容质量:改善 summary、补充架构 insight、推断 relations 关联、调整 confidence、丰富 tags。建议在 enrich_candidate 之后执行。',
239
- parameters: {
240
- type: 'object',
241
- properties: {
242
- candidateIds: {
243
- type: 'array',
244
- items: { type: 'string' },
245
- description: '指定候选 ID 列表(可选,默认全部 bootstrap 候选)',
246
- },
247
- userPrompt: {
248
- type: 'string',
249
- description: '用户自定义润色提示词,指导 AI 润色方向(如"侧重描述线程安全注意事项")',
250
- },
251
- dryRun: { type: 'boolean', description: '仅预览 AI 润色结果,不写入数据库' },
252
- },
253
- },
254
- handler: async (params, ctx) => {
255
- if (!ctx.aiProvider) {
256
- return { error: 'AI provider not available' };
257
- }
258
- // V3: 委托给 bootstrap handler 的 refine 逻辑
259
- const { bootstrapRefine } = await import('../../../external/mcp/handlers/bootstrap-internal.js');
260
- const result = await bootstrapRefine(ctx, {
261
- candidateIds: params.candidateIds,
262
- userPrompt: params.userPrompt,
263
- dryRun: params.dryRun,
264
- });
265
- return result?.data || result;
266
- },
267
- };
@@ -1,234 +0,0 @@
1
- /**
2
- * knowledge-graph.js — 知识图谱类工具 (3)
3
- *
4
- * 10. check_duplicate 候选查重
5
- * 11. discover_relations AI 关系发现
6
- * 12. add_graph_edge 手动添加图谱边
7
- */
8
-
9
- import { findSimilarRecipes } from '../../candidate/SimilarityService.js';
10
-
11
- // ────────────────────────────────────────────────────────────
12
- // 10. check_duplicate
13
- // ────────────────────────────────────────────────────────────
14
- export const checkDuplicate = {
15
- name: 'check_duplicate',
16
- description:
17
- '候选查重 — 检测候选代码是否与已有 Recipe 重复(基于标题/摘要/代码的 Jaccard 相似度)。',
18
- parameters: {
19
- type: 'object',
20
- properties: {
21
- candidate: { type: 'object', description: '候选对象 { title, summary, code, usageGuide }' },
22
- candidateId: { type: 'string', description: '或提供候选 ID,从数据库读取' },
23
- projectRoot: { type: 'string', description: '项目根目录(可选,默认当前项目)' },
24
- threshold: { type: 'number', description: '相似度阈值,默认 0.5' },
25
- },
26
- },
27
- handler: async (params, ctx) => {
28
- let cand = params.candidate;
29
- const projectRoot = params.projectRoot || ctx.projectRoot;
30
- const threshold = params.threshold ?? 0.5;
31
-
32
- // 如果提供 candidateId,从数据库读取条目信息
33
- if (!cand && params.candidateId) {
34
- try {
35
- const knowledgeService = ctx.container.get('knowledgeService');
36
- const found = await knowledgeService.get(params.candidateId);
37
- if (found) {
38
- const json = typeof found.toJSON === 'function' ? found.toJSON() : found;
39
- cand = {
40
- title: json.title || '',
41
- summary: json.description || '',
42
- code: json.content?.pattern || '',
43
- usageGuide: '',
44
- };
45
- }
46
- } catch {
47
- /* ignore */
48
- }
49
- }
50
-
51
- if (!cand) {
52
- return { similar: [], message: 'No candidate provided' };
53
- }
54
-
55
- const similar = findSimilarRecipes(projectRoot, cand, {
56
- threshold,
57
- topK: 10,
58
- });
59
-
60
- return {
61
- similar,
62
- hasDuplicate: similar.some((s) => s.similarity >= 0.7),
63
- highestSimilarity: similar.length > 0 ? similar[0].similarity : 0,
64
- _meta: {
65
- confidence: similar.length === 0 ? 'none' : similar[0].similarity >= 0.7 ? 'high' : 'low',
66
- hint:
67
- similar.length === 0
68
- ? '未发现相似 Recipe,可放心提交。'
69
- : similar[0].similarity >= 0.7
70
- ? '发现高度相似 Recipe,建议人工审核是否重复。'
71
- : '有低相似度匹配,大概率不是重复。',
72
- },
73
- };
74
- },
75
- };
76
-
77
- // ────────────────────────────────────────────────────────────
78
- // 11. discover_relations
79
- // ────────────────────────────────────────────────────────────
80
- export const discoverRelations = {
81
- name: 'discover_relations',
82
- description:
83
- 'AI 知识图谱关系发现 — 分析 Recipe 对之间的潜在关系(requires/extends/enforces/calls 等),并自动写入知识图谱。',
84
- parameters: {
85
- type: 'object',
86
- properties: {
87
- recipePairs: {
88
- type: 'array',
89
- items: {
90
- type: 'object',
91
- properties: {
92
- a: {
93
- type: 'object',
94
- properties: {
95
- id: { type: 'string' },
96
- title: { type: 'string' },
97
- category: { type: 'string' },
98
- code: { type: 'string' },
99
- },
100
- },
101
- b: {
102
- type: 'object',
103
- properties: {
104
- id: { type: 'string' },
105
- title: { type: 'string' },
106
- category: { type: 'string' },
107
- code: { type: 'string' },
108
- },
109
- },
110
- },
111
- },
112
- description:
113
- 'Recipe 对数组 [{ a: {id, title, category, code}, b: {id, title, category, code} }]',
114
- },
115
- dryRun: { type: 'boolean', description: '仅分析不写入,默认 false' },
116
- },
117
- required: ['recipePairs'],
118
- },
119
- handler: async (params, ctx) => {
120
- if (!ctx.aiProvider) {
121
- return { error: 'AI provider not available' };
122
- }
123
-
124
- const { recipePairs, dryRun = false } = params;
125
- if (!recipePairs || recipePairs.length === 0) {
126
- return { relations: [] };
127
- }
128
-
129
- // 构建 LLM prompt
130
- const pairsText = recipePairs
131
- .map(
132
- (p, i) => `
133
- --- Pair #${i + 1} ---
134
- Recipe A [${p.a.id}]: ${p.a.title} (${p.a.category}/${p.a.language || ''})
135
- ${p.a.code ? `Code: ${p.a.code.substring(0, 300)}` : ''}
136
-
137
- Recipe B [${p.b.id}]: ${p.b.title} (${p.b.category}/${p.b.language || ''})
138
- ${p.b.code ? `Code: ${p.b.code.substring(0, 300)}` : ''}`
139
- )
140
- .join('\n');
141
-
142
- const prompt = `# Role
143
- You are a Software Architect analyzing relationships between code recipes (knowledge units).
144
-
145
- # Goal
146
- For each Recipe pair below, determine if there is a meaningful relationship.
147
-
148
- # Relationship Types
149
- - requires: A needs B to function
150
- - extends: A builds upon / enriches B
151
- - enforces: A enforces rules defined in B
152
- - depends_on: A depends on B
153
- - inherits: A inherits from B (class/protocol)
154
- - implements: A implements interface/protocol defined in B
155
- - calls: A calls API defined in B
156
- - prerequisite: B must be learned/applied before A
157
- - none: No meaningful relationship
158
-
159
- # Output
160
- Return a JSON array. For each pair with a relationship (skip "none"):
161
- { "index": 0, "from_id": "...", "to_id": "...", "relation": "requires", "confidence": 0.85, "reason": "A uses the network client defined in B" }
162
-
163
- Return ONLY a JSON array. No markdown, no extra text. Return [] if no relationships found.
164
-
165
- # Recipe Pairs
166
- ${pairsText}`;
167
-
168
- const parsed = await ctx.aiProvider.chatWithStructuredOutput(prompt, {
169
- openChar: '[',
170
- closeChar: ']',
171
- temperature: 0.2,
172
- });
173
- const relations = Array.isArray(parsed) ? parsed : [];
174
-
175
- // 写入知识图谱(除非 dryRun)
176
- if (!dryRun && relations.length > 0) {
177
- try {
178
- const kgService = ctx.container.get('knowledgeGraphService');
179
- for (const rel of relations) {
180
- if (rel.from_id && rel.to_id && rel.relation && rel.relation !== 'none') {
181
- kgService.addEdge(rel.from_id, 'recipe', rel.to_id, 'recipe', rel.relation, {
182
- confidence: rel.confidence || 0.5,
183
- reason: rel.reason || '',
184
- source: 'ai-discovery',
185
- });
186
- }
187
- }
188
- } catch {
189
- /* KG not available */
190
- }
191
- }
192
-
193
- return {
194
- analyzed: recipePairs.length,
195
- relations: relations.filter((r) => r.relation !== 'none'),
196
- written: dryRun ? 0 : relations.filter((r) => r.relation !== 'none').length,
197
- };
198
- },
199
- };
200
-
201
- // ────────────────────────────────────────────────────────────
202
- // 12. add_graph_edge
203
- // ────────────────────────────────────────────────────────────
204
- export const addGraphEdge = {
205
- name: 'add_graph_edge',
206
- description: '手动添加知识图谱关系边(从 A 到 B 的关系)。',
207
- parameters: {
208
- type: 'object',
209
- properties: {
210
- fromId: { type: 'string', description: '源节点 ID' },
211
- fromType: { type: 'string', description: '源节点类型 (recipe/candidate)' },
212
- toId: { type: 'string', description: '目标节点 ID' },
213
- toType: { type: 'string', description: '目标节点类型 (recipe/candidate)' },
214
- relation: {
215
- type: 'string',
216
- description:
217
- '关系类型 (requires/extends/enforces/depends_on/inherits/implements/calls/prerequisite)',
218
- },
219
- weight: { type: 'number', description: '权重 0-1,默认 1.0' },
220
- },
221
- required: ['fromId', 'fromType', 'toId', 'toType', 'relation'],
222
- },
223
- handler: async (params, ctx) => {
224
- const kgService = ctx.container.get('knowledgeGraphService');
225
- return kgService.addEdge(
226
- params.fromId,
227
- params.fromType,
228
- params.toId,
229
- params.toType,
230
- params.relation,
231
- { weight: params.weight || 1.0, source: 'manual' }
232
- );
233
- },
234
- };
@@ -1,18 +0,0 @@
1
- /**
2
- * tools.js — ChatAgent 工具定义统一入口 (Barrel Re-export)
3
- *
4
- * 实际工具定义已拆分到 ./tools/ 子目录:
5
- * - project-access.js 项目数据访问 (5)
6
- * - query.js 查询类 (6)
7
- * - ai-analysis.js AI 分析类 (4)
8
- * - knowledge-graph.js 知识图谱 (3)
9
- * - guard.js Guard 安全类 (6)
10
- * - lifecycle.js 生命周期操作类 (11)
11
- * - infrastructure.js 基础设施 + Skills (7)
12
- * - composite.js 组合工具 + 元工具 (6)
13
- * - ast-graph.js AST 分析 + Agent Memory (10)
14
- *
15
- * 本文件仅做 re-export,保持向后兼容。
16
- */
17
-
18
- export { ALL_TOOLS, default } from './tools/index.js';
@@ -1,5 +0,0 @@
1
- /**
2
- * @deprecated Moved to lib/platform/ios/snippet/PlaceholderConverter.js
3
- * This re-export shim maintains backward compatibility.
4
- */
5
- export { PlaceholderConverter } from '../../platform/ios/snippet/PlaceholderConverter.js';
@@ -1,5 +0,0 @@
1
- /**
2
- * @deprecated Moved to lib/platform/ios/snippet/XcodeCodec.js
3
- * This re-export shim maintains backward compatibility.
4
- */
5
- export { XcodeCodec } from '../../../platform/ios/snippet/XcodeCodec.js';
File without changes
File without changes
File without changes
File without changes