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.
Files changed (56) hide show
  1. package/bin/cli.js +64 -1
  2. package/config/default.json +9 -0
  3. package/dashboard/dist/assets/{index-I2ySoCmF.js → index-Bnm26ulL.js} +47 -47
  4. package/dashboard/dist/index.html +1 -1
  5. package/lib/cli/SetupService.js +92 -5
  6. package/lib/cli/UpgradeService.js +14 -5
  7. package/lib/core/discovery/GenericDiscoverer.js +4 -28
  8. package/lib/external/mcp/handlers/bootstrap/base-dimensions.js +246 -0
  9. package/lib/external/mcp/handlers/bootstrap/pipeline/checkpoint.js +80 -0
  10. package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-configs.js +275 -0
  11. package/lib/external/mcp/handlers/bootstrap/pipeline/noAiFallback.js +600 -0
  12. package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +125 -342
  13. package/lib/external/mcp/handlers/bootstrap/refine.js +362 -0
  14. package/lib/external/mcp/handlers/bootstrap.js +6 -590
  15. package/lib/external/mcp/handlers/browse.js +119 -9
  16. package/lib/external/mcp/handlers/guard.js +25 -6
  17. package/lib/external/mcp/handlers/search.js +56 -24
  18. package/lib/http/routes/guardRules.js +9 -17
  19. package/lib/injection/ServiceContainer.js +12 -3
  20. package/lib/platform/ios/xcode/XcodeImportResolver.js +434 -0
  21. package/lib/platform/ios/xcode/XcodeIntegration.js +40 -659
  22. package/lib/platform/ios/xcode/XcodeWriteUtils.js +220 -0
  23. package/lib/service/chat/ChatAgent.js +39 -418
  24. package/lib/service/chat/ChatAgentPrompts.js +149 -0
  25. package/lib/service/chat/ChatAgentTasks.js +297 -0
  26. package/lib/service/chat/tools/_shared.js +61 -0
  27. package/lib/service/chat/tools/ai-analysis.js +284 -0
  28. package/lib/service/chat/tools/ast-graph.js +681 -0
  29. package/lib/service/chat/tools/composite.js +496 -0
  30. package/lib/service/chat/tools/guard.js +265 -0
  31. package/lib/service/chat/tools/index.js +250 -0
  32. package/lib/service/chat/tools/infrastructure.js +222 -0
  33. package/lib/service/chat/tools/knowledge-graph.js +234 -0
  34. package/lib/service/chat/tools/lifecycle.js +469 -0
  35. package/lib/service/chat/tools/project-access.js +923 -0
  36. package/lib/service/chat/tools/query.js +264 -0
  37. package/lib/service/chat/tools.js +14 -3994
  38. package/lib/service/cursor/AgentInstructionsGenerator.js +395 -0
  39. package/lib/service/cursor/CursorDeliveryPipeline.js +70 -11
  40. package/lib/service/cursor/FileProtection.js +116 -0
  41. package/lib/service/cursor/KnowledgeCompressor.js +61 -11
  42. package/lib/service/cursor/SkillsSyncer.js +5 -3
  43. package/lib/service/cursor/TopicClassifier.js +19 -3
  44. package/lib/service/guard/ExclusionManager.js +26 -2
  45. package/lib/service/guard/GuardCheckEngine.js +38 -370
  46. package/lib/service/guard/GuardCodeChecks.js +362 -0
  47. package/lib/service/guard/GuardCrossFileChecks.js +307 -0
  48. package/lib/service/guard/GuardPatternUtils.js +180 -0
  49. package/lib/service/guard/GuardService.js +80 -38
  50. package/lib/service/module/ModuleService.js +1 -0
  51. package/lib/service/search/SearchEngine.js +10 -2
  52. package/lib/service/wiki/WikiGenerator.js +226 -1532
  53. package/lib/service/wiki/WikiRenderers.js +1878 -0
  54. package/lib/service/wiki/WikiUtils.js +907 -0
  55. package/lib/shared/LanguageService.js +299 -0
  56. package/package.json +1 -1
