autosnippet 3.0.0 → 3.0.2

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 (290) hide show
  1. package/README.md +230 -324
  2. package/bin/api-server.js +1 -1
  3. package/bin/cli.js +204 -244
  4. package/bin/mcp-server.js +5 -3
  5. package/config/knowledge-base.config.js +132 -132
  6. package/dashboard/dist/assets/{icons-CEfgGaZi.js → icons-Cdq22n2i.js} +95 -100
  7. package/dashboard/dist/assets/index-ClkyPkDX.js +133 -0
  8. package/dashboard/dist/assets/index-t4QrJwv1.css +1 -0
  9. package/dashboard/dist/index.html +3 -3
  10. package/lib/bootstrap.js +8 -8
  11. package/lib/cli/AiScanService.js +86 -40
  12. package/lib/cli/KnowledgeSyncService.js +113 -74
  13. package/lib/cli/SetupService.js +439 -277
  14. package/lib/cli/UpgradeService.js +63 -100
  15. package/lib/core/AstAnalyzer.js +276 -597
  16. package/lib/core/ast/ProjectGraph.js +101 -40
  17. package/lib/core/ast/ensure-grammars.js +232 -0
  18. package/lib/core/ast/index.js +115 -0
  19. package/lib/core/ast/lang-dart.js +661 -0
  20. package/lib/core/ast/lang-go.js +530 -0
  21. package/lib/core/ast/lang-java.js +435 -0
  22. package/lib/core/ast/lang-javascript.js +272 -0
  23. package/lib/core/ast/lang-kotlin.js +423 -0
  24. package/lib/core/ast/lang-objc.js +388 -0
  25. package/lib/core/ast/lang-python.js +371 -0
  26. package/lib/core/ast/lang-swift.js +337 -0
  27. package/lib/core/ast/lang-typescript.js +503 -0
  28. package/lib/core/capability/CapabilityProbe.js +18 -9
  29. package/lib/core/constitution/Constitution.js +2 -3
  30. package/lib/core/constitution/ConstitutionValidator.js +65 -24
  31. package/lib/core/discovery/DartDiscoverer.js +534 -0
  32. package/lib/core/discovery/DiscovererRegistry.js +83 -0
  33. package/lib/core/discovery/GenericDiscoverer.js +225 -0
  34. package/lib/core/discovery/GoDiscoverer.js +541 -0
  35. package/lib/core/discovery/JvmDiscoverer.js +506 -0
  36. package/lib/core/discovery/NodeDiscoverer.js +466 -0
  37. package/lib/core/discovery/ProjectDiscoverer.js +93 -0
  38. package/lib/core/discovery/PythonDiscoverer.js +338 -0
  39. package/lib/core/discovery/SpmDiscoverer.js +5 -0
  40. package/lib/core/discovery/index.js +53 -0
  41. package/lib/core/enhancement/EnhancementPack.js +71 -0
  42. package/lib/core/enhancement/EnhancementRegistry.js +47 -0
  43. package/lib/core/enhancement/android-enhancement.js +102 -0
  44. package/lib/core/enhancement/django-enhancement.js +70 -0
  45. package/lib/core/enhancement/fastapi-enhancement.js +63 -0
  46. package/lib/core/enhancement/go-grpc-enhancement.js +152 -0
  47. package/lib/core/enhancement/go-web-enhancement.js +201 -0
  48. package/lib/core/enhancement/index.js +65 -0
  49. package/lib/core/enhancement/node-server-enhancement.js +88 -0
  50. package/lib/core/enhancement/react-enhancement.js +86 -0
  51. package/lib/core/enhancement/spring-enhancement.js +112 -0
  52. package/lib/core/enhancement/vue-enhancement.js +96 -0
  53. package/lib/core/gateway/Gateway.js +8 -9
  54. package/lib/core/gateway/GatewayActionRegistry.js +1 -1
  55. package/lib/core/permission/PermissionManager.js +12 -8
  56. package/lib/domain/index.js +13 -9
  57. package/lib/domain/knowledge/KnowledgeEntry.js +111 -101
  58. package/lib/domain/knowledge/KnowledgeRepository.js +0 -1
  59. package/lib/domain/knowledge/Lifecycle.js +22 -22
  60. package/lib/domain/knowledge/index.js +9 -12
  61. package/lib/domain/knowledge/values/Constraints.js +31 -21
  62. package/lib/domain/knowledge/values/Content.js +21 -13
  63. package/lib/domain/knowledge/values/Quality.js +31 -18
  64. package/lib/domain/knowledge/values/Reasoning.js +20 -12
  65. package/lib/domain/knowledge/values/Relations.js +37 -25
  66. package/lib/domain/knowledge/values/Stats.js +18 -12
  67. package/lib/domain/knowledge/values/index.js +4 -3
  68. package/lib/domain/snippet/Snippet.js +35 -10
  69. package/lib/external/ai/AiFactory.js +48 -16
  70. package/lib/external/ai/AiProvider.js +184 -90
  71. package/lib/external/ai/providers/ClaudeProvider.js +25 -12
  72. package/lib/external/ai/providers/GoogleGeminiProvider.js +59 -30
  73. package/lib/external/ai/providers/MockProvider.js +9 -3
  74. package/lib/external/ai/providers/OpenAiProvider.js +51 -29
  75. package/lib/external/mcp/McpServer.js +66 -36
  76. package/lib/external/mcp/errorHandler.js +23 -11
  77. package/lib/external/mcp/handlers/LanguageExtensions.js +138 -53
  78. package/lib/external/mcp/handlers/TargetClassifier.js +52 -16
  79. package/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.js +81 -20
  80. package/lib/external/mcp/handlers/bootstrap/pipeline/EpisodicMemory.js +71 -42
  81. package/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.js +9 -17
  82. package/lib/external/mcp/handlers/bootstrap/pipeline/ToolResultCache.js +14 -9
  83. package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-context.js +15 -7
  84. package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +352 -153
  85. package/lib/external/mcp/handlers/bootstrap/pipeline/tier-scheduler.js +52 -12
  86. package/lib/external/mcp/handlers/bootstrap/skills.js +143 -39
  87. package/lib/external/mcp/handlers/bootstrap.js +691 -168
  88. package/lib/external/mcp/handlers/browse.js +66 -22
  89. package/lib/external/mcp/handlers/candidate.js +118 -35
  90. package/lib/external/mcp/handlers/consolidated.js +49 -17
  91. package/lib/external/mcp/handlers/guard.js +104 -39
  92. package/lib/external/mcp/handlers/knowledge.js +60 -36
  93. package/lib/external/mcp/handlers/search.js +43 -14
  94. package/lib/external/mcp/handlers/skill.js +120 -45
  95. package/lib/external/mcp/handlers/structure.js +240 -86
  96. package/lib/external/mcp/handlers/system.js +42 -12
  97. package/lib/external/mcp/handlers/wiki.js +58 -33
  98. package/lib/external/mcp/tools.js +306 -123
  99. package/lib/http/HttpServer.js +72 -47
  100. package/lib/http/middleware/RateLimiter.js +5 -3
  101. package/lib/http/middleware/errorHandler.js +6 -1
  102. package/lib/http/middleware/requestLogger.js +14 -3
  103. package/lib/http/middleware/roleResolver.js +30 -23
  104. package/lib/http/routes/ai.js +387 -265
  105. package/lib/http/routes/auth.js +81 -61
  106. package/lib/http/routes/candidates.js +430 -320
  107. package/lib/http/routes/commands.js +289 -189
  108. package/lib/http/routes/extract.js +158 -125
  109. package/lib/http/routes/guardRules.js +309 -217
  110. package/lib/http/routes/knowledge.js +213 -154
  111. package/lib/http/routes/modules.js +578 -0
  112. package/lib/http/routes/monitoring.js +6 -6
  113. package/lib/http/routes/recipes.js +104 -93
  114. package/lib/http/routes/search.js +361 -305
  115. package/lib/http/routes/skills.js +145 -98
  116. package/lib/http/routes/snippets.js +42 -30
  117. package/lib/http/routes/spm.js +3 -405
  118. package/lib/http/routes/violations.js +113 -93
  119. package/lib/http/routes/wiki.js +211 -170
  120. package/lib/http/utils/routeHelpers.js +3 -1
  121. package/lib/http/utils/sse-sessions.js +16 -6
  122. package/lib/http/utils/sse.js +15 -5
  123. package/lib/infrastructure/audit/AuditLogger.js +5 -2
  124. package/lib/infrastructure/audit/AuditStore.js +10 -7
  125. package/lib/infrastructure/cache/CacheService.js +3 -1
  126. package/lib/infrastructure/cache/GraphCache.js +8 -4
  127. package/lib/infrastructure/cache/UnifiedCacheAdapter.js +1 -1
  128. package/lib/infrastructure/config/ConfigLoader.js +9 -5
  129. package/lib/infrastructure/config/Defaults.js +30 -10
  130. package/lib/infrastructure/config/Paths.js +28 -8
  131. package/lib/infrastructure/config/TriggerSymbol.js +22 -10
  132. package/lib/infrastructure/database/DatabaseConnection.js +15 -10
  133. package/lib/infrastructure/database/migrations/001_initial_schema.js +0 -1
  134. package/lib/infrastructure/external/ClipboardManager.js +6 -2
  135. package/lib/infrastructure/external/NativeUi.js +50 -43
  136. package/lib/infrastructure/external/OpenBrowser.js +14 -17
  137. package/lib/infrastructure/external/XcodeAutomation.js +14 -258
  138. package/lib/infrastructure/logging/Logger.js +46 -30
  139. package/lib/infrastructure/monitoring/ErrorTracker.js +7 -5
  140. package/lib/infrastructure/monitoring/PerformanceMonitor.js +12 -4
  141. package/lib/infrastructure/paths/HeaderResolver.js +25 -9
  142. package/lib/infrastructure/paths/PathFinder.js +34 -12
  143. package/lib/infrastructure/plugin/PluginManager.js +26 -8
  144. package/lib/infrastructure/realtime/RealtimeService.js +2 -2
  145. package/lib/infrastructure/vector/Chunker.js +22 -7
  146. package/lib/infrastructure/vector/IndexingPipeline.js +46 -22
  147. package/lib/infrastructure/vector/JsonVectorAdapter.js +90 -53
  148. package/lib/infrastructure/vector/VectorStore.js +28 -10
  149. package/lib/injection/ServiceContainer.js +247 -93
  150. package/lib/platform/ios/index.js +63 -0
  151. package/lib/platform/ios/routes/spm.js +437 -0
  152. package/lib/platform/ios/snippet/PlaceholderConverter.js +55 -0
  153. package/lib/platform/ios/snippet/XcodeCodec.js +112 -0
  154. package/lib/{service → platform/ios}/spm/DependencyGraph.js +41 -17
  155. package/lib/{service → platform/ios}/spm/PackageSwiftParser.js +41 -14
  156. package/lib/{service → platform/ios}/spm/PolicyEngine.js +9 -4
  157. package/lib/platform/ios/spm/SpmDiscoverer.js +122 -0
  158. package/lib/{service → platform/ios}/spm/SpmService.js +385 -127
  159. package/lib/{service/automation → platform/ios/xcode}/SaveEventFilter.js +8 -7
  160. package/lib/platform/ios/xcode/XcodeAutomation.js +350 -0
  161. package/lib/{service/automation → platform/ios/xcode}/XcodeIntegration.js +325 -145
  162. package/lib/repository/base/BaseRepository.js +7 -9
  163. package/lib/repository/knowledge/KnowledgeRepository.impl.js +98 -75
  164. package/lib/repository/token/TokenUsageStore.js +4 -2
  165. package/lib/service/automation/ActionPipeline.js +1 -1
  166. package/lib/service/automation/AutomationOrchestrator.js +8 -4
  167. package/lib/service/automation/ContextCollector.js +7 -5
  168. package/lib/service/automation/DirectiveDetector.js +23 -16
  169. package/lib/service/automation/FileWatcher.js +112 -56
  170. package/lib/service/automation/TriggerResolver.js +6 -4
  171. package/lib/service/automation/handlers/AlinkHandler.js +24 -12
  172. package/lib/service/automation/handlers/CreateHandler.js +19 -20
  173. package/lib/service/automation/handlers/DraftHandler.js +14 -8
  174. package/lib/service/automation/handlers/GuardHandler.js +93 -63
  175. package/lib/service/automation/handlers/HeaderHandler.js +1 -6
  176. package/lib/service/automation/handlers/SearchHandler.js +155 -88
  177. package/lib/service/bootstrap/BootstrapTaskManager.js +77 -35
  178. package/lib/service/candidate/SimilarityService.js +25 -9
  179. package/lib/service/chat/AnalystAgent.js +50 -24
  180. package/lib/service/chat/CandidateGuardrail.js +143 -17
  181. package/lib/service/chat/ChatAgent.js +759 -243
  182. package/lib/service/chat/ContextWindow.js +116 -71
  183. package/lib/service/chat/ConversationStore.js +77 -36
  184. package/lib/service/chat/EpisodicConsolidator.js +47 -23
  185. package/lib/service/chat/HandoffProtocol.js +98 -22
  186. package/lib/service/chat/Memory.js +34 -14
  187. package/lib/service/chat/ProducerAgent.js +40 -20
  188. package/lib/service/chat/ProjectSemanticMemory.js +109 -78
  189. package/lib/service/chat/ReasoningLayer.js +148 -70
  190. package/lib/service/chat/ReasoningTrace.js +44 -32
  191. package/lib/service/chat/TaskPipeline.js +39 -19
  192. package/lib/service/chat/ToolRegistry.js +48 -29
  193. package/lib/service/chat/WorkingMemory.js +44 -18
  194. package/lib/service/chat/tools.js +1096 -494
  195. package/lib/service/context/RecipeExtractor.js +132 -51
  196. package/lib/service/cursor/CursorDeliveryPipeline.js +82 -37
  197. package/lib/service/cursor/KnowledgeCompressor.js +25 -22
  198. package/lib/service/cursor/RulesGenerator.js +13 -7
  199. package/lib/service/cursor/SkillsSyncer.js +77 -27
  200. package/lib/service/cursor/TokenBudget.js +2 -2
  201. package/lib/service/cursor/TopicClassifier.js +54 -20
  202. package/lib/service/guard/ComplianceReporter.js +55 -43
  203. package/lib/service/guard/ExclusionManager.js +67 -29
  204. package/lib/service/guard/GuardCheckEngine.js +381 -86
  205. package/lib/service/guard/GuardFeedbackLoop.js +22 -10
  206. package/lib/service/guard/GuardService.js +29 -19
  207. package/lib/service/guard/RuleLearner.js +55 -23
  208. package/lib/service/guard/SourceFileCollector.js +27 -20
  209. package/lib/service/guard/ViolationsStore.js +43 -38
  210. package/lib/service/knowledge/CodeEntityGraph.js +147 -82
  211. package/lib/service/knowledge/ConfidenceRouter.js +12 -10
  212. package/lib/service/knowledge/KnowledgeFileWriter.js +147 -56
  213. package/lib/service/knowledge/KnowledgeGraphService.js +81 -34
  214. package/lib/service/knowledge/KnowledgeService.js +222 -112
  215. package/lib/service/module/ModuleService.js +969 -0
  216. package/lib/service/quality/FeedbackCollector.js +27 -15
  217. package/lib/service/quality/QualityScorer.js +78 -24
  218. package/lib/service/recipe/RecipeCandidateValidator.js +110 -44
  219. package/lib/service/recipe/RecipeParser.js +78 -45
  220. package/lib/service/search/CoarseRanker.js +43 -28
  221. package/lib/service/search/CrossEncoderReranker.js +32 -21
  222. package/lib/service/search/InvertedIndex.js +21 -7
  223. package/lib/service/search/MultiSignalRanker.js +90 -28
  224. package/lib/service/search/RetrievalFunnel.js +45 -24
  225. package/lib/service/search/SearchEngine.js +255 -103
  226. package/lib/service/skills/EventAggregator.js +32 -15
  227. package/lib/service/skills/SignalCollector.js +140 -64
  228. package/lib/service/skills/SkillAdvisor.js +79 -42
  229. package/lib/service/skills/SkillHooks.js +16 -14
  230. package/lib/service/snippet/PlaceholderConverter.js +5 -0
  231. package/lib/service/snippet/SnippetFactory.js +116 -99
  232. package/lib/service/snippet/SnippetInstaller.js +234 -62
  233. package/lib/service/snippet/codecs/SnippetCodec.js +67 -0
  234. package/lib/service/snippet/codecs/VSCodeCodec.js +102 -0
  235. package/lib/service/snippet/codecs/XcodeCodec.js +5 -0
  236. package/lib/service/wiki/WikiGenerator.js +637 -263
  237. package/lib/shared/DimensionCopyRegistry.js +472 -0
  238. package/lib/shared/LanguageService.js +399 -0
  239. package/lib/shared/PathGuard.js +45 -28
  240. package/lib/shared/RecipeReadinessChecker.js +72 -12
  241. package/lib/shared/constants.js +41 -41
  242. package/lib/shared/errors/BaseError.js +2 -2
  243. package/lib/shared/errors/index.js +4 -4
  244. package/lib/shared/similarity.js +25 -8
  245. package/lib/shared/token-utils.js +6 -2
  246. package/lib/shared/utils/common.js +12 -4
  247. package/package.json +49 -13
  248. package/scripts/bench-real-projects.mjs +256 -0
  249. package/scripts/build-native-ui.js +30 -30
  250. package/scripts/clear-old-vector-index.js +5 -35
  251. package/scripts/clear-vector-cache.js +7 -37
  252. package/scripts/collect-test-project-stats.mjs +160 -0
  253. package/scripts/diagnose-mcp.js +41 -32
  254. package/scripts/ensure-parse-package.js +6 -9
  255. package/scripts/generate-recipe-drafts.js +116 -77
  256. package/scripts/init-db.js +3 -20
  257. package/scripts/init-snippets.js +305 -0
  258. package/scripts/init-vector-db.js +173 -170
  259. package/scripts/install-cursor-skill.js +148 -104
  260. package/scripts/install-full.js +8 -21
  261. package/scripts/install-vscode-copilot.js +146 -145
  262. package/scripts/migrate-md-to-knowledge.mjs +139 -151
  263. package/scripts/postinstall-safe.js +5 -17
  264. package/scripts/recipe-audit.js +106 -82
  265. package/scripts/release.js +283 -323
  266. package/scripts/setup-mcp-config.js +60 -52
  267. package/scripts/verify-context-api.js +20 -20
  268. package/skills/autosnippet-analysis/SKILL.md +10 -6
  269. package/skills/autosnippet-candidates/SKILL.md +27 -26
  270. package/skills/autosnippet-coldstart/SKILL.md +555 -38
  271. package/skills/autosnippet-concepts/SKILL.md +349 -337
  272. package/skills/autosnippet-create/SKILL.md +5 -5
  273. package/skills/autosnippet-reference-dart/SKILL.md +543 -0
  274. package/skills/autosnippet-reference-go/SKILL.md +539 -0
  275. package/skills/autosnippet-reference-java/SKILL.md +534 -0
  276. package/skills/autosnippet-reference-jsts/SKILL.md +41 -9
  277. package/skills/autosnippet-reference-kotlin/SKILL.md +526 -0
  278. package/skills/autosnippet-reference-objc/SKILL.md +29 -6
  279. package/skills/autosnippet-reference-python/SKILL.md +800 -0
  280. package/skills/autosnippet-reference-swift/SKILL.md +70 -14
  281. package/skills/autosnippet-structure/SKILL.md +4 -4
  282. package/templates/cursor-rules/autosnippet-conventions.mdc +2 -2
  283. package/templates/recipes-setup/README.md +2 -2
  284. package/templates/recipes-setup/_template.md +1 -1
  285. package/dashboard/dist/assets/index-Bun3ld_J.css +0 -1
  286. package/dashboard/dist/assets/index-_Sk_Dmg3.js +0 -143
  287. package/resources/asd-entry/main.swift +0 -159
  288. package/scripts/build-asd-entry.js +0 -51
  289. package/scripts/init-xcode-snippets.js +0 -311
  290. package/template.json +0 -39
