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.
- package/README.md +230 -324
- package/bin/api-server.js +1 -1
- package/bin/cli.js +204 -244
- package/bin/mcp-server.js +5 -3
- package/config/knowledge-base.config.js +132 -132
- package/dashboard/dist/assets/{icons-CEfgGaZi.js → icons-Cdq22n2i.js} +95 -100
- package/dashboard/dist/assets/index-ClkyPkDX.js +133 -0
- package/dashboard/dist/assets/index-t4QrJwv1.css +1 -0
- package/dashboard/dist/index.html +3 -3
- package/lib/bootstrap.js +8 -8
- package/lib/cli/AiScanService.js +86 -40
- package/lib/cli/KnowledgeSyncService.js +113 -74
- package/lib/cli/SetupService.js +439 -277
- package/lib/cli/UpgradeService.js +63 -100
- package/lib/core/AstAnalyzer.js +276 -597
- package/lib/core/ast/ProjectGraph.js +101 -40
- package/lib/core/ast/ensure-grammars.js +232 -0
- package/lib/core/ast/index.js +115 -0
- package/lib/core/ast/lang-dart.js +661 -0
- package/lib/core/ast/lang-go.js +530 -0
- package/lib/core/ast/lang-java.js +435 -0
- package/lib/core/ast/lang-javascript.js +272 -0
- package/lib/core/ast/lang-kotlin.js +423 -0
- package/lib/core/ast/lang-objc.js +388 -0
- package/lib/core/ast/lang-python.js +371 -0
- package/lib/core/ast/lang-swift.js +337 -0
- package/lib/core/ast/lang-typescript.js +503 -0
- package/lib/core/capability/CapabilityProbe.js +18 -9
- package/lib/core/constitution/Constitution.js +2 -3
- package/lib/core/constitution/ConstitutionValidator.js +65 -24
- package/lib/core/discovery/DartDiscoverer.js +534 -0
- package/lib/core/discovery/DiscovererRegistry.js +83 -0
- package/lib/core/discovery/GenericDiscoverer.js +225 -0
- package/lib/core/discovery/GoDiscoverer.js +541 -0
- package/lib/core/discovery/JvmDiscoverer.js +506 -0
- package/lib/core/discovery/NodeDiscoverer.js +466 -0
- package/lib/core/discovery/ProjectDiscoverer.js +93 -0
- package/lib/core/discovery/PythonDiscoverer.js +338 -0
- package/lib/core/discovery/SpmDiscoverer.js +5 -0
- package/lib/core/discovery/index.js +53 -0
- package/lib/core/enhancement/EnhancementPack.js +71 -0
- package/lib/core/enhancement/EnhancementRegistry.js +47 -0
- package/lib/core/enhancement/android-enhancement.js +102 -0
- package/lib/core/enhancement/django-enhancement.js +70 -0
- package/lib/core/enhancement/fastapi-enhancement.js +63 -0
- package/lib/core/enhancement/go-grpc-enhancement.js +152 -0
- package/lib/core/enhancement/go-web-enhancement.js +201 -0
- package/lib/core/enhancement/index.js +65 -0
- package/lib/core/enhancement/node-server-enhancement.js +88 -0
- package/lib/core/enhancement/react-enhancement.js +86 -0
- package/lib/core/enhancement/spring-enhancement.js +112 -0
- package/lib/core/enhancement/vue-enhancement.js +96 -0
- package/lib/core/gateway/Gateway.js +8 -9
- package/lib/core/gateway/GatewayActionRegistry.js +1 -1
- package/lib/core/permission/PermissionManager.js +12 -8
- package/lib/domain/index.js +13 -9
- package/lib/domain/knowledge/KnowledgeEntry.js +111 -101
- package/lib/domain/knowledge/KnowledgeRepository.js +0 -1
- package/lib/domain/knowledge/Lifecycle.js +22 -22
- package/lib/domain/knowledge/index.js +9 -12
- package/lib/domain/knowledge/values/Constraints.js +31 -21
- package/lib/domain/knowledge/values/Content.js +21 -13
- package/lib/domain/knowledge/values/Quality.js +31 -18
- package/lib/domain/knowledge/values/Reasoning.js +20 -12
- package/lib/domain/knowledge/values/Relations.js +37 -25
- package/lib/domain/knowledge/values/Stats.js +18 -12
- package/lib/domain/knowledge/values/index.js +4 -3
- package/lib/domain/snippet/Snippet.js +35 -10
- package/lib/external/ai/AiFactory.js +48 -16
- package/lib/external/ai/AiProvider.js +184 -90
- package/lib/external/ai/providers/ClaudeProvider.js +25 -12
- package/lib/external/ai/providers/GoogleGeminiProvider.js +59 -30
- package/lib/external/ai/providers/MockProvider.js +9 -3
- package/lib/external/ai/providers/OpenAiProvider.js +51 -29
- package/lib/external/mcp/McpServer.js +66 -36
- package/lib/external/mcp/errorHandler.js +23 -11
- package/lib/external/mcp/handlers/LanguageExtensions.js +138 -53
- package/lib/external/mcp/handlers/TargetClassifier.js +52 -16
- package/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.js +81 -20
- package/lib/external/mcp/handlers/bootstrap/pipeline/EpisodicMemory.js +71 -42
- package/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.js +9 -17
- package/lib/external/mcp/handlers/bootstrap/pipeline/ToolResultCache.js +14 -9
- package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-context.js +15 -7
- package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +352 -153
- package/lib/external/mcp/handlers/bootstrap/pipeline/tier-scheduler.js +52 -12
- package/lib/external/mcp/handlers/bootstrap/skills.js +143 -39
- package/lib/external/mcp/handlers/bootstrap.js +691 -168
- package/lib/external/mcp/handlers/browse.js +66 -22
- package/lib/external/mcp/handlers/candidate.js +118 -35
- package/lib/external/mcp/handlers/consolidated.js +49 -17
- package/lib/external/mcp/handlers/guard.js +104 -39
- package/lib/external/mcp/handlers/knowledge.js +60 -36
- package/lib/external/mcp/handlers/search.js +43 -14
- package/lib/external/mcp/handlers/skill.js +120 -45
- package/lib/external/mcp/handlers/structure.js +240 -86
- package/lib/external/mcp/handlers/system.js +42 -12
- package/lib/external/mcp/handlers/wiki.js +58 -33
- package/lib/external/mcp/tools.js +306 -123
- package/lib/http/HttpServer.js +72 -47
- package/lib/http/middleware/RateLimiter.js +5 -3
- package/lib/http/middleware/errorHandler.js +6 -1
- package/lib/http/middleware/requestLogger.js +14 -3
- package/lib/http/middleware/roleResolver.js +30 -23
- package/lib/http/routes/ai.js +387 -265
- package/lib/http/routes/auth.js +81 -61
- package/lib/http/routes/candidates.js +430 -320
- package/lib/http/routes/commands.js +289 -189
- package/lib/http/routes/extract.js +158 -125
- package/lib/http/routes/guardRules.js +309 -217
- package/lib/http/routes/knowledge.js +213 -154
- package/lib/http/routes/modules.js +578 -0
- package/lib/http/routes/monitoring.js +6 -6
- package/lib/http/routes/recipes.js +104 -93
- package/lib/http/routes/search.js +361 -305
- package/lib/http/routes/skills.js +145 -98
- package/lib/http/routes/snippets.js +42 -30
- package/lib/http/routes/spm.js +3 -405
- package/lib/http/routes/violations.js +113 -93
- package/lib/http/routes/wiki.js +211 -170
- package/lib/http/utils/routeHelpers.js +3 -1
- package/lib/http/utils/sse-sessions.js +16 -6
- package/lib/http/utils/sse.js +15 -5
- package/lib/infrastructure/audit/AuditLogger.js +5 -2
- package/lib/infrastructure/audit/AuditStore.js +10 -7
- package/lib/infrastructure/cache/CacheService.js +3 -1
- package/lib/infrastructure/cache/GraphCache.js +8 -4
- package/lib/infrastructure/cache/UnifiedCacheAdapter.js +1 -1
- package/lib/infrastructure/config/ConfigLoader.js +9 -5
- package/lib/infrastructure/config/Defaults.js +30 -10
- package/lib/infrastructure/config/Paths.js +28 -8
- package/lib/infrastructure/config/TriggerSymbol.js +22 -10
- package/lib/infrastructure/database/DatabaseConnection.js +15 -10
- package/lib/infrastructure/database/migrations/001_initial_schema.js +0 -1
- package/lib/infrastructure/external/ClipboardManager.js +6 -2
- package/lib/infrastructure/external/NativeUi.js +50 -43
- package/lib/infrastructure/external/OpenBrowser.js +14 -17
- package/lib/infrastructure/external/XcodeAutomation.js +14 -258
- package/lib/infrastructure/logging/Logger.js +46 -30
- package/lib/infrastructure/monitoring/ErrorTracker.js +7 -5
- package/lib/infrastructure/monitoring/PerformanceMonitor.js +12 -4
- package/lib/infrastructure/paths/HeaderResolver.js +25 -9
- package/lib/infrastructure/paths/PathFinder.js +34 -12
- package/lib/infrastructure/plugin/PluginManager.js +26 -8
- package/lib/infrastructure/realtime/RealtimeService.js +2 -2
- package/lib/infrastructure/vector/Chunker.js +22 -7
- package/lib/infrastructure/vector/IndexingPipeline.js +46 -22
- package/lib/infrastructure/vector/JsonVectorAdapter.js +90 -53
- package/lib/infrastructure/vector/VectorStore.js +28 -10
- package/lib/injection/ServiceContainer.js +247 -93
- package/lib/platform/ios/index.js +63 -0
- package/lib/platform/ios/routes/spm.js +437 -0
- package/lib/platform/ios/snippet/PlaceholderConverter.js +55 -0
- package/lib/platform/ios/snippet/XcodeCodec.js +112 -0
- package/lib/{service → platform/ios}/spm/DependencyGraph.js +41 -17
- package/lib/{service → platform/ios}/spm/PackageSwiftParser.js +41 -14
- package/lib/{service → platform/ios}/spm/PolicyEngine.js +9 -4
- package/lib/platform/ios/spm/SpmDiscoverer.js +122 -0
- package/lib/{service → platform/ios}/spm/SpmService.js +385 -127
- package/lib/{service/automation → platform/ios/xcode}/SaveEventFilter.js +8 -7
- package/lib/platform/ios/xcode/XcodeAutomation.js +350 -0
- package/lib/{service/automation → platform/ios/xcode}/XcodeIntegration.js +325 -145
- package/lib/repository/base/BaseRepository.js +7 -9
- package/lib/repository/knowledge/KnowledgeRepository.impl.js +98 -75
- package/lib/repository/token/TokenUsageStore.js +4 -2
- package/lib/service/automation/ActionPipeline.js +1 -1
- package/lib/service/automation/AutomationOrchestrator.js +8 -4
- package/lib/service/automation/ContextCollector.js +7 -5
- package/lib/service/automation/DirectiveDetector.js +23 -16
- package/lib/service/automation/FileWatcher.js +112 -56
- package/lib/service/automation/TriggerResolver.js +6 -4
- package/lib/service/automation/handlers/AlinkHandler.js +24 -12
- package/lib/service/automation/handlers/CreateHandler.js +19 -20
- package/lib/service/automation/handlers/DraftHandler.js +14 -8
- package/lib/service/automation/handlers/GuardHandler.js +93 -63
- package/lib/service/automation/handlers/HeaderHandler.js +1 -6
- package/lib/service/automation/handlers/SearchHandler.js +155 -88
- package/lib/service/bootstrap/BootstrapTaskManager.js +77 -35
- package/lib/service/candidate/SimilarityService.js +25 -9
- package/lib/service/chat/AnalystAgent.js +50 -24
- package/lib/service/chat/CandidateGuardrail.js +143 -17
- package/lib/service/chat/ChatAgent.js +759 -243
- package/lib/service/chat/ContextWindow.js +116 -71
- package/lib/service/chat/ConversationStore.js +77 -36
- package/lib/service/chat/EpisodicConsolidator.js +47 -23
- package/lib/service/chat/HandoffProtocol.js +98 -22
- package/lib/service/chat/Memory.js +34 -14
- package/lib/service/chat/ProducerAgent.js +40 -20
- package/lib/service/chat/ProjectSemanticMemory.js +109 -78
- package/lib/service/chat/ReasoningLayer.js +148 -70
- package/lib/service/chat/ReasoningTrace.js +44 -32
- package/lib/service/chat/TaskPipeline.js +39 -19
- package/lib/service/chat/ToolRegistry.js +48 -29
- package/lib/service/chat/WorkingMemory.js +44 -18
- package/lib/service/chat/tools.js +1096 -494
- package/lib/service/context/RecipeExtractor.js +132 -51
- package/lib/service/cursor/CursorDeliveryPipeline.js +82 -37
- package/lib/service/cursor/KnowledgeCompressor.js +25 -22
- package/lib/service/cursor/RulesGenerator.js +13 -7
- package/lib/service/cursor/SkillsSyncer.js +77 -27
- package/lib/service/cursor/TokenBudget.js +2 -2
- package/lib/service/cursor/TopicClassifier.js +54 -20
- package/lib/service/guard/ComplianceReporter.js +55 -43
- package/lib/service/guard/ExclusionManager.js +67 -29
- package/lib/service/guard/GuardCheckEngine.js +381 -86
- package/lib/service/guard/GuardFeedbackLoop.js +22 -10
- package/lib/service/guard/GuardService.js +29 -19
- package/lib/service/guard/RuleLearner.js +55 -23
- package/lib/service/guard/SourceFileCollector.js +27 -20
- package/lib/service/guard/ViolationsStore.js +43 -38
- package/lib/service/knowledge/CodeEntityGraph.js +147 -82
- package/lib/service/knowledge/ConfidenceRouter.js +12 -10
- package/lib/service/knowledge/KnowledgeFileWriter.js +147 -56
- package/lib/service/knowledge/KnowledgeGraphService.js +81 -34
- package/lib/service/knowledge/KnowledgeService.js +222 -112
- package/lib/service/module/ModuleService.js +969 -0
- package/lib/service/quality/FeedbackCollector.js +27 -15
- package/lib/service/quality/QualityScorer.js +78 -24
- package/lib/service/recipe/RecipeCandidateValidator.js +110 -44
- package/lib/service/recipe/RecipeParser.js +78 -45
- package/lib/service/search/CoarseRanker.js +43 -28
- package/lib/service/search/CrossEncoderReranker.js +32 -21
- package/lib/service/search/InvertedIndex.js +21 -7
- package/lib/service/search/MultiSignalRanker.js +90 -28
- package/lib/service/search/RetrievalFunnel.js +45 -24
- package/lib/service/search/SearchEngine.js +255 -103
- package/lib/service/skills/EventAggregator.js +32 -15
- package/lib/service/skills/SignalCollector.js +140 -64
- package/lib/service/skills/SkillAdvisor.js +79 -42
- package/lib/service/skills/SkillHooks.js +16 -14
- package/lib/service/snippet/PlaceholderConverter.js +5 -0
- package/lib/service/snippet/SnippetFactory.js +116 -99
- package/lib/service/snippet/SnippetInstaller.js +234 -62
- package/lib/service/snippet/codecs/SnippetCodec.js +67 -0
- package/lib/service/snippet/codecs/VSCodeCodec.js +102 -0
- package/lib/service/snippet/codecs/XcodeCodec.js +5 -0
- package/lib/service/wiki/WikiGenerator.js +637 -263
- package/lib/shared/DimensionCopyRegistry.js +472 -0
- package/lib/shared/LanguageService.js +399 -0
- package/lib/shared/PathGuard.js +45 -28
- package/lib/shared/RecipeReadinessChecker.js +72 -12
- package/lib/shared/constants.js +41 -41
- package/lib/shared/errors/BaseError.js +2 -2
- package/lib/shared/errors/index.js +4 -4
- package/lib/shared/similarity.js +25 -8
- package/lib/shared/token-utils.js +6 -2
- package/lib/shared/utils/common.js +12 -4
- package/package.json +49 -13
- package/scripts/bench-real-projects.mjs +256 -0
- package/scripts/build-native-ui.js +30 -30
- package/scripts/clear-old-vector-index.js +5 -35
- package/scripts/clear-vector-cache.js +7 -37
- package/scripts/collect-test-project-stats.mjs +160 -0
- package/scripts/diagnose-mcp.js +41 -32
- package/scripts/ensure-parse-package.js +6 -9
- package/scripts/generate-recipe-drafts.js +116 -77
- package/scripts/init-db.js +3 -20
- package/scripts/init-snippets.js +305 -0
- package/scripts/init-vector-db.js +173 -170
- package/scripts/install-cursor-skill.js +148 -104
- package/scripts/install-full.js +8 -21
- package/scripts/install-vscode-copilot.js +146 -145
- package/scripts/migrate-md-to-knowledge.mjs +139 -151
- package/scripts/postinstall-safe.js +5 -17
- package/scripts/recipe-audit.js +106 -82
- package/scripts/release.js +283 -323
- package/scripts/setup-mcp-config.js +60 -52
- package/scripts/verify-context-api.js +20 -20
- package/skills/autosnippet-analysis/SKILL.md +10 -6
- package/skills/autosnippet-candidates/SKILL.md +27 -26
- package/skills/autosnippet-coldstart/SKILL.md +555 -38
- package/skills/autosnippet-concepts/SKILL.md +349 -337
- package/skills/autosnippet-create/SKILL.md +5 -5
- package/skills/autosnippet-reference-dart/SKILL.md +543 -0
- package/skills/autosnippet-reference-go/SKILL.md +539 -0
- package/skills/autosnippet-reference-java/SKILL.md +534 -0
- package/skills/autosnippet-reference-jsts/SKILL.md +41 -9
- package/skills/autosnippet-reference-kotlin/SKILL.md +526 -0
- package/skills/autosnippet-reference-objc/SKILL.md +29 -6
- package/skills/autosnippet-reference-python/SKILL.md +800 -0
- package/skills/autosnippet-reference-swift/SKILL.md +70 -14
- package/skills/autosnippet-structure/SKILL.md +4 -4
- package/templates/cursor-rules/autosnippet-conventions.mdc +2 -2
- package/templates/recipes-setup/README.md +2 -2
- package/templates/recipes-setup/_template.md +1 -1
- package/dashboard/dist/assets/index-Bun3ld_J.css +0 -1
- package/dashboard/dist/assets/index-_Sk_Dmg3.js +0 -143
- package/resources/asd-entry/main.swift +0 -159
- package/scripts/build-asd-entry.js +0 -51
- package/scripts/init-xcode-snippets.js +0 -311
- package/template.json +0 -39
|
@@ -12,11 +12,14 @@
|
|
|
12
12
|
* 运行方式:在项目根目录执行 npm run install:cursor-skill,或 asd install:cursor-skill,或 node scripts/install-cursor-skill.js
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import { fileURLToPath } from 'node:url';
|
|
16
15
|
import { dirname } from 'node:path';
|
|
16
|
+
import { fileURLToPath } from 'node:url';
|
|
17
|
+
|
|
17
18
|
const __filename = fileURLToPath(import.meta.url);
|
|
18
19
|
const __dirname = dirname(__filename);
|
|
20
|
+
|
|
19
21
|
import { createRequire } from 'node:module';
|
|
22
|
+
|
|
20
23
|
const require = createRequire(import.meta.url);
|
|
21
24
|
|
|
22
25
|
import fs from 'node:fs';
|
|
@@ -34,25 +37,27 @@ function findProjectRootFromCwd() {
|
|
|
34
37
|
let current = path.resolve(process.cwd());
|
|
35
38
|
const maxLevels = 20;
|
|
36
39
|
let levels = 0;
|
|
37
|
-
|
|
40
|
+
|
|
38
41
|
while (levels < maxLevels) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
42
|
+
const boxspecPath = path.join(current, 'AutoSnippet', 'AutoSnippet.boxspec.json');
|
|
43
|
+
if (fs.existsSync(boxspecPath)) {
|
|
44
|
+
return current; // 当前目录就是项目根
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 还要检查当前目录本身就是知识库目录的情况(用户直接在 AutoSnippet/ 中运行)
|
|
48
|
+
const directBoxspec = path.join(current, 'AutoSnippet.boxspec.json');
|
|
49
|
+
if (fs.existsSync(directBoxspec)) {
|
|
50
|
+
return path.dirname(current); // 当前是知识库,其父级才是项目根
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const parentPath = path.dirname(current);
|
|
54
|
+
if (parentPath === current) {
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
current = parentPath;
|
|
58
|
+
levels++;
|
|
54
59
|
}
|
|
55
|
-
|
|
60
|
+
|
|
56
61
|
return null;
|
|
57
62
|
}
|
|
58
63
|
|
|
@@ -62,10 +67,14 @@ if (found) {
|
|
|
62
67
|
} else {
|
|
63
68
|
// 备选方案:使用PathFinder的查找逻辑
|
|
64
69
|
try {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
70
|
+
const findPath = require(
|
|
71
|
+
path.join(autoSnippetRoot, 'lib', 'infrastructure/paths/PathFinder.js')
|
|
72
|
+
);
|
|
73
|
+
const fallback = findPath.findProjectRootSync(process.cwd());
|
|
74
|
+
if (fallback) {
|
|
75
|
+
projectRoot = fallback;
|
|
76
|
+
}
|
|
77
|
+
} catch (_err) {}
|
|
69
78
|
}
|
|
70
79
|
|
|
71
80
|
const skillsTarget = path.join(projectRoot, '.cursor', 'skills');
|
|
@@ -75,16 +84,14 @@ if (!fs.existsSync(skillsSource)) {
|
|
|
75
84
|
process.exit(1);
|
|
76
85
|
}
|
|
77
86
|
|
|
78
|
-
const skillDirs = fs
|
|
79
|
-
.
|
|
80
|
-
.
|
|
87
|
+
const skillDirs = fs
|
|
88
|
+
.readdirSync(skillsSource, { withFileTypes: true })
|
|
89
|
+
.filter((d) => d.isDirectory())
|
|
90
|
+
.map((d) => d.name);
|
|
81
91
|
|
|
82
92
|
if (skillDirs.length === 0) {
|
|
83
|
-
console.log('ℹ️ skills 下暂无 skill 目录,跳过安装。');
|
|
84
93
|
process.exit(0);
|
|
85
94
|
}
|
|
86
|
-
|
|
87
|
-
console.log('🚀 Cursor Skills 安装\n');
|
|
88
95
|
|
|
89
96
|
function getRecipesDir(root) {
|
|
90
97
|
try {
|
|
@@ -97,25 +104,31 @@ function getRecipesDir(root) {
|
|
|
97
104
|
if (fs.existsSync(specPath)) {
|
|
98
105
|
const spec = JSON.parse(fs.readFileSync(specPath, 'utf8'));
|
|
99
106
|
const dir = spec?.recipes?.dir;
|
|
100
|
-
if (dir)
|
|
107
|
+
if (dir) {
|
|
108
|
+
return path.join(root, dir);
|
|
109
|
+
}
|
|
101
110
|
}
|
|
102
111
|
}
|
|
103
|
-
} catch {
|
|
112
|
+
} catch {
|
|
113
|
+
/* fallback */
|
|
114
|
+
}
|
|
104
115
|
return path.join(root, defaults.RECIPES_DIR);
|
|
105
116
|
}
|
|
106
117
|
|
|
107
118
|
function collectMdFiles(dir, baseDir, list = []) {
|
|
108
|
-
if (!fs.existsSync(dir))
|
|
119
|
+
if (!fs.existsSync(dir)) {
|
|
120
|
+
return list;
|
|
121
|
+
}
|
|
109
122
|
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
110
123
|
for (const e of entries) {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
124
|
+
const full = path.join(dir, e.name);
|
|
125
|
+
if (e.isDirectory() && !e.name.startsWith('.')) {
|
|
126
|
+
collectMdFiles(full, baseDir, list);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (e.isFile() && e.name.toLowerCase().endsWith('.md')) {
|
|
130
|
+
list.push(path.relative(baseDir, full).replace(/\\/g, '/'));
|
|
131
|
+
}
|
|
119
132
|
}
|
|
120
133
|
return list;
|
|
121
134
|
}
|
|
@@ -125,7 +138,9 @@ function collectMdFiles(dir, baseDir, list = []) {
|
|
|
125
138
|
*/
|
|
126
139
|
function extractFrontmatterFields(content) {
|
|
127
140
|
const m = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
128
|
-
if (!m)
|
|
141
|
+
if (!m) {
|
|
142
|
+
return {};
|
|
143
|
+
}
|
|
129
144
|
const block = m[1];
|
|
130
145
|
const extract = (key) => {
|
|
131
146
|
const re = new RegExp(`^${key}:\s*["']?(.+?)["']?\s*$`, 'm');
|
|
@@ -152,9 +167,13 @@ function extractFrontmatterFields(content) {
|
|
|
152
167
|
*/
|
|
153
168
|
function buildProjectRecipesContext(projectRoot) {
|
|
154
169
|
const recipesDir = getRecipesDir(projectRoot);
|
|
155
|
-
if (!fs.existsSync(recipesDir))
|
|
170
|
+
if (!fs.existsSync(recipesDir)) {
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
156
173
|
const mdFiles = collectMdFiles(recipesDir, recipesDir).sort();
|
|
157
|
-
if (mdFiles.length === 0)
|
|
174
|
+
if (mdFiles.length === 0) {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
158
177
|
|
|
159
178
|
const lines = [
|
|
160
179
|
'# Project Recipes Index\n\n',
|
|
@@ -178,7 +197,9 @@ function buildProjectRecipesContext(projectRoot) {
|
|
|
178
197
|
const lang = fm.language || '';
|
|
179
198
|
const kind = fm.kind || '';
|
|
180
199
|
const summary = (fm.summary_cn || fm.summary_en || '').replace(/\|/g, '/');
|
|
181
|
-
lines.push(
|
|
200
|
+
lines.push(
|
|
201
|
+
`| ${idx} | ${rel} | ${title} | ${trigger} | ${cat} | ${lang} | ${kind} | ${summary} |\n`
|
|
202
|
+
);
|
|
182
203
|
} catch (_) {
|
|
183
204
|
lines.push(`| ${idx} | ${rel} | *(read error)* | | | | | |\n`);
|
|
184
205
|
}
|
|
@@ -200,9 +221,15 @@ function buildProjectRecipesContext(projectRoot) {
|
|
|
200
221
|
}
|
|
201
222
|
|
|
202
223
|
lines.push('\n## Usage Tips\n\n');
|
|
203
|
-
lines.push(
|
|
204
|
-
|
|
205
|
-
|
|
224
|
+
lines.push(
|
|
225
|
+
'- 查找 Recipe: `autosnippet_search({ query })` 或 `autosnippet_search({ query, mode: "context" })`\n'
|
|
226
|
+
);
|
|
227
|
+
lines.push(
|
|
228
|
+
'- 获取详情: `autosnippet_knowledge({ operation: "get", id })` — 返回完整 Recipe 内容、关系、约束\n'
|
|
229
|
+
);
|
|
230
|
+
lines.push(
|
|
231
|
+
'- 按类型浏览: `autosnippet_knowledge({ operation: "list", kind: "rule" })` / `kind: "pattern"` / `kind: "fact"`\n'
|
|
232
|
+
);
|
|
206
233
|
lines.push('- Guard 检查: `autosnippet_guard({ code })` / `autosnippet_guard({ files })`\n');
|
|
207
234
|
|
|
208
235
|
return lines.join('');
|
|
@@ -210,26 +237,32 @@ function buildProjectRecipesContext(projectRoot) {
|
|
|
210
237
|
|
|
211
238
|
function buildSpmmapSummary(projectRoot) {
|
|
212
239
|
const spmmapPath = path.join(projectRoot, defaults.SPMMAP_PATH);
|
|
213
|
-
if (!fs.existsSync(spmmapPath))
|
|
214
|
-
|
|
215
|
-
const data = JSON.parse(fs.readFileSync(spmmapPath, 'utf8'));
|
|
216
|
-
const graph = data.graph || {};
|
|
217
|
-
const packages = graph.packages || {};
|
|
218
|
-
const edges = graph.edges || {};
|
|
219
|
-
const lines = ['# SPM 依赖结构摘要\n', `Generated by \`asd install:cursor-skill\`. Source: ${defaults.SPMMAP_PATH}\n`, '\n## Packages\n'];
|
|
220
|
-
for (const [pkg, info] of Object.entries(packages)) {
|
|
221
|
-
const targets = (info.targets || []).join(', ');
|
|
222
|
-
lines.push(`- **${pkg}**: ${targets || '(no targets)'}\n`);
|
|
240
|
+
if (!fs.existsSync(spmmapPath)) {
|
|
241
|
+
return null;
|
|
223
242
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
243
|
+
try {
|
|
244
|
+
const data = JSON.parse(fs.readFileSync(spmmapPath, 'utf8'));
|
|
245
|
+
const graph = data.graph || {};
|
|
246
|
+
const packages = graph.packages || {};
|
|
247
|
+
const edges = graph.edges || {};
|
|
248
|
+
const lines = [
|
|
249
|
+
'# SPM 依赖结构摘要\n',
|
|
250
|
+
`Generated by \`asd install:cursor-skill\`. Source: ${defaults.SPMMAP_PATH}\n`,
|
|
251
|
+
'\n## Packages\n',
|
|
252
|
+
];
|
|
253
|
+
for (const [pkg, info] of Object.entries(packages)) {
|
|
254
|
+
const targets = (info.targets || []).join(', ');
|
|
255
|
+
lines.push(`- **${pkg}**: ${targets || '(no targets)'}\n`);
|
|
228
256
|
}
|
|
229
|
-
|
|
230
|
-
|
|
257
|
+
lines.push('\n## 依赖关系 (from → to)\n');
|
|
258
|
+
for (const [from, toList] of Object.entries(edges)) {
|
|
259
|
+
if (Array.isArray(toList)) {
|
|
260
|
+
lines.push(`- ${from} → ${toList.join(', ')}\n`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return lines.join('');
|
|
231
264
|
} catch (_) {
|
|
232
|
-
|
|
265
|
+
return null;
|
|
233
266
|
}
|
|
234
267
|
}
|
|
235
268
|
|
|
@@ -238,53 +271,62 @@ for (const name of skillDirs) {
|
|
|
238
271
|
const dest = path.join(skillsTarget, name);
|
|
239
272
|
// 合并模式:只覆盖源文件中存在的文件,保留用户在 skill 目录下自己添加的文件
|
|
240
273
|
fs.cpSync(src, dest, { recursive: true, force: true });
|
|
241
|
-
console.log(` ✅ ${name}`);
|
|
242
274
|
|
|
243
275
|
if (name === 'autosnippet-recipes') {
|
|
244
276
|
// V2: 生成轻量 Recipe 索引(替代 V1 全文拼接 + by-category 切片)
|
|
245
277
|
const context = buildProjectRecipesContext(projectRoot);
|
|
246
278
|
const refDir = path.join(dest, 'references');
|
|
247
|
-
if (!fs.existsSync(refDir))
|
|
279
|
+
if (!fs.existsSync(refDir)) {
|
|
280
|
+
fs.mkdirSync(refDir, { recursive: true });
|
|
281
|
+
}
|
|
248
282
|
const contextPath = path.join(refDir, 'project-recipes-context.md');
|
|
249
283
|
if (context) {
|
|
250
284
|
fs.writeFileSync(contextPath, context, 'utf8');
|
|
251
|
-
console.log(` 📋 Recipe 索引已生成 (轻量索引 + MCP 按需检索)`);
|
|
252
285
|
} else {
|
|
253
|
-
if (fs.existsSync(contextPath))
|
|
286
|
+
if (fs.existsSync(contextPath)) {
|
|
287
|
+
fs.unlinkSync(contextPath);
|
|
288
|
+
}
|
|
254
289
|
}
|
|
255
290
|
// 清理 V1 遗留的 by-category 切片(如存在)
|
|
256
291
|
const oldCatDir = path.join(refDir, 'by-category');
|
|
257
292
|
if (fs.existsSync(oldCatDir)) {
|
|
258
293
|
fs.rmSync(oldCatDir, { recursive: true });
|
|
259
|
-
console.log(` 🧹 已清理 V1 遗留 by-category 切片`);
|
|
260
294
|
}
|
|
261
295
|
const oldIndexJson = path.join(refDir, 'index.json');
|
|
262
|
-
if (fs.existsSync(oldIndexJson))
|
|
296
|
+
if (fs.existsSync(oldIndexJson)) {
|
|
297
|
+
fs.unlinkSync(oldIndexJson);
|
|
298
|
+
}
|
|
263
299
|
}
|
|
264
300
|
if (name === 'autosnippet-structure') {
|
|
265
301
|
// spmmap 摘要注入到 structure skill(替代已删除的 dep-graph skill)
|
|
266
302
|
const summary = buildSpmmapSummary(projectRoot);
|
|
267
303
|
const refDir = path.join(dest, 'references');
|
|
268
|
-
if (!fs.existsSync(refDir))
|
|
304
|
+
if (!fs.existsSync(refDir)) {
|
|
305
|
+
fs.mkdirSync(refDir, { recursive: true });
|
|
306
|
+
}
|
|
269
307
|
const summaryPath = path.join(refDir, 'spmmap-summary.md');
|
|
270
308
|
if (summary) {
|
|
271
309
|
fs.writeFileSync(summaryPath, summary, 'utf8');
|
|
272
|
-
console.log(` 🗺️ SPM 依赖摘要已生成`);
|
|
273
310
|
} else {
|
|
274
|
-
if (fs.existsSync(summaryPath))
|
|
311
|
+
if (fs.existsSync(summaryPath)) {
|
|
312
|
+
fs.unlinkSync(summaryPath);
|
|
313
|
+
}
|
|
275
314
|
}
|
|
276
315
|
}
|
|
277
316
|
if (name === 'autosnippet-guard') {
|
|
278
317
|
// V2: Guard 索引(同 recipes 索引),Agent 主路径走 MCP guard_check
|
|
279
318
|
const context = buildProjectRecipesContext(projectRoot);
|
|
280
319
|
const refDir = path.join(dest, 'references');
|
|
281
|
-
if (!fs.existsSync(refDir))
|
|
320
|
+
if (!fs.existsSync(refDir)) {
|
|
321
|
+
fs.mkdirSync(refDir, { recursive: true });
|
|
322
|
+
}
|
|
282
323
|
const guardPath = path.join(refDir, 'guard-context.md');
|
|
283
324
|
if (context) {
|
|
284
325
|
fs.writeFileSync(guardPath, context, 'utf8');
|
|
285
|
-
console.log(` 🛡️ Guard 索引已生成 (轻量 fallback)`);
|
|
286
326
|
} else {
|
|
287
|
-
if (fs.existsSync(guardPath))
|
|
327
|
+
if (fs.existsSync(guardPath)) {
|
|
328
|
+
fs.unlinkSync(guardPath);
|
|
329
|
+
}
|
|
288
330
|
}
|
|
289
331
|
}
|
|
290
332
|
}
|
|
@@ -293,17 +335,19 @@ for (const name of skillDirs) {
|
|
|
293
335
|
const cursorRulesSource = path.join(autoSnippetRoot, 'templates', 'cursor-rules');
|
|
294
336
|
const cursorRulesTarget = path.join(projectRoot, '.cursor', 'rules');
|
|
295
337
|
if (fs.existsSync(cursorRulesSource)) {
|
|
296
|
-
const ruleFiles = fs
|
|
297
|
-
|
|
298
|
-
|
|
338
|
+
const ruleFiles = fs
|
|
339
|
+
.readdirSync(cursorRulesSource, { withFileTypes: true })
|
|
340
|
+
.filter((d) => d.isFile() && d.name.toLowerCase().endsWith('.mdc'))
|
|
341
|
+
.map((d) => d.name);
|
|
299
342
|
if (ruleFiles.length > 0) {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
const
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
343
|
+
if (!fs.existsSync(cursorRulesTarget)) {
|
|
344
|
+
fs.mkdirSync(cursorRulesTarget, { recursive: true });
|
|
345
|
+
}
|
|
346
|
+
for (const name of ruleFiles) {
|
|
347
|
+
const src = path.join(cursorRulesSource, name);
|
|
348
|
+
const dest = path.join(cursorRulesTarget, name);
|
|
349
|
+
fs.copyFileSync(src, dest);
|
|
350
|
+
}
|
|
307
351
|
}
|
|
308
352
|
}
|
|
309
353
|
|
|
@@ -314,36 +358,36 @@ const addMcp = process.argv.includes('--mcp');
|
|
|
314
358
|
if (addMcp && fs.existsSync(mcpServerScript)) {
|
|
315
359
|
let mcp = { mcpServers: {} };
|
|
316
360
|
if (fs.existsSync(mcpPath)) {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
361
|
+
try {
|
|
362
|
+
mcp = JSON.parse(fs.readFileSync(mcpPath, 'utf8'));
|
|
363
|
+
if (!mcp.mcpServers) {
|
|
364
|
+
mcp.mcpServers = {};
|
|
365
|
+
}
|
|
366
|
+
} catch (_) {}
|
|
321
367
|
}
|
|
322
368
|
mcp.mcpServers.autosnippet = {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
369
|
+
type: 'stdio',
|
|
370
|
+
command: 'node',
|
|
371
|
+
args: [mcpServerScript],
|
|
372
|
+
env: { ASD_UI_URL: process.env.ASD_UI_URL || defaults.DEFAULT_ASD_UI_URL },
|
|
327
373
|
};
|
|
328
374
|
fs.mkdirSync(path.dirname(mcpPath), { recursive: true });
|
|
329
375
|
fs.writeFileSync(mcpPath, JSON.stringify(mcp, null, 2), 'utf8');
|
|
330
|
-
console.log(' ✅ MCP 配置');
|
|
331
376
|
} else if (addMcp) {
|
|
332
377
|
// mcp-server.js 不存在,已跳过
|
|
333
378
|
}
|
|
334
379
|
|
|
335
|
-
console.log('🎯 Cursor skills 已就绪,安装到项目:', projectRoot);
|
|
336
|
-
console.log(`\n📌 下一步:重启 Cursor 后生效`);
|
|
337
|
-
|
|
338
380
|
const runEmbed = process.argv.includes('--embed');
|
|
339
381
|
if (runEmbed) {
|
|
340
382
|
(async () => {
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
383
|
+
try {
|
|
384
|
+
const IndexingPipeline = require(
|
|
385
|
+
path.join(autoSnippetRoot, 'lib', 'context', 'IndexingPipeline')
|
|
386
|
+
);
|
|
387
|
+
const _result = await IndexingPipeline.run(projectRoot, { clear: false });
|
|
388
|
+
// 语义索引已更新
|
|
389
|
+
} catch (e) {
|
|
390
|
+
console.warn('⚠️ 语义索引更新失败:', e.message);
|
|
391
|
+
}
|
|
348
392
|
})().catch(() => process.exit(1));
|
|
349
393
|
}
|
package/scripts/install-full.js
CHANGED
|
@@ -6,53 +6,40 @@
|
|
|
6
6
|
* asd install:full --parser - 上述 + Swift 解析器
|
|
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
|
-
import path from 'node:path';
|
|
16
16
|
import fs from 'node:fs';
|
|
17
|
+
import path from 'node:path';
|
|
17
18
|
|
|
18
19
|
const rootDir = path.resolve(__dirname, '..');
|
|
19
|
-
const withParser =
|
|
20
|
-
|
|
20
|
+
const withParser =
|
|
21
|
+
process.env.ASD_INSTALL_PARSER === '1' || process.env.ASD_INSTALL_PARSER === 'true';
|
|
22
|
+
const withNativeUi =
|
|
23
|
+
process.env.ASD_INSTALL_NATIVE_UI === '1' || process.env.ASD_INSTALL_NATIVE_UI === 'true';
|
|
21
24
|
const dashboardDist = path.join(rootDir, 'dashboard', 'dist');
|
|
22
|
-
|
|
23
|
-
console.log('=== AutoSnippet 全量安装 ===\n');
|
|
24
|
-
|
|
25
|
-
// 1. 核心 + 可选依赖
|
|
26
|
-
console.log('1/4 安装核心与可选依赖...');
|
|
27
25
|
execSync('npm install', { cwd: rootDir, stdio: 'inherit' });
|
|
28
|
-
console.log('');
|
|
29
26
|
|
|
30
27
|
// 2. Dashboard(仅当前端不存在时安装并构建)
|
|
31
28
|
if (!fs.existsSync(dashboardDist)) {
|
|
32
|
-
console.log('2/4 前端不存在,安装并构建 Dashboard...');
|
|
33
29
|
const dashboardDir = path.join(rootDir, 'dashboard');
|
|
34
30
|
execSync('npm install', { cwd: dashboardDir, stdio: 'inherit' });
|
|
35
31
|
execSync('npm run build:dashboard', { cwd: rootDir, stdio: 'inherit' });
|
|
36
|
-
console.log('');
|
|
37
32
|
} else {
|
|
38
|
-
console.log('2/4 跳过 Dashboard(已存在预构建前端)');
|
|
39
|
-
console.log('');
|
|
40
33
|
}
|
|
41
34
|
|
|
42
35
|
// 3. ParsePackage / Native UI(可选)
|
|
43
36
|
if (withParser) {
|
|
44
|
-
console.log('3/4 构建 Swift 解析器(ParsePackage)...');
|
|
45
37
|
execSync('npm run build:parser', { cwd: rootDir, stdio: 'inherit' });
|
|
46
38
|
} else {
|
|
47
|
-
console.log('3/4 跳过 ParsePackage(需时执行 asd install:full --parser)');
|
|
48
39
|
}
|
|
49
40
|
if (withNativeUi || process.platform === 'darwin') {
|
|
50
|
-
console.log('4/4 构建 Native UI 辅助程序(macOS)...');
|
|
51
41
|
try {
|
|
52
|
-
|
|
42
|
+
await import('./build-native-ui.js');
|
|
53
43
|
} catch (_) {}
|
|
54
44
|
} else {
|
|
55
|
-
console.log('4/4 跳过 Native UI(非 macOS)');
|
|
56
45
|
}
|
|
57
|
-
|
|
58
|
-
console.log('\n✅ 全量安装完成');
|