@@ -31,6 +31,18 @@ import { ConversationStore } from './ConversationStore.js';
31
31
  import { Memory } from './Memory.js';
32
32
  import { ReasoningLayer } from './ReasoningLayer.js';
33
33
  import { TaskPipeline } from './TaskPipeline.js';
34
+ import {
35
+ taskCheckAndSubmit,
36
+ taskDiscoverAllRelations,
37
+ taskFullEnrich,
38
+ taskQualityAudit,
39
+ taskGuardFullScan,
40
+ } from './ChatAgentTasks.js';
41
+ import {
42
+ buildNativeToolSystemPrompt,
43
+ buildProjectBriefing,
44
+ cleanFinalAnswer,
45
+ } from './ChatAgentPrompts.js';
34
46
 
35
47
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
36
48
  const PROJECT_ROOT = path.resolve(__dirname, '../../..');
@@ -245,7 +257,7 @@ export class ChatAgent {
245
257
  }
246
258
 
247
259
  // 每次对话刷新项目概况(不是每轮 ReAct)
248
- this.#projectBriefingCache = await this.#buildProjectBriefing();
260
+ this.#projectBriefingCache = await buildProjectBriefing({ container: this.#container });
249
261
 
250
262
  // ── 统一原生函数调用路径(v5.0: 移除文本解析路径) ──
251
263
  // 所有 Provider 均通过 chatWithTools() 进行结构化工具调用。