@@ -6,29 +6,29 @@
6
6
  * 使用:node scripts/release.js [patch|minor|major]
7
7
  */
8
8
 
9
- import { fileURLToPath } from 'node:url';
10
9
  import { dirname } from 'node:path';
10
+ import { fileURLToPath } from 'node:url';
11
+
11
12
  const __filename = fileURLToPath(import.meta.url);
12
13
  const __dirname = dirname(__filename);
13
14
 
14
15
  import { execSync } from 'node:child_process';
15
16
  import fs from 'node:fs';
16
- import path from 'node:path';
17
17
  import { createRequire } from 'node:module';
18
+ import path from 'node:path';
19
+
18
20
  const require = createRequire(import.meta.url);
19
21
  // 颜色输出
20
- const colors = {
22
+ const _colors = {
21
23
  reset: '\x1b[0m',
22
24
  green: '\x1b[32m',
23
25
  red: '\x1b[31m',
24
26
  yellow: '\x1b[33m',
25
27
  blue: '\x1b[36m',
26
- bold: '\x1b[1m'
28
+ bold: '\x1b[1m',
27
29
  };
28
30
 
29
- function log(message, color = 'reset') {
30
- console.log(`${colors[color]}${message}${colors.reset}`);
31
- }
31
+ function log(message, color = 'reset') {}
32
32
 
33
33
  function success(message) {
34
34
  log(`✅ ${message}`, 'green');
@@ -54,307 +54,290 @@ function header(message) {
54
54
 
55
55
  function exec(command, options = {}) {
56
56
  try {
57
- return execSync(command, {
58
- encoding: 'utf8',
59
- stdio: options.silent ? 'pipe' : 'inherit',
60
- ...options
61
- });
57
+ return execSync(command, {
58
+ encoding: 'utf8',
59
+ stdio: options.silent ? 'pipe' : 'inherit',
60
+ ...options,
61
+ });
62
62
  } catch (err) {
63
- if (!options.ignoreError) {
64
- throw err;
65
- }
66
- return null;
63
+ if (!options.ignoreError) {
64
+ throw err;
65
+ }
66
+ return null;
67
67
  }
68
68
  }
69
69
 
70
70
  // 检查项
71
71
  class ReleaseChecker {
72
72
  constructor() {
73
- this.errors = [];
74
- this.warnings = [];
73
+ this.errors = [];
74
+ this.warnings = [];
75
75
  }
76
76
 
77
77
  // 检查 Git 状态
78
78
  checkGitStatus() {
79
- header('Git 状态检查');
80
-
81
- // 检查分支
82
- const branch = exec('git branch --show-current', { silent: true })?.trim();
83
- if (branch !== 'main' && branch !== 'master') {
84
- this.errors.push(`当前分支不是 main/master: ${branch}`);
85
- error(`当前分支: ${branch}`);
86
- } else {
87
- success(`当前分支: ${branch}`);
88
- }
89
-
90
- // 检查工作区
91
- const status = exec('git status --short', { silent: true });
92
- if (status && status.trim()) {
93
- this.errors.push('工作区有未提交的变更');
94
- error('工作区不干净:');
95
- console.log(status);
96
- } else {
97
- success('工作区干净');
98
- }
99
-
100
- // 检查远程同步
101
- try {
102
- exec('git fetch origin', { silent: true });
103
- const behind = exec('git rev-list HEAD..origin/main --count', { silent: true, ignoreError: true })?.trim();
104
- if (behind && parseInt(behind) > 0) {
105
- this.warnings.push(`本地落后远程 ${behind} 个提交`);
106
- warning(`需要先 pull: git pull origin main`);
79
+ header('Git 状态检查');
80
+
81
+ // 检查分支
82
+ const branch = exec('git branch --show-current', { silent: true })?.trim();
83
+ if (branch !== 'main' && branch !== 'master') {
84
+ this.errors.push(`当前分支不是 main/master: ${branch}`);
85
+ error(`当前分支: ${branch}`);
107
86
  } else {
108
- success('与远程同步');
87
+ success(`当前分支: ${branch}`);
88
+ }
89
+
90
+ // 检查工作区
91
+ const status = exec('git status --short', { silent: true });
92
+ if (status?.trim()) {
93
+ this.errors.push('工作区有未提交的变更');
94
+ error('工作区不干净:');
95
+ } else {
96
+ success('工作区干净');
97
+ }
98
+
99
+ // 检查远程同步
100
+ try {
101
+ exec('git fetch origin', { silent: true });
102
+ const behind = exec('git rev-list HEAD..origin/main --count', {
103
+ silent: true,
104
+ ignoreError: true,
105
+ })?.trim();
106
+ if (behind && parseInt(behind) > 0) {
107
+ this.warnings.push(`本地落后远程 ${behind} 个提交`);
108
+ warning(`需要先 pull: git pull origin main`);
109
+ } else {
110
+ success('与远程同步');
111
+ }
112
+ } catch (_err) {
113
+ warning('无法检查远程同步状态');
109
114
  }
110
- } catch (err) {
111
- warning('无法检查远程同步状态');
112
- }
113
115
  }
114
116
 
115
117
  // 检查 Node.js 环境
116
118
  checkNodeEnvironment() {
117
- header('Node.js 环境检查');
118
-
119
- const nodeVersion = process.version;
120
- const majorVersion = parseInt(nodeVersion.slice(1).split('.')[0]);
121
-
122
- if (majorVersion < 16) {
123
- this.errors.push(`Node.js 版本过低: ${nodeVersion} (需要 >=16)`);
124
- error(`Node.js: ${nodeVersion}`);
125
- } else {
126
- success(`Node.js: ${nodeVersion}`);
127
- }
128
-
129
- // 检查环境变量配置
130
- const envPath = path.join(__dirname, '../.env');
131
- if (!fs.existsSync(envPath)) {
132
- this.errors.push('.env 文件不存在');
133
- error('.env: 不存在');
134
- } else {
135
- const envContent = fs.readFileSync(envPath, 'utf8');
136
- const nodeEnv = envContent.match(/NODE_ENV=(\w+)/)?.[1];
137
-
138
- if (nodeEnv === 'production') {
139
- this.errors.push('.env 已是生产环境,发布前应该是开发环境');
140
- error(`环境: ${nodeEnv} (应该是 development)`);
119
+ header('Node.js 环境检查');
120
+
121
+ const nodeVersion = process.version;
122
+ const majorVersion = parseInt(nodeVersion.slice(1).split('.')[0]);
123
+
124
+ if (majorVersion < 16) {
125
+ this.errors.push(`Node.js 版本过低: ${nodeVersion} (需要 >=16)`);
126
+ error(`Node.js: ${nodeVersion}`);
141
127
  } else {
142
- success(`环境: ${nodeEnv || 'development'}`);
128
+ success(`Node.js: ${nodeVersion}`);
143
129
  }
144
-
145
- // 检查是否有备份
146
- const backupPath = path.join(__dirname, '../.env.backup');
147
- if (fs.existsSync(backupPath)) {
148
- warning('.env.backup 已存在,可能有未完成的发布');
130
+
131
+ // 检查环境变量配置
132
+ const envPath = path.join(__dirname, '../.env');
133
+ if (!fs.existsSync(envPath)) {
134
+ this.errors.push('.env 文件不存在');
135
+ error('.env: 不存在');
136
+ } else {
137
+ const envContent = fs.readFileSync(envPath, 'utf8');
138
+ const nodeEnv = envContent.match(/NODE_ENV=(\w+)/)?.[1];
139
+
140
+ if (nodeEnv === 'production') {
141
+ this.errors.push('.env 已是生产环境,发布前应该是开发环境');
142
+ error(`环境: ${nodeEnv} (应该是 development)`);
143
+ } else {
144
+ success(`环境: ${nodeEnv || 'development'}`);
145
+ }
146
+
147
+ // 检查是否有备份
148
+ const backupPath = path.join(__dirname, '../.env.backup');
149
+ if (fs.existsSync(backupPath)) {
150
+ warning('.env.backup 已存在,可能有未完成的发布');
151
+ }
149
152
  }
150
153
  }
151
- }
152
154
 
153
155
  // 检查并构建前端(生产环境)
154
156
  buildFrontend() {
155
- header('构建前端(生产环境)');
156
-
157
- // 备份 .env
158
- info('备份 .env 文件...');
159
- const envPath = path.join(__dirname, '../.env');
160
- const backupPath = path.join(__dirname, '../.env.backup');
161
-
162
- if (fs.existsSync(envPath)) {
163
- fs.copyFileSync(envPath, backupPath);
164
- success('.env 已备份');
165
- }
166
-
167
- // 切换到生产环境
168
- info('切换到生产环境...');
169
- const envContent = fs.readFileSync(envPath, 'utf8');
170
- const productionEnv = envContent
171
- .replace(/NODE_ENV=.*/g, 'NODE_ENV=production')
172
- .replace(/VITE_API_BASE_URL=.*/g, 'VITE_API_BASE_URL=https://your-production-api.com');
173
-
174
- fs.writeFileSync(envPath, productionEnv);
175
- success('已切换到生产环境');
176
-
177
- // 构建 Dashboard
178
- try {
179
- info('构建 Dashboard...');
180
- exec('cd dashboard && npm run build');
181
-
182
- const distPath = path.join(__dirname, '../dashboard/dist/index.html');
183
- if (fs.existsSync(distPath)) {
184
- success('Dashboard 构建成功');
185
- } else {
186
- throw new Error('dist/index.html 不存在');
157
+ header('构建前端(生产环境)');
158
+
159
+ // 备份 .env
160
+ info('备份 .env 文件...');
161
+ const envPath = path.join(__dirname, '../.env');
162
+ const backupPath = path.join(__dirname, '../.env.backup');
163
+
164
+ if (fs.existsSync(envPath)) {
165
+ fs.copyFileSync(envPath, backupPath);
166
+ success('.env 已备份');
187
167
  }
188
- } catch (err) {
189
- this.errors.push('Dashboard 构建失败');
190
- error('Dashboard 构建失败');
191
-
192
- // 恢复环境
193
- warning('恢复开发环境...');
194
- fs.copyFileSync(backupPath, envPath);
195
- fs.unlinkSync(backupPath);
196
-
197
- throw err;
198
- }
199
-
200
- // 恢复开发环境(稍后在发布完成后再恢复)
201
- info('⚠️ 记得在发布完成后恢复开发环境');
168
+
169
+ // 切换到生产环境
170
+ info('切换到生产环境...');
171
+ const envContent = fs.readFileSync(envPath, 'utf8');
172
+ const productionEnv = envContent
173
+ .replace(/NODE_ENV=.*/g, 'NODE_ENV=production')
174
+ .replace(/VITE_API_BASE_URL=.*/g, 'VITE_API_BASE_URL=https://your-production-api.com');
175
+
176
+ fs.writeFileSync(envPath, productionEnv);
177
+ success('已切换到生产环境');
178
+
179
+ // 构建 Dashboard
180
+ try {
181
+ info('构建 Dashboard...');
182
+ exec('cd dashboard && npm run build');
183
+
184
+ const distPath = path.join(__dirname, '../dashboard/dist/index.html');
185
+ if (fs.existsSync(distPath)) {
186
+ success('Dashboard 构建成功');
187
+ } else {
188
+ throw new Error('dist/index.html 不存在');
189
+ }
190
+ } catch (err) {
191
+ this.errors.push('Dashboard 构建失败');
192
+ error('Dashboard 构建失败');
193
+
194
+ // 恢复环境
195
+ warning('恢复开发环境...');
196
+ fs.copyFileSync(backupPath, envPath);
197
+ fs.unlinkSync(backupPath);
198
+
199
+ throw err;
200
+ }
201
+
202
+ // 恢复开发环境(稍后在发布完成后再恢复)
203
+ info('⚠️ 记得在发布完成后恢复开发环境');
202
204
  }
203
-
205
+
204
206
  // 恢复开发环境
205
207
  restoreEnvironment() {
206
- header('恢复开发环境');
207
-
208
- const envPath = path.join(__dirname, '../.env');
209
- const backupPath = path.join(__dirname, '../.env.backup');
210
-
211
- if (fs.existsSync(backupPath)) {
212
- fs.copyFileSync(backupPath, envPath);
213
- fs.unlinkSync(backupPath);
214
- success('已恢复开发环境');
215
- } else {
216
- warning('未找到 .env.backup,请手动检查环境变量');
217
- }
208
+ header('恢复开发环境');
209
+
210
+ const envPath = path.join(__dirname, '../.env');
211
+ const backupPath = path.join(__dirname, '../.env.backup');
212
+
213
+ if (fs.existsSync(backupPath)) {
214
+ fs.copyFileSync(backupPath, envPath);
215
+ fs.unlinkSync(backupPath);
216
+ success('已恢复开发环境');
217
+ } else {
218
+ warning('未找到 .env.backup,请手动检查环境变量');
219
+ }
218
220
  }
219
-
221
+
220
222
  // 检查其他构建产物
221
223
  checkBuildArtifacts() {
222
- header('其他构建产物检查');
223
-
224
- const nativeUI = path.join(__dirname, '../resources/native-ui/native-ui');
225
-
226
- if (!fs.existsSync(nativeUI)) {
227
- this.warnings.push('Native UI 未构建 (执行 npm run build:native-ui)');
228
- warning('Native UI: 未构建');
229
- } else {
230
- const stat = fs.statSync(nativeUI);
231
- success(`Native UI: 已构建 (${new Date(stat.mtime).toLocaleString()})`);
232
- }
224
+ header('其他构建产物检查');
225
+
226
+ const nativeUI = path.join(__dirname, '../resources/native-ui/native-ui');
227
+
228
+ if (!fs.existsSync(nativeUI)) {
229
+ this.warnings.push('Native UI 未构建 (执行 npm run build:native-ui)');
230
+ warning('Native UI: 未构建');
231
+ } else {
232
+ const stat = fs.statSync(nativeUI);
233
+ success(`Native UI: 已构建 (${new Date(stat.mtime).toLocaleString()})`);
234
+ }
233
235
  }
234
236
 
235
237
  // 运行测试
236
238
  runTests() {
237
- header('运行测试');
238
-
239
- try {
240
- info('运行单元测试...');
241
- exec('npm run test:unit');
242
- success('单元测试通过');
243
- } catch (err) {
244
- this.errors.push('单元测试失败');
245
- error('单元测试失败');
246
- }
247
-
248
- try {
249
- info('运行集成测试...');
250
- exec('npm run test:integration');
251
- success('集成测试通过');
252
- } catch (err) {
253
- this.errors.push('集成测试失败');
254
- error('集成测试失败');
255
- }
239
+ header('运行测试');
240
+
241
+ try {
242
+ info('运行单元测试...');
243
+ exec('npm run test:unit');
244
+ success('单元测试通过');
245
+ } catch (_err) {
246
+ this.errors.push('单元测试失败');
247
+ error('单元测试失败');
248
+ }
249
+
250
+ try {
251
+ info('运行集成测试...');
252
+ exec('npm run test:integration');
253
+ success('集成测试通过');
254
+ } catch (_err) {
255
+ this.errors.push('集成测试失败');
256
+ error('集成测试失败');
257
+ }
256
258
  }
257
259
 
258
260
  // 总结
259
261
  summary() {
260
- header('检查总结');
261
-
262
- if (this.errors.length === 0 && this.warnings.length === 0) {
263
- success('所有检查通过,可以发布!');
264
- return true;
265
- }
266
-
267
- if (this.errors.length > 0) {
268
- error(`发现 ${this.errors.length} 个错误:`);
269
- this.errors.forEach((err, i) => {
270
- console.log(` ${i + 1}. ${err}`);
271
- });
272
- }
273
-
274
- if (this.warnings.length > 0) {
275
- warning(`发现 ${this.warnings.length} 个警告:`);
276
- this.warnings.forEach((warn, i) => {
277
- console.log(` ${i + 1}. ${warn}`);
278
- });
279
- }
280
-
281
- return this.errors.length === 0;
262
+ header('检查总结');
263
+
264
+ if (this.errors.length === 0 && this.warnings.length === 0) {
265
+ success('所有检查通过,可以发布!');
266
+ return true;
267
+ }
268
+
269
+ if (this.errors.length > 0) {
270
+ error(`发现 ${this.errors.length} 个错误:`);
271
+ this.errors.forEach((err, i) => {});
272
+ }
273
+
274
+ if (this.warnings.length > 0) {
275
+ warning(`发现 ${this.warnings.length} 个警告:`);
276
+ this.warnings.forEach((warn, i) => {});
277
+ }
278
+
279
+ return this.errors.length === 0;
282
280
  }
283
281
  }
284
282
 
285
283
  // 发布流程
286
284
  function release(versionType, checker) {
287
285
  header(`开始发布流程 (${versionType})`);
288
-
286
+
289
287
  // 读取当前版本
290
288
  const packageJson = require('../package.json');
291
289
  const currentVersion = packageJson.version;
292
290
  info(`当前版本: ${currentVersion}`);
293
-
291
+
294
292
  // 构建前端(生产环境)
295
293
  try {
296
- checker.buildFrontend();
297
- } catch (err) {
298
- error('前端构建失败,发布中止');
299
- process.exit(1);
294
+ checker.buildFrontend();
295
+ } catch (_err) {
296
+ error('前端构建失败,发布中止');
297
+ process.exit(1);
300
298
  }
301
-
299
+
302
300
  // 执行版本升级
303
301
  try {
304
- info(`执行 npm version ${versionType}...`);
305
- const newVersion = exec(`npm version ${versionType}`, { silent: true })?.trim();
306
- success(`版本已更新: ${currentVersion} → ${newVersion}`);
307
-
308
- info('请手动编辑 CHANGELOG.md,然后按回车继续...');
309
- // 等待用户输入
310
- require('child_process').spawnSync('read', ['-p', ''], {
311
- stdio: 'inherit',
312
- shell: true
313
- });
314
-
315
- // 修正 commit(包含 dist/ 文件)
316
- info('提交所有变更(包括构建产物)...');
317
- exec('git add .');
318
- exec(`git commit --amend -m "chore: release ${newVersion}"`);
319
- exec(`git tag -f ${newVersion}`);
320
- success('Commit 和 tag 已更新');
321
-
322
- // 推送到 GitHub
323
- info('推送到 GitHub(触发自动发布)...');
324
- exec('git push origin main --tags');
325
- success('已推送到 GitHub,等待 Actions 自动发布');
326
-
327
- // 恢复开发环境
328
- checker.restoreEnvironment();
329
-
330
- header('🎉 发布流程完成!');
331
- console.log(`
332
- 版本: ${newVersion}
333
- GitHub: https://github.com/gaoxuefeng/AutoSnippet/releases/tag/${newVersion}
334
-
335
- ⏳ GitHub Actions 正在自动发布到 npm...
336
-
337
- 下一步:
338
- 1. 等待 Actions 完成: https://github.com/gaoxuefeng/AutoSnippet/actions
339
- 2. 验证 npm 包: npm view autosnippet@${newVersion}
340
- 3. 创建 GitHub Release: https://github.com/gaoxuefeng/AutoSnippet/releases/new?tag=${newVersion}
341
- 4. 通知团队成员升级版本
342
-
343
- ⚠️ 已恢复开发环境配置
344
- `);
345
-
346
- } catch (err) {
347
- error('发布失败!');
348
- console.error(err.message);
349
-
350
- // 尝试恢复环境
351
- try {
302
+ info(`执行 npm version ${versionType}...`);
303
+ const newVersion = exec(`npm version ${versionType}`, { silent: true })?.trim();
304
+ success(`版本已更新: ${currentVersion} → ${newVersion}`);
305
+
306
+ info('请手动编辑 CHANGELOG.md,然后按回车继续...');
307
+ // 等待用户输入
308
+ require('node:child_process').spawnSync('read', ['-p', ''], {
309
+ stdio: 'inherit',
310
+ shell: true,
311
+ });
312
+
313
+ // 修正 commit(包含 dist/ 文件)
314
+ info('提交所有变更(包括构建产物)...');
315
+ exec('git add .');
316
+ exec(`git commit --amend -m "chore: release ${newVersion}"`);
317
+ exec(`git tag -f ${newVersion}`);
318
+ success('Commit 和 tag 已更新');
319
+
320
+ // 推送到 GitHub
321
+ info('推送到 GitHub(触发自动发布)...');
322
+ exec('git push origin main --tags');
323
+ success('已推送到 GitHub,等待 Actions 自动发布');
324
+
325
+ // 恢复开发环境
352
326
  checker.restoreEnvironment();
353
- } catch (restoreErr) {
354
- error('恢复环境失败,请手动检查 .env 文件');
355
- }
356
-
357
- process.exit(1);
327
+
328
+ header('🎉 发布流程完成!');
329
+ } catch (err) {
330
+ error('发布失败!');
331
+ console.error(err.message);
332
+
333
+ // 尝试恢复环境
334
+ try {
335
+ checker.restoreEnvironment();
336
+ } catch (_restoreErr) {
337
+ error('恢复环境失败,请手动检查 .env 文件');
338
+ }
339
+
340
+ process.exit(1);
358
341
  }
359
342
  }
360
343
 
@@ -362,88 +345,65 @@ GitHub: https://github.com/gaoxuefeng/AutoSnippet/releases/tag/${newVersion}
362
345
  function main() {
363
346
  const args = process.argv.slice(2);
364
347
  const command = args[0];
365
-
348
+
366
349
  // 显示帮助
367
350
  if (!command || command === '--help' || command === '-h') {
368
- console.log(`
369
- AutoSnippet 发布辅助脚本
370
-
371
- 用法:
372
- node scripts/release.js check # 仅执行发布前检查
373
- node scripts/release.js patch # 发布 Patch 版本 (Bug 修复)
374
- node scripts/release.js minor # 发布 Minor 版本 (新功能)
375
- node scripts/release.js major # 发布 Major 版本 (破坏性变更)
376
-
377
- 示例:
378
- node scripts/release.js check # 检查是否可以发布
379
- node scripts/release.js patch # 1.7.0 → 1.7.1
380
- node scripts/release.js minor # 1.7.0 → 1.8.0
381
- node scripts/release.js major # 1.7.0 → 2.0.0
382
-
383
- 参考文档:
384
- docs/AI发布指南.md # 完整发布指南
385
- docs/AI发布清单.md # 快速参考清单
386
- `);
387
- process.exit(0);
351
+ process.exit(0);
388
352
  }
389
-
353
+
390
354
  // 执行检查
391
355
  if (command === 'check') {
392
- const checker = new ReleaseChecker();
393
- checker.checkGitStatus();
394
- checker.checkNodeEnvironment();
395
- checker.checkBuildArtifacts();
396
-
397
- if (checker.summary()) {
398
- info('\n运行 `npm run test` 来执行完整测试');
399
- info('运行 `npm run release:patch/minor/major` 开始发布');
400
- process.exit(0);
401
- } else {
402
- error('\n请修复错误后再试');
403
- process.exit(1);
404
- }
356
+ const checker = new ReleaseChecker();
357
+ checker.checkGitStatus();
358
+ checker.checkNodeEnvironment();
359
+ checker.checkBuildArtifacts();
360
+
361
+ if (checker.summary()) {
362
+ info('\n运行 `npm run test` 来执行完整测试');
363
+ info('运行 `npm run release:patch/minor/major` 开始发布');
364
+ process.exit(0);
365
+ } else {
366
+ error('\n请修复错误后再试');
367
+ process.exit(1);
368
+ }
405
369
  }
406
-
370
+
407
371
  // 执行发布
408
372
  if (['patch', 'minor', 'major'].includes(command)) {
409
- // 先执行检查
410
- const checker = new ReleaseChecker();
411
- checker.checkGitStatus();
412
- checker.checkNodeEnvironment();
413
- checker.checkBuildArtifacts();
414
- checker.runTests();
415
-
416
- if (!checker.summary()) {
417
- error('\n发布前检查未通过,请修复后再试');
418
- process.exit(1);
419
- }
420
-
421
- // 确认发布
422
- console.log('');
423
- warning(`即将发布 ${command} 版本,是否继续?(y/N)`);
424
-
425
- const readline = require('readline').createInterface({
426
- input: process.stdin,
427
- output: process.stdout
428
- });
429
-
430
- readline.question('> ', (answer) => {
431
- readline.close();
432
-
433
- if (answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {
434
- release(command, checker);
435
- } else {
436
- info('已取消发布');
437
- process.exit(0);
373
+ // 先执行检查
374
+ const checker = new ReleaseChecker();
375
+ checker.checkGitStatus();
376
+ checker.checkNodeEnvironment();
377
+ checker.checkBuildArtifacts();
378
+ checker.runTests();
379
+
380
+ if (!checker.summary()) {
381
+ error('\n发布前检查未通过,请修复后再试');
382
+ process.exit(1);
438
383
  }
439
- });
440
-
441
- return;
384
+ warning(`即将发布 ${command} 版本,是否继续?(y/N)`);
385
+
386
+ const readline = require('node:readline').createInterface({
387
+ input: process.stdin,
388
+ output: process.stdout,
389
+ });
390
+
391
+ readline.question('> ', (answer) => {
392
+ readline.close();
393
+
394
+ if (answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {
395
+ release(command, checker);
396
+ } else {
397
+ info('已取消发布');
398
+ process.exit(0);
399
+ }
400
+ });
401
+
402
+ return;
442
403
  }
443
-
404
+
444
405
  // 未知命令
445
406
  error(`未知命令: ${command}`);
446
- console.log('运行 `node scripts/release.js --help` 查看帮助');
447
407
  process.exit(1);
448
408
  }
449
409