autosnippet 2.9.0 → 2.11.0

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 (115) hide show
  1. package/README.md +12 -12
  2. package/bin/cli.js +53 -40
  3. package/config/constitution.yaml +9 -2
  4. package/dashboard/dist/assets/{icons-CH-H9x0E.js → icons-D4IWpDIk.js} +105 -100
  5. package/dashboard/dist/assets/index-CWBNcF9z.css +1 -0
  6. package/dashboard/dist/assets/index-DHtzhbuG.js +120 -0
  7. package/dashboard/dist/index.html +3 -3
  8. package/lib/cli/AiScanService.js +35 -36
  9. package/lib/cli/KnowledgeSyncService.js +345 -0
  10. package/lib/cli/SetupService.js +8 -26
  11. package/lib/cli/UpgradeService.js +28 -0
  12. package/lib/core/gateway/GatewayActionRegistry.js +48 -58
  13. package/lib/domain/index.js +16 -11
  14. package/lib/domain/knowledge/KnowledgeEntry.js +289 -0
  15. package/lib/domain/knowledge/KnowledgeRepository.js +123 -0
  16. package/lib/domain/knowledge/Lifecycle.js +99 -0
  17. package/lib/domain/knowledge/index.js +27 -0
  18. package/lib/domain/knowledge/values/Constraints.js +128 -0
  19. package/lib/domain/knowledge/values/Content.js +69 -0
  20. package/lib/domain/knowledge/values/Quality.js +81 -0
  21. package/lib/domain/knowledge/values/Reasoning.js +70 -0
  22. package/lib/domain/knowledge/values/Relations.js +142 -0
  23. package/lib/domain/knowledge/values/Stats.js +72 -0
  24. package/lib/domain/knowledge/values/index.js +9 -0
  25. package/lib/external/ai/AiProvider.js +85 -11
  26. package/lib/external/mcp/McpServer.js +7 -5
  27. package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +18 -2
  28. package/lib/external/mcp/handlers/bootstrap.js +116 -11
  29. package/lib/external/mcp/handlers/browse.js +76 -73
  30. package/lib/external/mcp/handlers/candidate.js +26 -275
  31. package/lib/external/mcp/handlers/guard.js +2 -0
  32. package/lib/external/mcp/handlers/knowledge.js +267 -0
  33. package/lib/external/mcp/handlers/structure.js +25 -23
  34. package/lib/external/mcp/handlers/system.js +10 -12
  35. package/lib/external/mcp/tools.js +134 -140
  36. package/lib/http/HttpServer.js +14 -8
  37. package/lib/http/routes/ai.js +4 -3
  38. package/lib/http/routes/extract.js +48 -4
  39. package/lib/http/routes/knowledge.js +246 -0
  40. package/lib/http/routes/search.js +12 -17
  41. package/lib/infrastructure/database/migrations/016_unified_knowledge_entries.js +395 -0
  42. package/lib/infrastructure/database/migrations/017_camelcase_knowledge_entries.js +107 -0
  43. package/lib/infrastructure/external/XcodeAutomation.js +187 -103
  44. package/lib/injection/ServiceContainer.js +69 -60
  45. package/lib/repository/knowledge/KnowledgeRepository.impl.js +338 -0
  46. package/lib/service/automation/DirectiveDetector.js +2 -3
  47. package/lib/service/automation/FileWatcher.js +59 -28
  48. package/lib/service/automation/XcodeIntegration.js +931 -156
  49. package/lib/service/automation/handlers/AlinkHandler.js +5 -4
  50. package/lib/service/automation/handlers/CreateHandler.js +53 -19
  51. package/lib/service/automation/handlers/DraftHandler.js +1 -1
  52. package/lib/service/automation/handlers/GuardHandler.js +183 -20
  53. package/lib/service/automation/handlers/SearchHandler.js +25 -22
  54. package/lib/service/candidate/SimilarityService.js +2 -2
  55. package/lib/service/chat/AnalystAgent.js +9 -0
  56. package/lib/service/chat/CandidateGuardrail.js +22 -11
  57. package/lib/service/chat/ChatAgent.js +132 -54
  58. package/lib/service/chat/ContextWindow.js +5 -5
  59. package/lib/service/chat/HandoffProtocol.js +1 -0
  60. package/lib/service/chat/ProducerAgent.js +40 -13
  61. package/lib/service/chat/ReasoningLayer.js +854 -0
  62. package/lib/service/chat/ReasoningTrace.js +329 -0
  63. package/lib/service/chat/tools.js +308 -205
  64. package/lib/service/cursor/CursorDeliveryPipeline.js +279 -0
  65. package/lib/service/cursor/KnowledgeCompressor.js +87 -0
  66. package/lib/service/cursor/RulesGenerator.js +168 -0
  67. package/lib/service/cursor/SkillsSyncer.js +268 -0
  68. package/lib/service/cursor/TokenBudget.js +58 -0
  69. package/lib/service/cursor/TopicClassifier.js +141 -0
  70. package/lib/service/guard/GuardCheckEngine.js +99 -10
  71. package/lib/service/guard/GuardService.js +57 -46
  72. package/lib/service/knowledge/ConfidenceRouter.js +159 -0
  73. package/lib/service/knowledge/KnowledgeFileWriter.js +595 -0
  74. package/lib/service/knowledge/KnowledgeService.js +802 -0
  75. package/lib/service/recipe/RecipeParser.js +3 -12
  76. package/lib/service/search/SearchEngine.js +67 -22
  77. package/lib/service/skills/SignalCollector.js +14 -9
  78. package/lib/service/skills/SkillAdvisor.js +13 -11
  79. package/lib/service/snippet/SnippetFactory.js +5 -5
  80. package/lib/service/spm/SpmService.js +15 -48
  81. package/lib/shared/RecipeReadinessChecker.js +6 -11
  82. package/package.json +1 -1
  83. package/scripts/install-cursor-skill.js +0 -6
  84. package/scripts/migrate-md-to-knowledge.mjs +364 -0
  85. package/skills/autosnippet-analysis/SKILL.md +15 -7
  86. package/skills/autosnippet-candidates/SKILL.md +8 -8
  87. package/skills/autosnippet-coldstart/SKILL.md +8 -4
  88. package/skills/autosnippet-concepts/SKILL.md +7 -6
  89. package/skills/autosnippet-create/SKILL.md +13 -13
  90. package/skills/autosnippet-intent/SKILL.md +3 -2
  91. package/skills/autosnippet-lifecycle/SKILL.md +5 -5
  92. package/skills/autosnippet-recipes/SKILL.md +18 -6
  93. package/templates/constitution.yaml +1 -1
  94. package/templates/copilot-instructions.md +6 -6
  95. package/templates/recipes-setup/README.md +3 -3
  96. package/dashboard/dist/assets/index-CqJRvYRL.js +0 -197
  97. package/dashboard/dist/assets/index-DICm9PNa.css +0 -1
  98. package/lib/cli/CandidateSyncService.js +0 -261
  99. package/lib/cli/SyncService.js +0 -356
  100. package/lib/domain/candidate/Candidate.js +0 -196
  101. package/lib/domain/candidate/CandidateRepository.js +0 -107
  102. package/lib/domain/candidate/Reasoning.js +0 -52
  103. package/lib/domain/recipe/Recipe.js +0 -421
  104. package/lib/domain/recipe/RecipeRepository.js +0 -54
  105. package/lib/domain/types/CandidateStatus.js +0 -52
  106. package/lib/http/routes/candidates.js +0 -559
  107. package/lib/http/routes/recipes.js +0 -397
  108. package/lib/repository/candidate/CandidateRepository.impl.js +0 -230
  109. package/lib/repository/recipe/RecipeRepository.impl.js +0 -498
  110. package/lib/service/candidate/CandidateAggregator.js +0 -52
  111. package/lib/service/candidate/CandidateFileWriter.js +0 -383
  112. package/lib/service/candidate/CandidateService.js +0 -1001
  113. package/lib/service/recipe/RecipeFileWriter.js +0 -514
  114. package/lib/service/recipe/RecipeService.js +0 -786
  115. package/lib/service/recipe/RecipeStatsTracker.js +0 -148