@@ -408,7 +420,14 @@ export class ChatAgent {
408
420
  isSystem && !disablePhaseRouter ? new PhaseRouter(budget, isSkillOnly) : null;
409
421
 
410
422
  // ── 系统提示词 (支持外部覆盖) ──
411
- let baseSystemPrompt = systemPromptOverride || this.#buildNativeToolSystemPrompt(budget);
423
+ let baseSystemPrompt = systemPromptOverride || buildNativeToolSystemPrompt({
424
+ currentSource: this.#currentSource,
425
+ projectBriefingCache: this.#projectBriefingCache,
426
+ memory: this.#memory,
427
+ semanticMemory: this.#semanticMemory,
428
+ budget,
429
+ soulPath: SOUL_PATH,
430
+ });
412
431
 
413
432
  // ── 统一注入语言指令(对所有来源生效: user 对话 / system bootstrap / analyst / producer)──
414
433
  const effectiveLang = this.#currentLang;
@@ -734,7 +753,7 @@ export class ChatAgent {
734
753
  `[ChatAgent] ⚠ AI returned ${aiResult.functionCalls.length} tool calls despite toolChoice=none (graceful exit) — ignoring tools, treating as text`
735
754
  );
736
755
  if (aiResult.text) {
737
- const reply = this.#cleanFinalAnswer(aiResult.text);
756
+ const reply = cleanFinalAnswer(aiResult.text);
738
757
  const totalDuration = Date.now() - execStartTime;
739
758
  reasoning.afterRound();
740
759
  this.#logger.info(
@@ -1095,7 +1114,7 @@ export class ChatAgent {
1095
1114
  continue;
1096
1115
  }
1097
1116
  // 已在 SUMMARIZE 阶段 — 这就是最终回答
1098
- const reply = this.#cleanFinalAnswer(aiResult.text || '');
1117
+ const reply = cleanFinalAnswer(aiResult.text || '');
1099
1118
  const totalDuration = Date.now() - execStartTime;
1100
1119
  reasoning.afterRound();
1101
1120
  this.#logger.info(
@@ -1126,7 +1145,7 @@ export class ChatAgent {
1126
1145
  continue;
1127
1146
  }
1128
1147
  // 非生产阶段的未转换文本 = 最终回答
1129
- const reply = this.#cleanFinalAnswer(aiResult.text || '');
1148
+ const reply = cleanFinalAnswer(aiResult.text || '');
1130
1149
  const totalDuration = Date.now() - execStartTime;
1131
1150
  reasoning.afterRound();
1132
1151
  this.#logger.info(
@@ -1148,7 +1167,7 @@ export class ChatAgent {
1148
1167
 
1149
1168
  // 用户对话 / graceful exit: 文字回答即最终回答
1150
1169
  if (ctx.__gracefulExitInjected || !isSystem) {
1151
- const reply = this.#cleanFinalAnswer(aiResult.text || '');
1170
+ const reply = cleanFinalAnswer(aiResult.text || '');
1152
1171
  const totalDuration = Date.now() - execStartTime;
1153
1172
  reasoning.afterRound();
1154
1173
  this.#logger.info(
@@ -1164,7 +1183,7 @@ export class ChatAgent {
1164
1183
  }
1165
1184
 
1166
1185
  // system 模式非 graceful exit 的文字回答(理论上不应到这里)
1167
- const reply = this.#cleanFinalAnswer(aiResult.text || '');
1186
+ const reply = cleanFinalAnswer(aiResult.text || '');
1168
1187
  const totalDuration = Date.now() - execStartTime;
1169
1188
  reasoning.afterRound();
1170
1189
  this.#logger.info(
@@ -1299,7 +1318,7 @@ ${toolContextSummary}
1299
1318
  this.#currentTokenUsage.input += summaryResult.usage.inputTokens || 0;
1300
1319
  this.#currentTokenUsage.output += summaryResult.usage.outputTokens || 0;
1301
1320
  }
1302
- finalReply = this.#cleanFinalAnswer(summaryResult.text || '');
1321
+ finalReply = cleanFinalAnswer(summaryResult.text || '');
1303
1322
  } catch (err) {
1304
1323
  this.#logger.warn(`[ChatAgent] forced summary AI call failed: ${err.message}`);
1305
1324
 
@@ -1514,18 +1533,25 @@ ${toolContextSummary}
1514
1533
  if (this.#pipelines.has(taskName)) {
1515
1534
  return this.runPipeline(taskName, params);
1516
1535
  }
1536
+ // 构建任务上下文(提供给外部任务函数)
1537
+ const taskContext = {
1538
+ executeTool: (name, p) => this.executeTool(name, p),
1539
+ aiProvider: this.#aiProvider,
1540
+ container: this.#container,
1541
+ logger: this.#logger,
1542
+ };
1517
1543
  // 降级到硬编码任务(复杂交互逻辑无法用 DAG 表达的场景)
1518
1544
  switch (taskName) {
1519
1545
  case 'check_and_submit':
1520
- return this.#taskCheckAndSubmit(params);
1546
+ return taskCheckAndSubmit(taskContext, params);
1521
1547
  case 'discover_all_relations':
1522
- return this.#taskDiscoverAllRelations(params);
1548
+ return taskDiscoverAllRelations(taskContext, params);
1523
1549
  case 'full_enrich':
1524
- return this.#taskFullEnrich(params);
1550
+ return taskFullEnrich(taskContext, params);
1525
1551
  case 'quality_audit':
1526
- return this.#taskQualityAudit(params);
1552
+ return taskQualityAudit(taskContext, params);
1527
1553
  case 'guard_full_scan':
1528
- return this.#taskGuardFullScan(params);
1554
+ return taskGuardFullScan(taskContext, params);
1529
1555
  default:
1530
1556
  throw new Error(`Unknown task: ${taskName}`);
1531
1557
  }
@@ -1589,289 +1615,6 @@ ${toolContextSummary}
1589
1615
  };
1590
1616
  }
1591
1617
 
1592
- // ─── 预定义任务 ────────────────────────────────────────
1593
-
1594
- /**
1595
- * 任务: 提交前查重 + 质量预评
1596
- * 1. check_duplicate → 若发现相似 ≥ 0.7 则建议合并
1597
- * 2. 顺便返回质量评估建议
1598
- */
1599
- async #taskCheckAndSubmit({ candidate, projectRoot }) {
1600
- // Step 1: 查重
1601
- const duplicates = await this.executeTool('check_duplicate', {
1602
- candidate,
1603
- projectRoot,
1604
- threshold: 0.5,
1605
- });
1606
-
1607
- // Step 2: 如果有高相似度,使用 AI 分析是否真正重复
1608
- const highSim = (duplicates.similar || []).filter((d) => d.similarity >= 0.7);
1609
- let aiVerdict = null;
1610
- if (highSim.length > 0 && this.#aiProvider) {
1611
- const verdictPrompt = `以下新候选代码与已有 Recipe 高度相似,请判断是否真正重复。
1612
-
1613
- 新候选:
1614
- - Title: ${candidate.title || '(未命名)'}
1615
- - Code: ${(candidate.code || '').substring(0, 1000)}
1616
-
1617
- 相似 Recipe:
1618
- ${highSim.map((s) => `- ${s.title} (相似度: ${s.similarity})`).join('\n')}
1619
-
1620
- 请回答: DUPLICATE(真正重复)/ SIMILAR(相似但不同,建议保留并标注关系)/ UNIQUE(误判,可放心提交)
1621
- 只回答一个词。`;
1622
- try {
1623
- const raw = await this.#aiProvider.chat(verdictPrompt, { temperature: 0, maxTokens: 20 });
1624
- aiVerdict = (raw || '').trim().toUpperCase().split(/\s/)[0];
1625
- } catch {
1626
- /* ignore */
1627
- }
1628
- }
1629
-
1630
- return {
1631
- duplicates: duplicates.similar || [],
1632
- highSimilarity: highSim,
1633
- aiVerdict,
1634
- recommendation:
1635
- highSim.length === 0
1636
- ? 'safe_to_submit'
1637
- : aiVerdict === 'DUPLICATE'
1638
- ? 'block_duplicate'
1639
- : 'review_suggested',
1640
- };
1641
- }
1642
-
1643
- /**
1644
- * 任务: 批量发现 Recipe 间的知识图谱关系
1645
- * 遍历所有 Recipe,两两分析可能的关系
1646
- */
1647
- async #taskDiscoverAllRelations({ batchSize = 20 } = {}) {
1648
- const ctx = this.#getToolContext();
1649
- const knowledgeService = ctx.container.get('knowledgeService');
1650
- if (!knowledgeService) {
1651
- throw new Error('KnowledgeService 不可用');
1652
- }
1653
-
1654
- if (!ctx.aiProvider) {
1655
- throw new Error('AI Provider 未配置,请先设置 API Key');
1656
- }
1657
-
1658
- // 获取所有活跃知识条目
1659
- const { items = [], data = [] } = await knowledgeService.list(
1660
- { lifecycle: 'active' },
1661
- { page: 1, pageSize: 500 }
1662
- );
1663
- const recipes = items.length > 0 ? items : data;
1664
- if (recipes.length < 2) {
1665
- return {
1666
- discovered: 0,
1667
- totalPairs: 0,
1668
- message: `只有 ${recipes.length} 条 Recipe,至少需要 2 条`,
1669
- };
1670
- }
1671
-
1672
- // 按 batch 分组分析
1673
- const pairs = [];
1674
- for (let i = 0; i < recipes.length; i++) {
1675
- for (let j = i + 1; j < recipes.length; j++) {
1676
- pairs.push([recipes[i], recipes[j]]);
1677
- }
1678
- }
1679
-
1680
- let discovered = 0;
1681
- const results = [];
1682
- let batchErrors = 0;
1683
-
1684
- // 分批处理,单批失败不终止整体
1685
- for (let b = 0; b < pairs.length; b += batchSize) {
1686
- const batch = pairs.slice(b, b + batchSize);
1687
- try {
1688
- const result = await this.executeTool('discover_relations', {
1689
- recipePairs: batch.map(([a, b]) => ({
1690
- a: {
1691
- id: a.id,
1692
- title: a.title,
1693
- category: a.category,
1694
- language: a.language,
1695
- code: String(a.content || a.code || '').substring(0, 500),
1696
- },
1697
- b: {
1698
- id: b.id,
1699
- title: b.title,
1700
- category: b.category,
1701
- language: b.language,
1702
- code: String(b.content || b.code || '').substring(0, 500),
1703
- },
1704
- })),
1705
- });
1706
-
1707
- if (result.error) {
1708
- batchErrors++;
1709
- this.#logger.warn(
1710
- `[DiscoverRelations] Batch ${Math.floor(b / batchSize) + 1} error: ${result.error}`
1711
- );
1712
- continue;
1713
- }
1714
- if (result.relations) {
1715
- discovered += result.relations.length;
1716
- results.push(...result.relations);
1717
- }
1718
- } catch (err) {
1719
- batchErrors++;
1720
- this.#logger.warn(
1721
- `[DiscoverRelations] Batch ${Math.floor(b / batchSize) + 1} threw: ${err.message}`
1722
- );
1723
- }
1724
- }
1725
-
1726
- return {
1727
- discovered,
1728
- totalPairs: pairs.length,
1729
- totalBatches: Math.ceil(pairs.length / batchSize),
1730
- batchErrors,
1731
- relations: results,
1732
- };
1733
- }
1734
-
1735
- /**
1736
- * 任务: 批量 AI 补全候选语义字段
1737
- */
1738
- async #taskFullEnrich({ status = 'pending', maxCount = 50 } = {}) {
1739
- const ctx = this.#getToolContext();
1740
- const knowledgeService = ctx.container.get('knowledgeService');
1741
-
1742
- const { items = [], data = [] } = await knowledgeService.list(
1743
- { lifecycle: status },
1744
- { page: 1, pageSize: maxCount }
1745
- );
1746
- const candidates = items.length > 0 ? items : data;
1747
- if (candidates.length === 0) {
1748
- return { enriched: 0, message: 'No candidates to enrich' };
1749
- }
1750
-
1751
- // 筛选缺失语义字段的候选
1752
- const needEnrich = candidates.filter((c) => {
1753
- const m = c.metadata || {};
1754
- return !m.rationale || !m.knowledgeType || !m.complexity;
1755
- });
1756
-
1757
- if (needEnrich.length === 0) {
1758
- return { enriched: 0, message: 'All candidates already enriched' };
1759
- }
1760
-
1761
- const result = await this.executeTool('enrich_candidate', {
1762
- candidateIds: needEnrich.map((c) => c.id).slice(0, 20),
1763
- });
1764
-
1765
- return result;
1766
- }
1767
-
1768
- /**
1769
- * 任务: 批量质量审计全部 Recipe
1770
- * 对活跃 Recipe 逐个评分,返回低于阈值的列表
1771
- */
1772
- async #taskQualityAudit({ threshold = 0.6, maxCount = 100 } = {}) {
1773
- const ctx = this.#getToolContext();
1774
- const knowledgeService = ctx.container.get('knowledgeService');
1775
-
1776
- const { items = [], data = [] } = await knowledgeService.list(
1777
- { lifecycle: 'active' },
1778
- { page: 1, pageSize: maxCount }
1779
- );
1780
- const recipes = items.length > 0 ? items : data;
1781
- if (recipes.length === 0) {
1782
- return { total: 0, lowQuality: [], message: 'No active recipes' };
1783
- }
1784
-
1785
- const lowQuality = [];
1786
- const gradeDistribution = { A: 0, B: 0, C: 0, D: 0, F: 0 };
1787
-
1788
- for (const recipe of recipes) {
1789
- const scoreResult = await this.executeTool('quality_score', { recipe });
1790
- if (scoreResult.grade) {
1791
- gradeDistribution[scoreResult.grade] = (gradeDistribution[scoreResult.grade] || 0) + 1;
1792
- }
1793
- if (scoreResult.score < threshold) {
1794
- lowQuality.push({
1795
- id: recipe.id,
1796
- title: recipe.title,
1797
- score: scoreResult.score,
1798
- grade: scoreResult.grade,
1799
- dimensions: scoreResult.dimensions,
1800
- });
1801
- }
1802
- }
1803
-
1804
- lowQuality.sort((a, b) => a.score - b.score);
1805
-
1806
- return {
1807
- total: recipes.length,
1808
- threshold,
1809
- gradeDistribution,
1810
- lowQualityCount: lowQuality.length,
1811
- lowQuality,
1812
- };
1813
- }
1814
-
1815
- /**
1816
- * 任务: Guard 完整扫描
1817
- * 对代码运行全部 Guard 规则 + 生成修复建议
1818
- */
1819
- async #taskGuardFullScan({ code, language, filePath } = {}) {
1820
- if (!code) {
1821
- return { error: 'code is required' };
1822
- }
1823
-
1824
- // Step 1: 静态检查
1825
- const checkResult = await this.executeTool('guard_check_code', {
1826
- code,
1827
- language: language || 'unknown',
1828
- scope: 'project',
1829
- });
1830
-
1831
- // Step 2: 如果有违规且 AI 可用,生成修复建议
1832
- let suggestions = null;
1833
- if (checkResult.violationCount > 0 && this.#aiProvider) {
1834
- try {
1835
- const violationSummary = (checkResult.violations || [])
1836
- .slice(0, 5)
1837
- .map(
1838
- (v) =>
1839
- `- [${v.severity}] ${v.message || v.ruleName} (line ${v.line || v.matches?.[0]?.line || '?'})`
1840
- )
1841
- .join('\n');
1842
-
1843
- const prompt = `以下代码存在 Guard 规则违规。请为每个违规提供修复建议。
1844
-
1845
- 违规列表:
1846
- ${violationSummary}
1847
-
1848
- 代码片段:
1849
- \`\`\`${language || ''}
1850
- ${code.substring(0, 3000)}
1851
- \`\`\`
1852
-
1853
- 请用 JSON 数组格式返回建议: [{"violation": "...", "suggestion": "...", "fixExample": "..."}]`;
1854
-
1855
- suggestions =
1856
- (await this.#aiProvider.chatWithStructuredOutput(prompt, {
1857
- openChar: '[',
1858
- closeChar: ']',
1859
- temperature: 0.3,
1860
- })) || [];
1861
- } catch {
1862
- /* AI suggestions optional */
1863
- }
1864
- }
1865
-
1866
- return {
1867
- filePath: filePath || '(inline)',
1868
- language,
1869
- violationCount: checkResult.violationCount,
1870
- violations: checkResult.violations,
1871
- suggestions,
1872
- };
1873
- }
1874
-
1875
1618
  // ─── 内置 DAG 管线注册 ─────────────────────────────────
