autosnippet 2.8.3 → 2.10.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 (110) hide show
  1. package/README.md +5 -5
  2. package/bin/cli.js +5 -33
  3. package/config/constitution.yaml +9 -2
  4. package/dashboard/dist/assets/{icons-B_Xg4B-s.js → icons-BkT3XrKf.js} +105 -100
  5. package/dashboard/dist/assets/index-BsB7DzW4.css +1 -0
  6. package/dashboard/dist/assets/index-DdmQMrJJ.js +155 -0
  7. package/dashboard/dist/index.html +3 -3
  8. package/lib/cli/AiScanService.js +13 -11
  9. package/lib/cli/KnowledgeSyncService.js +343 -0
  10. package/lib/cli/SetupService.js +9 -27
  11. package/lib/core/ast/ProjectGraph.js +160 -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 +351 -0
  15. package/lib/domain/knowledge/KnowledgeRepository.js +123 -0
  16. package/lib/domain/knowledge/Lifecycle.js +109 -0
  17. package/lib/domain/knowledge/index.js +27 -0
  18. package/lib/domain/knowledge/values/Constraints.js +125 -0
  19. package/lib/domain/knowledge/values/Content.js +86 -0
  20. package/lib/domain/knowledge/values/Quality.js +93 -0
  21. package/lib/domain/knowledge/values/Reasoning.js +69 -0
  22. package/lib/domain/knowledge/values/Relations.js +168 -0
  23. package/lib/domain/knowledge/values/Stats.js +87 -0
  24. package/lib/domain/knowledge/values/index.js +9 -0
  25. package/lib/external/ai/AiProvider.js +48 -0
  26. package/lib/external/ai/providers/GoogleGeminiProvider.js +12 -3
  27. package/lib/external/mcp/McpServer.js +7 -5
  28. package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +3 -2
  29. package/lib/external/mcp/handlers/bootstrap.js +121 -12
  30. package/lib/external/mcp/handlers/browse.js +77 -73
  31. package/lib/external/mcp/handlers/candidate.js +29 -276
  32. package/lib/external/mcp/handlers/guard.js +2 -0
  33. package/lib/external/mcp/handlers/knowledge.js +205 -0
  34. package/lib/external/mcp/handlers/skill.js +4 -2
  35. package/lib/external/mcp/handlers/structure.js +25 -23
  36. package/lib/external/mcp/handlers/system.js +10 -12
  37. package/lib/external/mcp/tools.js +125 -138
  38. package/lib/http/HttpServer.js +4 -8
  39. package/lib/http/middleware/requestLogger.js +3 -3
  40. package/lib/http/routes/ai.js +17 -1
  41. package/lib/http/routes/extract.js +48 -4
  42. package/lib/http/routes/knowledge.js +246 -0
  43. package/lib/http/routes/search.js +12 -17
  44. package/lib/http/routes/skills.js +44 -1
  45. package/lib/infrastructure/cache/GraphCache.js +143 -0
  46. package/lib/infrastructure/database/migrations/015_create_token_usage.js +27 -0
  47. package/lib/infrastructure/database/migrations/016_unified_knowledge_entries.js +395 -0
  48. package/lib/infrastructure/external/XcodeAutomation.js +187 -103
  49. package/lib/infrastructure/realtime/RealtimeService.js +14 -2
  50. package/lib/injection/ServiceContainer.js +164 -63
  51. package/lib/repository/knowledge/KnowledgeRepository.impl.js +373 -0
  52. package/lib/repository/token/TokenUsageStore.js +162 -0
  53. package/lib/service/automation/DirectiveDetector.js +2 -3
  54. package/lib/service/automation/FileWatcher.js +67 -28
  55. package/lib/service/automation/XcodeIntegration.js +931 -156
  56. package/lib/service/automation/handlers/AlinkHandler.js +6 -4
  57. package/lib/service/automation/handlers/CreateHandler.js +53 -18
  58. package/lib/service/automation/handlers/GuardHandler.js +183 -20
  59. package/lib/service/automation/handlers/SearchHandler.js +35 -17
  60. package/lib/service/chat/AnalystAgent.js +25 -14
  61. package/lib/service/chat/CandidateGuardrail.js +1 -1
  62. package/lib/service/chat/ChatAgent.js +280 -48
  63. package/lib/service/chat/ContextWindow.js +92 -8
  64. package/lib/service/chat/HandoffProtocol.js +26 -1
  65. package/lib/service/chat/ProducerAgent.js +11 -9
  66. package/lib/service/chat/tools.js +298 -194
  67. package/lib/service/guard/GuardCheckEngine.js +114 -10
  68. package/lib/service/guard/GuardService.js +59 -48
  69. package/lib/service/knowledge/ConfidenceRouter.js +159 -0
  70. package/lib/service/knowledge/KnowledgeFileWriter.js +602 -0
  71. package/lib/service/knowledge/KnowledgeService.js +725 -0
  72. package/lib/service/search/SearchEngine.js +92 -19
  73. package/lib/service/skills/SignalCollector.js +15 -9
  74. package/lib/service/skills/SkillAdvisor.js +13 -11
  75. package/lib/service/snippet/SnippetFactory.js +5 -5
  76. package/lib/service/spm/SpmService.js +119 -18
  77. package/package.json +1 -1
  78. package/scripts/install-cursor-skill.js +0 -6
  79. package/scripts/migrate-md-to-knowledge.mjs +364 -0
  80. package/skills/autosnippet-analysis/SKILL.md +15 -7
  81. package/skills/autosnippet-candidates/SKILL.md +6 -6
  82. package/skills/autosnippet-coldstart/SKILL.md +7 -3
  83. package/skills/autosnippet-concepts/SKILL.md +7 -6
  84. package/skills/autosnippet-create/SKILL.md +13 -13
  85. package/skills/autosnippet-intent/SKILL.md +3 -2
  86. package/skills/autosnippet-lifecycle/SKILL.md +5 -5
  87. package/skills/autosnippet-recipes/SKILL.md +16 -4
  88. package/templates/constitution.yaml +1 -1
  89. package/templates/copilot-instructions.md +6 -6
  90. package/templates/recipes-setup/README.md +3 -3
  91. package/dashboard/dist/assets/index-CkIih2CC.css +0 -1
  92. package/dashboard/dist/assets/index-Duc8Qk-c.js +0 -197
  93. package/lib/cli/CandidateSyncService.js +0 -261
  94. package/lib/cli/SyncService.js +0 -356
  95. package/lib/domain/candidate/Candidate.js +0 -196
  96. package/lib/domain/candidate/CandidateRepository.js +0 -107
  97. package/lib/domain/candidate/Reasoning.js +0 -52
  98. package/lib/domain/recipe/Recipe.js +0 -421
  99. package/lib/domain/recipe/RecipeRepository.js +0 -54
  100. package/lib/domain/types/CandidateStatus.js +0 -52
  101. package/lib/http/routes/candidates.js +0 -559
  102. package/lib/http/routes/recipes.js +0 -397
  103. package/lib/repository/candidate/CandidateRepository.impl.js +0 -230
  104. package/lib/repository/recipe/RecipeRepository.impl.js +0 -498
  105. package/lib/service/candidate/CandidateAggregator.js +0 -52
  106. package/lib/service/candidate/CandidateFileWriter.js +0 -383
  107. package/lib/service/candidate/CandidateService.js +0 -973
  108. package/lib/service/recipe/RecipeFileWriter.js +0 -514
  109. package/lib/service/recipe/RecipeService.js +0 -786
  110. 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
- }