@@ -1,148 +0,0 @@
1
- /**
2
- * RecipeStatsTracker — Recipe 使用统计追踪器
3
- * 记录 guard/human/ai 三档使用次数,计算热度和权威分
4
- * 持久化到 AutoSnippet/recipe-stats.json(Git 友好)
5
- */
6
-
7
- import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync } from 'node:fs';
8
- import { join, dirname } from 'node:path';
9
- import Logger from '../../infrastructure/logging/Logger.js';
10
- import pathGuard from '../../shared/PathGuard.js';
11
-
12
- const SCHEMA_VERSION = 1;
13
- const DEFAULT_HEAT_WEIGHTS = { guard: 1.0, human: 2.0, ai: 1.5 };
14
- const AUTHORITY_ALPHA = 0.6;
15
-
16
- export class RecipeStatsTracker {
17
- #statsPath;
18
- #data; // { schemaVersion, byTrigger: {}, byFile: {} }
19
-
20
- constructor(projectRoot, options = {}) {
21
- const kbDir = options.knowledgeBaseDir || 'AutoSnippet';
22
- this.#statsPath = join(projectRoot, kbDir, 'recipe-stats.json');
23
- pathGuard.assertProjectWriteSafe(this.#statsPath);
24
- this.#migrateOldPath(projectRoot, options.internalDir || '.autosnippet');
25
- this.#data = this.#load();
26
- }
27
-
28
- /**
29
- * 记录一次 Recipe 使用
30
- * @param {{ trigger?: string, recipeFilePath?: string, source: 'guard'|'human'|'ai' }} usage
31
- */
32
- recordUsage(usage) {
33
- const { trigger, recipeFilePath, source = 'human' } = usage;
34
- const key = trigger || recipeFilePath;
35
- if (!key) return;
36
-
37
- const store = trigger ? this.#data.byTrigger : this.#data.byFile;
38
- if (!store[key]) {
39
- store[key] = { guardUsageCount: 0, humanUsageCount: 0, aiUsageCount: 0, lastUsedAt: null, authority: 0 };
40
- }
41
-
42
- const entry = store[key];
43
- if (source === 'guard') entry.guardUsageCount++;
44
- else if (source === 'ai') entry.aiUsageCount++;
45
- else entry.humanUsageCount++;
46
- entry.lastUsedAt = new Date().toISOString();
47
-
48
- this.#save();
49
- }
50
-
51
- /**
52
- * 设置权威分 (0-5)
53
- */
54
- setAuthority(key, value) {
55
- const entry = this.#data.byTrigger[key] || this.#data.byFile[key];
56
- if (entry) {
57
- entry.authority = Math.max(0, Math.min(5, value));
58
- this.#save();
59
- }
60
- }
61
-
62
- /**
63
- * 计算使用热度
64
- * heat = w_guard * guard + w_human * human + w_ai * ai
65
- */
66
- getUsageHeat(entry, weights = DEFAULT_HEAT_WEIGHTS) {
67
- if (!entry) return 0;
68
- return (entry.guardUsageCount || 0) * weights.guard
69
- + (entry.humanUsageCount || 0) * weights.human
70
- + (entry.aiUsageCount || 0) * weights.ai;
71
- }
72
-
73
- /**
74
- * 综合权威分 = α * normalize(heat) + (1-α) * (authority/5)
75
- */
76
- getAuthorityScore(entry, allEntries = null) {
77
- if (!entry) return 0;
78
- const heat = this.getUsageHeat(entry);
79
- const maxHeat = allEntries
80
- ? Math.max(...Object.values(allEntries).map(e => this.getUsageHeat(e)), 1)
81
- : Math.max(heat, 1);
82
- const normalizedHeat = heat / maxHeat;
83
- const normalizedAuthority = (entry.authority || 0) / 5;
84
- return AUTHORITY_ALPHA * normalizedHeat + (1 - AUTHORITY_ALPHA) * normalizedAuthority;
85
- }
86
-
87
- /**
88
- * 获取所有统计
89
- */
90
- getStats() {
91
- return { ...this.#data };
92
- }
93
-
94
- /**
95
- * 获取指定 Recipe 的统计
96
- */
97
- getEntryStats(key) {
98
- return this.#data.byTrigger[key] || this.#data.byFile[key] || null;
99
- }
100
-
101
- /**
102
- * 获取热门 Recipes (top N)
103
- */
104
- getTopRecipes(n = 10) {
105
- const allEntries = { ...this.#data.byTrigger, ...this.#data.byFile };
106
- return Object.entries(allEntries)
107
- .map(([key, entry]) => ({
108
- key,
109
- heat: this.getUsageHeat(entry),
110
- authorityScore: this.getAuthorityScore(entry, allEntries),
111
- ...entry,
112
- }))
113
- .sort((a, b) => b.authorityScore - a.authorityScore)
114
- .slice(0, n);
115
- }
116
-
117
- #load() {
118
- try {
119
- if (existsSync(this.#statsPath)) {
120
- return JSON.parse(readFileSync(this.#statsPath, 'utf-8'));
121
- }
122
- } catch { /* silent */ }
123
- return { schemaVersion: SCHEMA_VERSION, byTrigger: {}, byFile: {} };
124
- }
125
-
126
- #save() {
127
- try {
128
- const dir = dirname(this.#statsPath);
129
- if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
130
- writeFileSync(this.#statsPath, JSON.stringify(this.#data, null, 2));
131
- } catch (err) {
132
- Logger.getInstance().warn('RecipeStatsTracker: failed to persist stats', { error: err.message });
133
- }
134
- }
135
-
136
- #migrateOldPath(projectRoot, internalDir) {
137
- try {
138
- const oldPath = join(projectRoot, internalDir, 'recipe-stats.json');
139
- if (existsSync(oldPath) && !existsSync(this.#statsPath)) {
140
- const content = readFileSync(oldPath, 'utf-8');
141
- const dir = dirname(this.#statsPath);
142
- if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
143
- writeFileSync(this.#statsPath, content);
144
- unlinkSync(oldPath);
145
- }
146
- } catch { /* 迁移失败不阻断启动 */ }
147
- }
148
- }