1876
1619
 
1877
1620
  /**
@@ -1905,88 +1648,6 @@ ${code.substring(0, 3000)}
1905
1648
 
1906
1649
  // ─── Native Tool Calling 内部方法 ──────────────────────
1907
1650
 
1908
- /**
1909
- * 构建原生函数调用模式的系统提示词
1910
- *
1911
- * 设计原则:
1912
- * - 精简: bootstrap 模式不注入 SOUL.md 人格(节省 ~500 token)
1913
- * - 分层: 静态指令放 systemPrompt,动态上下文放 user prompt
1914
- * - 控制通过 PhaseRouter 状态机实现,不通过追加 user 消息
1915
- * - 工具描述已通过 functionDeclarations 传递,不重复
1916
- */
1917
- #buildNativeToolSystemPrompt(budget = DEFAULT_BUDGET) {
1918
- // 用户对话模式: 完整提示词(含 SOUL、Memory、项目概况)
1919
- if (this.#currentSource !== 'system') {
1920
- let soulSection = '';
1921
- try {
1922
- if (fs.existsSync(SOUL_PATH)) {
1923
- soulSection = `\n${fs.readFileSync(SOUL_PATH, 'utf-8').trim()}\n`;
1924
- }
1925
- } catch {
1926
- /* SOUL.md not available */
1927
- }
1928
-
1929
- return `${soulSection}
1930
- 你是 AutoSnippet 项目的统一 AI 中心。项目内所有 AI 推理和分析都通过你执行。
1931
- ${this.#projectBriefingCache}${this.#memory?.toPromptSection({ source: 'user' }) || ''}${this.#semanticMemory?.toPromptSection({ source: 'user' }) || ''}
1932
-
1933
- ## 使用规则
1934
- 1. 当需要查询数据时,直接调用相应工具。
1935
- 2. 工具参数严格按照工具声明中的 schema 传递。
1936
- 3. 对于代码分析任务,先 search_project_code 搜索,再 read_project_file 读取。
1937
- 4. 当工具返回错误时,尝试不同参数或方法。`;
1938
- }
1939
-
1940
- // Bootstrap 系统模式: LLM 以领域大脑的能力处理任务
1941
- return `你以「领域大脑」的能力来处理任务 — 你对软件工程领域拥有深厚的专家知识。
1942
- 你将分析一个真实项目,自主发现其中有价值的代码知识。
1943
- ${this.#projectBriefingCache}
1944
-
1945
- ## 你的能力定位
1946
- 你具备深度技术洞察力,能够理解代码背后的设计意图。
1947
- 你知道什么知识对开发团队最有价值 — 不是显而易见的样板代码,
1948
- 而是体现项目独有设计决策、架构模式和工程智慧的知识。
1949
-
1950
- ## 你的工作方式
1951
- 1. **全局感知** → list_project_structure 了解项目结构
1952
- 2. **定向探索** → get_file_summary 快速了解文件角色
1953
- 3. **深入研读** → search_project_code / read_project_file 获取真实代码
1954
- 4. **语义发现** → semantic_search_code 在知识库查找相关知识
1955
- 5. **知识产出** → submit_knowledge 提交有价值的发现
1956
-
1957
- ## 高效使用工具(节省轮次)
1958
- - **批量搜索**: search_project_code({ patterns: ["keywordA", "keywordB", "keywordC"] })
1959
- - **批量读文件**: read_project_file({ filePaths: ["path/a.m", "path/b.m"] })
1960
- - 合并同类请求为一次调用,避免逐个搜索/读取浪费轮次。
1961
-
1962
- ## 「项目特写」= 基本用法 + 项目特征融合
1963
- submit_knowledge 的 code 字段必须是「项目特写」— 将技术的基本用法与本项目的特征融合为一体:
1964
- 1. **项目选择了什么**: 采用了哪种写法/模式/约定
1965
- 2. **为什么这样选**: 统计数据(N 个文件、占比 M%)
1966
- 3. **项目禁止什么**: 被放弃的写法、反模式、显式禁用标记
1967
- 4. **新代码怎么写**: 可直接复制使用的代码模板
1968
-
1969
- ## 核心原则
1970
- - 代码必须真实,来自工具返回,不可编造
1971
- - 引用具体类名、方法名、数字,禁止「本模块」「该文件」等泛化描述
1972
- - 质量优先于数量,证据不足宁可不提交
1973
- - 高效利用步数 (≤${budget.maxIterations} 轮)`;
1974
- }
1975
-
1976
- /**
1977
- * 清理最终回答(去除 Thought/preamble + MEMORY 标签)
1978
- */
1979
- #cleanFinalAnswer(response) {
1980
- if (!response) {
1981
- return '';
1982
- }
1983
- return response
1984
- .replace(/^(Final Answer|最终回答|Answer)\s*[::]\s*/i, '')
1985
- .replace(/\[MEMORY:\w+\]\s*[\s\S]*?\s*\[\/MEMORY\]/g, '')
1986
- .replace(/\n{3,}/g, '\n\n')
1987
- .trim();
1988
- }
1989
-
1990
1651
  /**
1991
1652
  * 获取工具执行上下文
1992
1653
  * @param {object} [extras] — 额外注入到上下文的字段(如 _sessionToolCalls)
@@ -2059,46 +1720,6 @@ submit_knowledge 的 code 字段必须是「项目特写」— 将技术的基
2059
1720
  }
2060
1721
  }
2061
1722
 
2062
- /**
2063
- * 构建项目概况注入到系统提示词(每次 execute 刷新一次)
2064
- * 单次 SQL 聚合 < 5ms,静默降级
2065
- */
2066
- async #buildProjectBriefing() {
2067
- try {
2068
- const db = this.#container?.get('database');
2069
- if (!db) {
2070
- return '';
2071
- }
2072
- // knowledgeType → kind 映射:
2073
- // rule: code-standard, code-style, best-practice, boundary-constraint
2074
- // pattern: code-pattern, architecture, solution
2075
- // fact: code-relation, inheritance, call-chain, data-flow, module-dependency
2076
- // V3: knowledge_entries 统一表(candidates 已合并,lifecycle 替代 status)
2077
- const stats = db
2078
- .prepare(`
2079
- SELECT
2080
- (SELECT COUNT(*) FROM knowledge_entries WHERE lifecycle = 'active') as recipeCount,
2081
- (SELECT COUNT(*) FROM knowledge_entries WHERE lifecycle = 'active' AND knowledgeType IN ('code-standard','code-style','best-practice','boundary-constraint')) as ruleCount,
2082
- (SELECT COUNT(*) FROM knowledge_entries WHERE lifecycle = 'active' AND knowledgeType IN ('code-pattern','architecture','solution')) as patternCount,
2083
- (SELECT COUNT(*) FROM knowledge_entries WHERE lifecycle = 'active' AND knowledgeType IN ('code-relation','inheritance','call-chain','data-flow','module-dependency')) as factCount,
2084
- (SELECT COUNT(*) FROM knowledge_entries WHERE lifecycle = 'active' AND knowledgeType = 'boundary-constraint') as guardRuleCount,
2085
- (SELECT COUNT(*) FROM knowledge_entries WHERE lifecycle = 'pending') as pendingCandidates,
2086
- (SELECT COUNT(*) FROM knowledge_entries) as totalCandidates
2087
- `)
2088
- .get();
2089
- if (!stats || stats.recipeCount === 0) {
2090
- return '\n## 项目状态\n⚠️ 知识库为空。建议先执行冷启动(bootstrap_knowledge)。\n';
2091
- }
2092
- let section = `\n## 项目状态\n- 知识库: ${stats.recipeCount} 条 Recipe(${stats.ruleCount || 0} rule / ${stats.patternCount || 0} pattern / ${stats.factCount || 0} fact)\n- Guard 规则: ${stats.guardRuleCount || 0} 条\n- 候选: ${stats.pendingCandidates} 条待审 / ${stats.totalCandidates} 条总计\n`;
2093
- if (stats.pendingCandidates > 10) {
2094
- section += `\n⚠️ 有 ${stats.pendingCandidates} 条候选积压,建议执行批量审核。\n`;
2095
- }
2096
- return section;
2097
- } catch {
2098
- return ''; // DB 不可用时静默降级
2099
- }
2100
- }
2101
-
2102
1723
  /**
2103
1724
  * 异步初始化 ProjectSemanticMemory (Tier 3)
2104
1725
  * 在构造函数中调用 (fire-and-forget)