autosnippet 3.2.18 → 3.2.21
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/LICENSE +1 -1
- package/README.md +73 -104
- package/config/default.json +1 -1
- package/dashboard/dist/assets/{index-CKMy5LY6.js → index-DdvZE4Yd.js} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/dist/bin/cli.js +45 -10
- package/dist/lib/agent/AgentEventBus.js +3 -3
- package/dist/lib/agent/AgentFactory.d.ts +3 -3
- package/dist/lib/agent/AgentFactory.js +4 -4
- package/dist/lib/agent/AgentMessage.d.ts +8 -8
- package/dist/lib/agent/AgentMessage.js +8 -8
- package/dist/lib/agent/AgentRuntime.js +2 -2
- package/dist/lib/agent/AgentState.js +4 -4
- package/dist/lib/agent/ConversationStore.d.ts +1 -1
- package/dist/lib/agent/ConversationStore.js +1 -1
- package/dist/lib/agent/PipelineStrategy.js +1 -1
- package/dist/lib/agent/context/ContextWindow.d.ts +2 -2
- package/dist/lib/agent/context/ContextWindow.js +7 -7
- package/dist/lib/agent/context/ExplorationTracker.js +9 -9
- package/dist/lib/agent/context/exploration/PlanTracker.js +2 -2
- package/dist/lib/agent/context/exploration/SignalDetector.d.ts +1 -1
- package/dist/lib/agent/context/exploration/SignalDetector.js +1 -1
- package/dist/lib/agent/core/LoopContext.d.ts +21 -21
- package/dist/lib/agent/core/LoopContext.js +21 -21
- package/dist/lib/agent/core/SystemPromptBuilder.js +4 -4
- package/dist/lib/agent/domain/EvidenceCollector.js +5 -5
- package/dist/lib/agent/memory/ActiveContext.js +1 -1
- package/dist/lib/agent/memory/MemoryRetriever.js +1 -1
- package/dist/lib/agent/memory/MemoryStore.js +2 -2
- package/dist/lib/agent/memory/SessionStore.js +3 -3
- package/dist/lib/agent/policies.d.ts +1 -1
- package/dist/lib/agent/policies.js +1 -1
- package/dist/lib/agent/strategies.d.ts +1 -1
- package/dist/lib/agent/strategies.js +4 -4
- package/dist/lib/agent/tools/_shared.d.ts +1 -1
- package/dist/lib/agent/tools/_shared.js +1 -1
- package/dist/lib/agent/tools/infrastructure.js +2 -2
- package/dist/lib/cli/SetupService.d.ts +25 -25
- package/dist/lib/cli/SetupService.js +28 -15
- package/dist/lib/cli/deploy/FileDeployer.d.ts +9 -2
- package/dist/lib/cli/deploy/FileDeployer.js +139 -46
- package/dist/lib/cli/deploy/FileManifest.d.ts +23 -39
- package/dist/lib/cli/deploy/FileManifest.js +22 -33
- package/dist/lib/core/AstAnalyzer.d.ts +2 -2
- package/dist/lib/core/AstAnalyzer.js +2 -2
- package/dist/lib/core/analysis/CallEdgeResolver.d.ts +7 -7
- package/dist/lib/core/analysis/CallEdgeResolver.js +9 -9
- package/dist/lib/core/analysis/CallGraphAnalyzer.d.ts +4 -4
- package/dist/lib/core/analysis/CallGraphAnalyzer.js +2 -2
- package/dist/lib/core/analysis/ImportPathResolver.d.ts +0 -2
- package/dist/lib/core/analysis/ImportPathResolver.js +2 -4
- package/dist/lib/core/ast/ProjectGraph.js +7 -7
- package/dist/lib/core/capability/CapabilityProbe.js +6 -14
- package/dist/lib/domain/knowledge/UnifiedValidator.js +2 -2
- package/dist/lib/domain/knowledge/values/Constraints.js +4 -4
- package/dist/lib/domain/knowledge/values/Content.js +6 -6
- package/dist/lib/domain/knowledge/values/Quality.js +5 -5
- package/dist/lib/domain/knowledge/values/Reasoning.js +5 -5
- package/dist/lib/domain/knowledge/values/Relations.js +1 -1
- package/dist/lib/domain/knowledge/values/Stats.js +6 -6
- package/dist/lib/domain/task/TaskIdGenerator.d.ts +4 -4
- package/dist/lib/domain/task/TaskIdGenerator.js +2 -2
- package/dist/lib/external/lark/LarkTransport.js +4 -4
- package/dist/lib/external/mcp/McpServer.d.ts +3 -7
- package/dist/lib/external/mcp/McpServer.js +9 -13
- package/dist/lib/external/mcp/handlers/bootstrap/ExternalSubmissionTracker.js +5 -5
- package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.js +4 -3
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.d.ts +3 -3
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.js +3 -3
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.d.ts +1 -1
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.js +1 -1
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/dimension-context.js +3 -3
- package/dist/lib/external/mcp/handlers/bootstrap/shared/dimension-sop.js +27 -14
- package/dist/lib/external/mcp/handlers/bootstrap-external.js +6 -0
- package/dist/lib/external/mcp/handlers/dimension-complete-external.js +55 -1
- package/dist/lib/external/mcp/handlers/skill.js +9 -31
- package/dist/lib/external/mcp/handlers/system.js +6 -4
- package/dist/lib/external/mcp/handlers/task.js +16 -1
- package/dist/lib/external/mcp/tools.d.ts +12 -10
- package/dist/lib/external/mcp/tools.js +97 -69
- package/dist/lib/http/utils/routeHelpers.d.ts +1 -1
- package/dist/lib/http/utils/routeHelpers.js +1 -1
- package/dist/lib/http/utils/sse-sessions.d.ts +1 -1
- package/dist/lib/http/utils/sse-sessions.js +1 -1
- package/dist/lib/infrastructure/cache/CacheService.js +1 -1
- package/dist/lib/infrastructure/logging/Logger.js +1 -1
- package/dist/lib/infrastructure/monitoring/ErrorTracker.js +1 -1
- package/dist/lib/infrastructure/vector/AsyncPersistence.js +8 -8
- package/dist/lib/infrastructure/vector/BatchEmbedder.d.ts +1 -1
- package/dist/lib/infrastructure/vector/BatchEmbedder.js +2 -2
- package/dist/lib/infrastructure/vector/HnswIndex.d.ts +4 -4
- package/dist/lib/infrastructure/vector/HnswIndex.js +5 -5
- package/dist/lib/infrastructure/vector/HnswVectorAdapter.js +8 -8
- package/dist/lib/infrastructure/vector/ScalarQuantizer.d.ts +1 -1
- package/dist/lib/infrastructure/vector/ScalarQuantizer.js +4 -4
- package/dist/lib/infrastructure/vector/VectorStore.d.ts +1 -1
- package/dist/lib/infrastructure/vector/VectorStore.js +1 -1
- package/dist/lib/injection/ServiceContainer.d.ts +1 -1
- package/dist/lib/injection/ServiceContainer.js +1 -1
- package/dist/lib/injection/modules/KnowledgeModule.js +4 -5
- package/dist/lib/platform/NativeUi.d.ts +1 -1
- package/dist/lib/platform/NativeUi.js +1 -1
- package/dist/lib/platform/ios/spm/DependencyGraph.d.ts +1 -1
- package/dist/lib/platform/ios/spm/DependencyGraph.js +1 -1
- package/dist/lib/platform/ios/spm/PolicyEngine.d.ts +1 -1
- package/dist/lib/platform/ios/spm/PolicyEngine.js +1 -1
- package/dist/lib/platform/ios/spm/SpmDiscoverer.js +1 -1
- package/dist/lib/platform/ios/spm/SpmHelper.js +3 -3
- package/dist/lib/platform/ios/xcode/SaveEventFilter.js +2 -2
- package/dist/lib/platform/ios/xcode/XcodeIntegration.js +1 -1
- package/dist/lib/repository/base/BaseRepository.js +1 -1
- package/dist/lib/repository/task/TaskRepository.impl.d.ts +2 -2
- package/dist/lib/repository/task/TaskRepository.impl.js +1 -1
- package/dist/lib/repository/token/TokenUsageStore.js +1 -1
- package/dist/lib/service/automation/ActionPipeline.d.ts +1 -1
- package/dist/lib/service/automation/ActionPipeline.js +1 -1
- package/dist/lib/service/bootstrap/BootstrapEventEmitter.js +2 -2
- package/dist/lib/service/bootstrap/BootstrapTaskManager.d.ts +1 -1
- package/dist/lib/service/bootstrap/BootstrapTaskManager.js +2 -2
- package/dist/lib/service/bootstrap/DimensionCopyRegistry.d.ts +2 -2
- package/dist/lib/service/bootstrap/DimensionCopyRegistry.js +2 -2
- package/dist/lib/service/delivery/AgentInstructionsGenerator.d.ts +6 -15
- package/dist/lib/service/delivery/AgentInstructionsGenerator.js +53 -189
- package/dist/lib/service/delivery/CursorDeliveryPipeline.d.ts +6 -16
- package/dist/lib/service/delivery/CursorDeliveryPipeline.js +14 -19
- package/dist/lib/service/delivery/KnowledgeCompressor.d.ts +1 -1
- package/dist/lib/service/delivery/KnowledgeCompressor.js +1 -1
- package/dist/lib/service/delivery/RulesGenerator.d.ts +10 -3
- package/dist/lib/service/delivery/RulesGenerator.js +43 -3
- package/dist/lib/service/delivery/SkillsSyncer.d.ts +21 -7
- package/dist/lib/service/delivery/SkillsSyncer.js +46 -10
- package/dist/lib/service/delivery/TopicClassifier.d.ts +3 -6
- package/dist/lib/service/delivery/TopicClassifier.js +0 -3
- package/dist/lib/service/guard/ExclusionManager.d.ts +1 -1
- package/dist/lib/service/guard/ExclusionManager.js +1 -1
- package/dist/lib/service/guard/GuardCheckEngine.d.ts +3 -3
- package/dist/lib/service/guard/GuardCheckEngine.js +5 -5
- package/dist/lib/service/guard/GuardCrossFileChecks.d.ts +1 -1
- package/dist/lib/service/guard/GuardFeedbackLoop.d.ts +3 -3
- package/dist/lib/service/guard/GuardFeedbackLoop.js +3 -3
- package/dist/lib/service/guard/GuardPatternUtils.js +1 -1
- package/dist/lib/service/guard/GuardService.d.ts +1 -15
- package/dist/lib/service/guard/GuardService.js +0 -1
- package/dist/lib/service/guard/RuleLearner.d.ts +1 -1
- package/dist/lib/service/guard/RuleLearner.js +1 -1
- package/dist/lib/service/knowledge/CodeEntityGraph.d.ts +3 -3
- package/dist/lib/service/knowledge/CodeEntityGraph.js +3 -3
- package/dist/lib/service/knowledge/KnowledgeService.d.ts +0 -1
- package/dist/lib/service/knowledge/KnowledgeService.js +0 -1
- package/dist/lib/service/module/ModuleService.d.ts +1 -1
- package/dist/lib/service/module/ModuleService.js +2 -2
- package/dist/lib/service/search/HybridRetriever.d.ts +2 -2
- package/dist/lib/service/search/HybridRetriever.js +2 -2
- package/dist/lib/service/search/SearchEngine.d.ts +1 -3
- package/dist/lib/service/search/SearchEngine.js +1 -3
- package/dist/lib/service/search/contextBoost.d.ts +1 -1
- package/dist/lib/service/skills/EventAggregator.js +2 -2
- package/dist/lib/service/skills/SignalCollector.js +1 -1
- package/dist/lib/service/snippet/codecs/VSCodeCodec.js +1 -1
- package/dist/lib/service/task/TaskGraphService.d.ts +0 -3
- package/dist/lib/service/task/TaskGraphService.js +0 -3
- package/dist/lib/service/task/TaskKnowledgeBridge.d.ts +8 -27
- package/dist/lib/service/task/TaskKnowledgeBridge.js +0 -8
- package/dist/lib/service/task/TaskReadyEngine.d.ts +1 -2
- package/dist/lib/service/task/TaskReadyEngine.js +0 -1
- package/dist/lib/service/wiki/WikiRenderers.js +0 -1
- package/dist/lib/service/wiki/WikiUtils.js +2 -7
- package/dist/lib/shared/PathGuard.js +6 -6
- package/dist/lib/shared/schemas/config.js +1 -1
- package/dist/lib/shared/schemas/mcp-tools.js +84 -43
- package/dist/scripts/install-vscode-copilot.js +14 -4
- package/package.json +1 -1
- package/skills/autosnippet-create/SKILL.md +131 -131
- package/skills/autosnippet-devdocs/SKILL.md +1 -2
- package/skills/autosnippet-guard/SKILL.md +20 -89
- package/skills/autosnippet-recipes/SKILL.md +35 -117
- package/skills/autosnippet-structure/SKILL.md +23 -55
- package/templates/cursor-rules/autosnippet-skills.mdc +17 -33
- package/templates/instructions/agent-static.md +24 -0
- package/templates/instructions/conventions.md +42 -0
- package/skills/autosnippet-analysis/SKILL.md +0 -169
- package/skills/autosnippet-candidates/SKILL.md +0 -367
- package/skills/autosnippet-coldstart/SKILL.md +0 -988
- package/skills/autosnippet-concepts/SKILL.md +0 -630
- package/skills/autosnippet-intent/SKILL.md +0 -55
- package/skills/autosnippet-lifecycle/SKILL.md +0 -100
- package/templates/copilot-instructions.md +0 -66
- package/templates/cursor-rules/autosnippet-conventions.mdc +0 -172
- package/templates/cursor-rules/autosnippet-workflow.mdc +0 -76
|
@@ -636,7 +636,7 @@ export class SearchEngine {
|
|
|
636
636
|
* - 已删除 → scorer.removeDocument()
|
|
637
637
|
* 3. 清空缓存以确保搜索结果刷新
|
|
638
638
|
*
|
|
639
|
-
* @param
|
|
639
|
+
* @param [opts] - force=true 强制全量重建
|
|
640
640
|
*/
|
|
641
641
|
refreshIndex(opts = {}) {
|
|
642
642
|
if (opts.force || !this._indexed || !this._lastIndexTime) {
|
|
@@ -689,7 +689,6 @@ export class SearchEngine {
|
|
|
689
689
|
* 使用 BM25F 思想:高价值字段(title, trigger)重复出现以提升 TF 权重
|
|
690
690
|
* — title ×3, trigger ×2, description ×1.5(通过重复 token 实现)
|
|
691
691
|
* 这确保标题匹配的文档获得显著更高的 BM25 分数
|
|
692
|
-
* @private
|
|
693
692
|
*/
|
|
694
693
|
_buildDocText(r) {
|
|
695
694
|
let contentText = '';
|
|
@@ -731,7 +730,6 @@ export class SearchEngine {
|
|
|
731
730
|
}
|
|
732
731
|
/**
|
|
733
732
|
* 从 DB 行构建文档 meta
|
|
734
|
-
* @private
|
|
735
733
|
*/
|
|
736
734
|
_buildDocMeta(r) {
|
|
737
735
|
let parsedTags = [];
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
/**
|
|
13
13
|
* @param items 已排序的候选列表(需有 rankerScore / coarseScore / score)
|
|
14
|
-
* @param
|
|
14
|
+
* @param [context.sessionHistory]
|
|
15
15
|
* @returns 含 contextScore / contextBoost 字段的排序列表
|
|
16
16
|
*/
|
|
17
17
|
export interface SearchItem {
|
|
@@ -22,9 +22,9 @@ const DEFAULT_WINDOW_MS = 5000; // 5 秒聚合窗口
|
|
|
22
22
|
const DEFAULT_MAX_BATCH = 50; // 单次 batch 最大事件数
|
|
23
23
|
const DEFAULT_DEDUPE_MS = 60_000; // 60 秒去重窗口
|
|
24
24
|
export class EventAggregator {
|
|
25
|
-
/**
|
|
25
|
+
/** >} */
|
|
26
26
|
#buckets = new Map();
|
|
27
|
-
/**
|
|
27
|
+
/** 已处理事件的 hash → 最后处理时间 */
|
|
28
28
|
#dedupeMap = new Map();
|
|
29
29
|
#listeners = new Map();
|
|
30
30
|
#windowMs;
|
|
@@ -61,7 +61,7 @@ export class VSCodeCodec extends SnippetCodec {
|
|
|
61
61
|
getBundleFilename() {
|
|
62
62
|
return BUNDLE_FILENAME;
|
|
63
63
|
}
|
|
64
|
-
/**
|
|
64
|
+
/** SnippetSpec → VSCode snippet entry */
|
|
65
65
|
#specToEntry(spec) {
|
|
66
66
|
const code = Array.isArray(spec.code) ? spec.code.join('\n') : spec.code || '';
|
|
67
67
|
// 自动将 Xcode 占位符转为 VSCode 格式
|
|
@@ -211,15 +211,12 @@ export declare class TaskGraphService {
|
|
|
211
211
|
* P2: 获取决策过期阈值(秒)
|
|
212
212
|
* 默认 30 天 = 2592000 秒。可通过容器内 'config' 服务配置。
|
|
213
213
|
* 返回 0 表示禁用过期检测。
|
|
214
|
-
* @private
|
|
215
214
|
*/
|
|
216
215
|
_getDecisionStaleThreshold(): number;
|
|
217
216
|
/**
|
|
218
217
|
* 查找因 closedTaskId 完成而新解除阻塞的任务
|
|
219
|
-
* @private
|
|
220
218
|
*/
|
|
221
219
|
_checkNewlyUnblocked(closedTaskId: string): string[];
|
|
222
|
-
/** @private */
|
|
223
220
|
_logEvent(taskId: string, eventType: string, oldValue: string | null, newValue: string | null): void;
|
|
224
221
|
}
|
|
225
222
|
export default TaskGraphService;
|
|
@@ -542,7 +542,6 @@ export class TaskGraphService {
|
|
|
542
542
|
* P2: 获取决策过期阈值(秒)
|
|
543
543
|
* 默认 30 天 = 2592000 秒。可通过容器内 'config' 服务配置。
|
|
544
544
|
* 返回 0 表示禁用过期检测。
|
|
545
|
-
* @private
|
|
546
545
|
*/
|
|
547
546
|
_getDecisionStaleThreshold() {
|
|
548
547
|
try {
|
|
@@ -565,7 +564,6 @@ export class TaskGraphService {
|
|
|
565
564
|
}
|
|
566
565
|
/**
|
|
567
566
|
* 查找因 closedTaskId 完成而新解除阻塞的任务
|
|
568
|
-
* @private
|
|
569
567
|
*/
|
|
570
568
|
_checkNewlyUnblocked(closedTaskId) {
|
|
571
569
|
const dependents = this.repo.getDependents(closedTaskId);
|
|
@@ -587,7 +585,6 @@ export class TaskGraphService {
|
|
|
587
585
|
}
|
|
588
586
|
return newlyReady;
|
|
589
587
|
}
|
|
590
|
-
/** @private */
|
|
591
588
|
_logEvent(taskId, eventType, oldValue, newValue) {
|
|
592
589
|
try {
|
|
593
590
|
this.repo.logEvent(taskId, eventType, oldValue, newValue);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { type SlimSearchResult } from '#service/search/SearchTypes.js';
|
|
2
1
|
import type { Task } from '../../domain/task/Task.js';
|
|
3
2
|
import Logger from '../../infrastructure/logging/Logger.js';
|
|
4
3
|
/** 知识注入的上下文选项(从 prime / ready / claim 透传) */
|
|
@@ -10,8 +9,6 @@ export interface KnowledgeEnrichOptions {
|
|
|
10
9
|
/** 当前编程语言 */
|
|
11
10
|
language?: string;
|
|
12
11
|
}
|
|
13
|
-
/** 投影后的知识条目(返回给 Agent)— 使用统一投影类型 */
|
|
14
|
-
type SlimKnowledgeItem = SlimSearchResult;
|
|
15
12
|
/**
|
|
16
13
|
* TaskKnowledgeBridge — 任务 ↔ 知识桥接服务
|
|
17
14
|
*
|
|
@@ -54,13 +51,8 @@ export declare class TaskKnowledgeBridge {
|
|
|
54
51
|
}): Promise<Record<string, unknown> | null>;
|
|
55
52
|
/**
|
|
56
53
|
* 为单个任务构建知识上下文(v2 — multi-query + 上下文 + 缓存)
|
|
57
|
-
* @private
|
|
58
54
|
*/
|
|
59
|
-
_buildContext
|
|
60
|
-
relatedKnowledge: SlimSearchResult[];
|
|
61
|
-
guardRules: SlimSearchResult[];
|
|
62
|
-
searchQuery: string;
|
|
63
|
-
} | null>;
|
|
55
|
+
private _buildContext;
|
|
64
56
|
/**
|
|
65
57
|
* P2: 构建多条互补搜索查询
|
|
66
58
|
*
|
|
@@ -69,45 +61,34 @@ export declare class TaskKnowledgeBridge {
|
|
|
69
61
|
* Q2 (语义): 用户输入 — 包含更丰富的自然语义
|
|
70
62
|
* Q3 (关键词): 从描述/用户输入提取技术术语
|
|
71
63
|
*
|
|
72
|
-
* @private
|
|
73
64
|
*/
|
|
74
|
-
_buildSearchQueries
|
|
65
|
+
private _buildSearchQueries;
|
|
75
66
|
/**
|
|
76
67
|
* P2: 从文本中提取技术术语(类名、文件名、API 名等)
|
|
77
|
-
* @private
|
|
78
68
|
*/
|
|
79
|
-
_extractTechTerms
|
|
69
|
+
private _extractTechTerms;
|
|
80
70
|
/**
|
|
81
71
|
* P2 + P3: Multi-Query 搜索 + 合并去重
|
|
82
72
|
*
|
|
83
73
|
* 对每个 query 执行搜索(并行),合并结果并按 score 去重保留最高分。
|
|
84
|
-
* @private
|
|
85
74
|
*/
|
|
86
|
-
_multiQuerySearch
|
|
87
|
-
language?: string;
|
|
88
|
-
}): Promise<Array<Record<string, unknown>>>;
|
|
75
|
+
private _multiQuerySearch;
|
|
89
76
|
/**
|
|
90
77
|
* 执行单次搜索(含 P3 上下文透传)
|
|
91
|
-
* @private
|
|
92
78
|
*/
|
|
93
|
-
_singleSearch
|
|
94
|
-
language?: string;
|
|
95
|
-
}): Promise<Array<Record<string, unknown>>>;
|
|
79
|
+
private _singleSearch;
|
|
96
80
|
/**
|
|
97
81
|
* P4: 相关性阈值判断
|
|
98
|
-
* @private
|
|
99
82
|
*/
|
|
100
|
-
_aboveThreshold
|
|
83
|
+
private _aboveThreshold;
|
|
101
84
|
/**
|
|
102
85
|
* P4: 增强投影 — 使用统一 slimSearchResult() 投影函数
|
|
103
|
-
* @private
|
|
104
86
|
*/
|
|
105
|
-
_projectItem
|
|
87
|
+
private _projectItem;
|
|
106
88
|
/**
|
|
107
89
|
* P6: 缓存键 — 基于 taskQuery + userQuery 的内容指纹
|
|
108
|
-
* @private
|
|
109
90
|
*/
|
|
110
|
-
_contentKey
|
|
91
|
+
private _contentKey;
|
|
111
92
|
/** 清除全部缓存(测试 / 索引重建后使用) */
|
|
112
93
|
clearCache(): void;
|
|
113
94
|
}
|
|
@@ -112,7 +112,6 @@ export class TaskKnowledgeBridge {
|
|
|
112
112
|
// ═══ 私有方法 ═══════════════════════════════════════
|
|
113
113
|
/**
|
|
114
114
|
* 为单个任务构建知识上下文(v2 — multi-query + 上下文 + 缓存)
|
|
115
|
-
* @private
|
|
116
115
|
*/
|
|
117
116
|
async _buildContext(task, options) {
|
|
118
117
|
const taskQuery = `${task.title} ${task.description}`.trim();
|
|
@@ -174,7 +173,6 @@ export class TaskKnowledgeBridge {
|
|
|
174
173
|
* Q2 (语义): 用户输入 — 包含更丰富的自然语义
|
|
175
174
|
* Q3 (关键词): 从描述/用户输入提取技术术语
|
|
176
175
|
*
|
|
177
|
-
* @private
|
|
178
176
|
*/
|
|
179
177
|
_buildSearchQueries(task, userQuery) {
|
|
180
178
|
const queries = [];
|
|
@@ -209,7 +207,6 @@ export class TaskKnowledgeBridge {
|
|
|
209
207
|
}
|
|
210
208
|
/**
|
|
211
209
|
* P2: 从文本中提取技术术语(类名、文件名、API 名等)
|
|
212
|
-
* @private
|
|
213
210
|
*/
|
|
214
211
|
_extractTechTerms(text) {
|
|
215
212
|
if (!text) {
|
|
@@ -234,7 +231,6 @@ export class TaskKnowledgeBridge {
|
|
|
234
231
|
* P2 + P3: Multi-Query 搜索 + 合并去重
|
|
235
232
|
*
|
|
236
233
|
* 对每个 query 执行搜索(并行),合并结果并按 score 去重保留最高分。
|
|
237
|
-
* @private
|
|
238
234
|
*/
|
|
239
235
|
async _multiQuerySearch(queries, options) {
|
|
240
236
|
if (queries.length === 0) {
|
|
@@ -262,7 +258,6 @@ export class TaskKnowledgeBridge {
|
|
|
262
258
|
}
|
|
263
259
|
/**
|
|
264
260
|
* 执行单次搜索(含 P3 上下文透传)
|
|
265
|
-
* @private
|
|
266
261
|
*/
|
|
267
262
|
async _singleSearch(query, options) {
|
|
268
263
|
const searchResult = await this._search.search(query, {
|
|
@@ -278,7 +273,6 @@ export class TaskKnowledgeBridge {
|
|
|
278
273
|
}
|
|
279
274
|
/**
|
|
280
275
|
* P4: 相关性阈值判断
|
|
281
|
-
* @private
|
|
282
276
|
*/
|
|
283
277
|
_aboveThreshold(item) {
|
|
284
278
|
const score = item.score || 0;
|
|
@@ -286,14 +280,12 @@ export class TaskKnowledgeBridge {
|
|
|
286
280
|
}
|
|
287
281
|
/**
|
|
288
282
|
* P4: 增强投影 — 使用统一 slimSearchResult() 投影函数
|
|
289
|
-
* @private
|
|
290
283
|
*/
|
|
291
284
|
_projectItem(item) {
|
|
292
285
|
return slimSearchResult(item);
|
|
293
286
|
}
|
|
294
287
|
/**
|
|
295
288
|
* P6: 缓存键 — 基于 taskQuery + userQuery 的内容指纹
|
|
296
|
-
* @private
|
|
297
289
|
*/
|
|
298
290
|
_contentKey(taskQuery, userQuery) {
|
|
299
291
|
return `${taskQuery}||${userQuery || ''}`;
|
|
@@ -15,8 +15,7 @@ export declare class TaskReadyEngine {
|
|
|
15
15
|
_readyStmt: ReturnType<import('better-sqlite3').Database['prepare']>;
|
|
16
16
|
/** @param db raw SQLite handle */
|
|
17
17
|
constructor(db: import('better-sqlite3').Database);
|
|
18
|
-
|
|
19
|
-
_prepareStatements(): void;
|
|
18
|
+
private _prepareStatements;
|
|
20
19
|
/**
|
|
21
20
|
* 获取就绪任务(核心方法)
|
|
22
21
|
*
|
|
@@ -1100,7 +1100,6 @@ export function renderGettingStarted(project, modules, ast, isZh) {
|
|
|
1100
1100
|
const BUILD_SYSTEM_FILES = Object.fromEntries(LanguageService.buildSystemMarkers.map((m) => [m.buildTool, m.file]));
|
|
1101
1101
|
/**
|
|
1102
1102
|
* 按生态系统输出构建步骤
|
|
1103
|
-
* @private
|
|
1104
1103
|
*/
|
|
1105
1104
|
function _pushBuildSteps(lines, buildSys, projectName, isZh) {
|
|
1106
1105
|
const { eco, buildTool } = buildSys;
|
|
@@ -548,7 +548,7 @@ export function profileFolders(projectInfo, options = {}) {
|
|
|
548
548
|
const root = projectInfo.root;
|
|
549
549
|
const sourceFiles = projectInfo.sourceFiles || [];
|
|
550
550
|
// ── 1. 按文件夹分组源文件 ──
|
|
551
|
-
/**
|
|
551
|
+
/** relDir → [relFilePath, ...] */
|
|
552
552
|
const folderFiles = new Map();
|
|
553
553
|
for (const relFile of sourceFiles) {
|
|
554
554
|
const dir = path.dirname(relFile);
|
|
@@ -558,7 +558,7 @@ export function profileFolders(projectInfo, options = {}) {
|
|
|
558
558
|
folderFiles.get(dir).push(relFile);
|
|
559
559
|
}
|
|
560
560
|
// ── 2. 聚合: 将子文件夹的文件计入父文件夹 (递归) ──
|
|
561
|
-
/**
|
|
561
|
+
/** relDir → 所有递归子文件 */
|
|
562
562
|
const folderRecursive = new Map();
|
|
563
563
|
for (const [dir, files] of folderFiles) {
|
|
564
564
|
// 把文件计入 dir 本身及所有祖先
|
|
@@ -612,7 +612,6 @@ export function profileFolders(projectInfo, options = {}) {
|
|
|
612
612
|
}
|
|
613
613
|
/**
|
|
614
614
|
* 修剪冗余文件夹: 如果子目录文件数与父目录接近 (>80%), 仅保留父目录
|
|
615
|
-
* @private
|
|
616
615
|
*/
|
|
617
616
|
function _pruneRedundantFolders(candidates, maxFolders) {
|
|
618
617
|
const kept = [];
|
|
@@ -649,7 +648,6 @@ function _pruneRedundantFolders(candidates, maxFolders) {
|
|
|
649
648
|
}
|
|
650
649
|
/**
|
|
651
650
|
* 为单个文件夹构建 FolderProfile
|
|
652
|
-
* @private
|
|
653
651
|
*/
|
|
654
652
|
function _buildFolderProfile(relDir, files, depth, projectRoot, sampleLines) {
|
|
655
653
|
const fullDir = path.join(projectRoot, relDir);
|
|
@@ -735,7 +733,6 @@ function _buildFolderProfile(relDir, files, depth, projectRoot, sampleLines) {
|
|
|
735
733
|
}
|
|
736
734
|
/**
|
|
737
735
|
* 从文件名列表检测命名约定
|
|
738
|
-
* @private
|
|
739
736
|
* @param fileNames basename 列表
|
|
740
737
|
*/
|
|
741
738
|
function _detectNamingPatterns(fileNames) {
|
|
@@ -781,7 +778,6 @@ function _detectNamingPatterns(fileNames) {
|
|
|
781
778
|
}
|
|
782
779
|
/**
|
|
783
780
|
* 从文件顶部提取 import/require 语句,推断文件夹级依赖
|
|
784
|
-
* @private
|
|
785
781
|
*/
|
|
786
782
|
function _extractImports(keyFiles, projectRoot, sampleLines, currentDir) {
|
|
787
783
|
const importTargets = new Set();
|
|
@@ -883,7 +879,6 @@ function _extractImports(keyFiles, projectRoot, sampleLines, currentDir) {
|
|
|
883
879
|
}
|
|
884
880
|
/**
|
|
885
881
|
* 提取文件头部注释 (第一个注释块)
|
|
886
|
-
* @private
|
|
887
882
|
*/
|
|
888
883
|
function _extractHeaderComment(fullPath) {
|
|
889
884
|
try {
|
|
@@ -62,17 +62,17 @@ const PROJECT_WRITE_SCOPE_PREFIXES = [
|
|
|
62
62
|
const PROJECT_ROOT_WRITABLE_FILES = ['.gitignore', '.env'];
|
|
63
63
|
class PathGuard {
|
|
64
64
|
targetPath;
|
|
65
|
-
/**
|
|
65
|
+
/** 项目根目录(绝对路径) */
|
|
66
66
|
#projectRoot = null;
|
|
67
|
-
/**
|
|
67
|
+
/** AutoSnippet 包自身根目录 */
|
|
68
68
|
#packageRoot = null;
|
|
69
|
-
/**
|
|
69
|
+
/** 额外允许的绝对路径前缀 */
|
|
70
70
|
#allowList = new Set();
|
|
71
|
-
/**
|
|
71
|
+
/** 知识库目录名(如 'AutoSnippet') */
|
|
72
72
|
#knowledgeBaseDir = null;
|
|
73
|
-
/**
|
|
73
|
+
/** 是否已配置 */
|
|
74
74
|
#configured = false;
|
|
75
|
-
/**
|
|
75
|
+
/** projectRoot 是否是 AutoSnippet 自身的开发仓库 */
|
|
76
76
|
#isDevRepo = false;
|
|
77
77
|
/**
|
|
78
78
|
* 配置 PathGuard(每个进程执行一次)
|
|
@@ -32,7 +32,7 @@ const MonitoringConfig = z.object({
|
|
|
32
32
|
});
|
|
33
33
|
const FileLogConfig = z.object({
|
|
34
34
|
enabled: z.boolean().default(true),
|
|
35
|
-
path: z.string().default('
|
|
35
|
+
path: z.string().default('./.autosnippet/logs'),
|
|
36
36
|
});
|
|
37
37
|
const LoggingConfig = z.object({
|
|
38
38
|
level: z.enum(['debug', 'info', 'warn', 'error', 'silent']).default('info'),
|
|
@@ -18,11 +18,14 @@ export const HealthInput = z.object({});
|
|
|
18
18
|
// 2. autosnippet_search
|
|
19
19
|
// ══════════════════════════════════════════════════════
|
|
20
20
|
export const SearchInput = z.object({
|
|
21
|
-
query: z.string().min(1, 'query is required'),
|
|
22
|
-
mode: z
|
|
23
|
-
|
|
21
|
+
query: z.string().min(1, 'query is required').describe('搜索关键词或自然语言描述'),
|
|
22
|
+
mode: z
|
|
23
|
+
.enum(['auto', 'keyword', 'bm25', 'semantic', 'context'])
|
|
24
|
+
.default('auto')
|
|
25
|
+
.describe('auto=自动选策略 | keyword=精确匹配 | bm25=全文检索 | semantic=向量语义 | context=综合+上下文'),
|
|
26
|
+
kind: KindEnum.default('all').describe('过滤知识类型: all/rule/pattern/fact'),
|
|
24
27
|
limit: z.number().int().min(1).max(100).default(10),
|
|
25
|
-
language: z.string().optional(),
|
|
28
|
+
language: z.string().optional().describe('按编程语言过滤,如 swift/typescript'),
|
|
26
29
|
sessionId: z.string().optional(),
|
|
27
30
|
sessionHistory: z.array(z.record(z.string(), z.unknown())).optional(),
|
|
28
31
|
});
|
|
@@ -31,8 +34,11 @@ export const SearchInput = z.object({
|
|
|
31
34
|
// ══════════════════════════════════════════════════════
|
|
32
35
|
export const KnowledgeInput = z
|
|
33
36
|
.object({
|
|
34
|
-
operation: z
|
|
35
|
-
|
|
37
|
+
operation: z
|
|
38
|
+
.enum(['list', 'get', 'insights', 'confirm_usage'])
|
|
39
|
+
.default('list')
|
|
40
|
+
.describe('list=列表 | get=单条详情(id) | insights=质量分析(id) | confirm_usage=记录采纳(id)'),
|
|
41
|
+
id: z.string().optional().describe('get/insights/confirm_usage 时必填'),
|
|
36
42
|
kind: KindEnum.optional(),
|
|
37
43
|
language: z.string().optional(),
|
|
38
44
|
category: z.string().optional(),
|
|
@@ -53,8 +59,11 @@ export const KnowledgeInput = z
|
|
|
53
59
|
// 4. autosnippet_structure
|
|
54
60
|
// ══════════════════════════════════════════════════════
|
|
55
61
|
export const StructureInput = z.object({
|
|
56
|
-
operation: z
|
|
57
|
-
|
|
62
|
+
operation: z
|
|
63
|
+
.enum(['targets', 'files', 'metadata'])
|
|
64
|
+
.default('targets')
|
|
65
|
+
.describe('targets=构建目标列表 | files=Target文件列表 | metadata=项目元数据'),
|
|
66
|
+
targetName: z.string().optional().describe('files 操作时指定目标名'),
|
|
58
67
|
includeSummary: z.boolean().default(true),
|
|
59
68
|
includeContent: z.boolean().default(false),
|
|
60
69
|
contentMaxLines: z.number().int().min(1).default(100),
|
|
@@ -64,8 +73,10 @@ export const StructureInput = z.object({
|
|
|
64
73
|
// 5. autosnippet_graph
|
|
65
74
|
// ══════════════════════════════════════════════════════
|
|
66
75
|
export const GraphInput = z.object({
|
|
67
|
-
operation: z
|
|
68
|
-
|
|
76
|
+
operation: z
|
|
77
|
+
.enum(['query', 'impact', 'path', 'stats'])
|
|
78
|
+
.describe('query=节点关系 | impact=影响分析 | path=路径查找 | stats=全局统计'),
|
|
79
|
+
nodeId: z.string().optional().describe('query/impact 时指定节点 ID'),
|
|
69
80
|
nodeType: z.string().default('recipe'),
|
|
70
81
|
fromId: z.string().optional(),
|
|
71
82
|
toId: z.string().optional(),
|
|
@@ -77,8 +88,11 @@ export const GraphInput = z.object({
|
|
|
77
88
|
// 6. autosnippet_call_context
|
|
78
89
|
// ══════════════════════════════════════════════════════
|
|
79
90
|
export const CallContextInput = z.object({
|
|
80
|
-
methodName: z.string().min(1, 'methodName is required'),
|
|
81
|
-
direction: z
|
|
91
|
+
methodName: z.string().min(1, 'methodName is required').describe('函数/方法名称,支持部分匹配'),
|
|
92
|
+
direction: z
|
|
93
|
+
.enum(['callers', 'callees', 'both', 'impact'])
|
|
94
|
+
.default('both')
|
|
95
|
+
.describe('callers=上游调用者 | callees=下游依赖 | both=双向 | impact=影响半径'),
|
|
82
96
|
maxDepth: z.number().int().min(1).max(5).default(2),
|
|
83
97
|
});
|
|
84
98
|
// ══════════════════════════════════════════════════════
|
|
@@ -95,21 +109,33 @@ export const GuardInput = z.object({
|
|
|
95
109
|
// ══════════════════════════════════════════════════════
|
|
96
110
|
export const SubmitKnowledgeInput = z.object({
|
|
97
111
|
// ── 必填字段 ──
|
|
98
|
-
title: TitleField,
|
|
99
|
-
language: LanguageField,
|
|
100
|
-
content: ContentSchema,
|
|
101
|
-
kind: StrictKindEnum,
|
|
102
|
-
doClause: z
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
112
|
+
title: TitleField.describe('知识标题,简洁明确'),
|
|
113
|
+
language: LanguageField.describe('编程语言,如 typescript/swift/python'),
|
|
114
|
+
content: ContentSchema.describe('内容对象: { pattern?: "代码片段", markdown?: "正文", rationale: "设计原理" }。pattern/markdown 至少提供一个,rationale 必填'),
|
|
115
|
+
kind: StrictKindEnum.describe('rule=规范约束 | pattern=代码模式 | fact=项目事实'),
|
|
116
|
+
doClause: z
|
|
117
|
+
.string()
|
|
118
|
+
.min(1, 'doClause is required')
|
|
119
|
+
.describe('✅ 应该怎么做(Channel A+B 硬依赖)'),
|
|
120
|
+
dontClause: z.string().min(1, 'dontClause is required').describe('❌ 不应该怎么做'),
|
|
121
|
+
whenClause: z.string().min(1, 'whenClause is required').describe('何时适用(Channel B 硬依赖)'),
|
|
122
|
+
coreCode: z.string().min(1, 'coreCode is required').describe('核心代码片段(Channel B 模板块)'),
|
|
123
|
+
category: z
|
|
124
|
+
.string()
|
|
125
|
+
.min(1, 'category is required')
|
|
126
|
+
.describe('View/Service/Tool/Model/Network/Storage/UI/Utility'),
|
|
127
|
+
trigger: z.string().min(1, 'trigger is required').describe('触发关键词,如 @NetworkMonitor'),
|
|
128
|
+
description: z.string().min(1, 'description is required').describe('一句话描述用途'),
|
|
129
|
+
headers: z.array(z.string()).describe('完整 import 语句列表'),
|
|
130
|
+
usageGuide: z
|
|
131
|
+
.string()
|
|
132
|
+
.min(1, 'usageGuide is required')
|
|
133
|
+
.describe('使用指南(Markdown,用 ### 分节:何时用/关键点/何时不用)'),
|
|
134
|
+
knowledgeType: z
|
|
135
|
+
.string()
|
|
136
|
+
.min(1, 'knowledgeType is required')
|
|
137
|
+
.describe('code-pattern/architecture/best-practice/code-standard 等'),
|
|
138
|
+
reasoning: ReasoningSchema.describe('推理对象: { whyStandard: "原因", sources: ["来源"], confidence: 0.0-1.0 }'),
|
|
113
139
|
// ── 可选字段 ──
|
|
114
140
|
topicHint: z.string().optional(),
|
|
115
141
|
complexity: ComplexityEnum.optional(),
|
|
@@ -130,12 +156,18 @@ export const SubmitKnowledgeInput = z.object({
|
|
|
130
156
|
// 8. autosnippet_submit_knowledge_batch
|
|
131
157
|
// ══════════════════════════════════════════════════════
|
|
132
158
|
export const SubmitKnowledgeBatchInput = z.object({
|
|
133
|
-
target_name: z
|
|
134
|
-
|
|
159
|
+
target_name: z
|
|
160
|
+
.string()
|
|
161
|
+
.min(1, 'target_name is required')
|
|
162
|
+
.describe('批量来源标识,如 network-module-scan'),
|
|
163
|
+
items: z
|
|
164
|
+
.array(z.record(z.string(), z.unknown()))
|
|
165
|
+
.min(1, 'items array must not be empty')
|
|
166
|
+
.describe('知识条目数组,每条字段同 submit_knowledge。content/reasoning 必须是对象'),
|
|
135
167
|
source: z.string().default('cursor-scan'),
|
|
136
|
-
deduplicate: z.boolean().default(true),
|
|
168
|
+
deduplicate: z.boolean().default(true).describe('基于 title 自动去重,默认开启'),
|
|
137
169
|
client_id: z.string().optional(),
|
|
138
|
-
dimensionId: z.string().optional(),
|
|
170
|
+
dimensionId: z.string().optional().describe('冷启动时关联维度 ID'),
|
|
139
171
|
});
|
|
140
172
|
// ══════════════════════════════════════════════════════
|
|
141
173
|
// 9. autosnippet_save_document
|
|
@@ -152,12 +184,14 @@ export const SaveDocumentInput = z.object({
|
|
|
152
184
|
// 10. autosnippet_skill
|
|
153
185
|
// ══════════════════════════════════════════════════════
|
|
154
186
|
export const SkillInput = z.object({
|
|
155
|
-
operation: z
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
187
|
+
operation: z
|
|
188
|
+
.enum(['list', 'load', 'create', 'update', 'delete', 'suggest'])
|
|
189
|
+
.describe('list=列表 | load=加载内容(name) | create=创建 | update=更新 | delete=删除 | suggest=推荐'),
|
|
190
|
+
name: z.string().optional().describe('Skill 名称(kebab-case,如 autosnippet-create)'),
|
|
191
|
+
skillName: z.string().optional().describe('name 的别名,与 name 等价'),
|
|
192
|
+
section: z.string().optional().describe('load 时过滤指定章节'),
|
|
193
|
+
description: z.string().optional().describe('create/update 时的简短描述'),
|
|
194
|
+
content: z.string().optional().describe('create/update 时的 Markdown 内容'),
|
|
161
195
|
overwrite: z.boolean().default(false),
|
|
162
196
|
createdBy: z.enum(['manual', 'user-ai', 'system-ai', 'external-ai']).default('external-ai'),
|
|
163
197
|
});
|
|
@@ -172,7 +206,10 @@ export const DimensionCompleteInput = z.object({
|
|
|
172
206
|
sessionId: z.string().optional(),
|
|
173
207
|
dimensionId: z.string().min(1, 'dimensionId is required'),
|
|
174
208
|
submittedRecipeIds: z.array(z.string()).optional(),
|
|
175
|
-
analysisText: z
|
|
209
|
+
analysisText: z
|
|
210
|
+
.string()
|
|
211
|
+
.min(1, 'analysisText is required')
|
|
212
|
+
.describe('维度分析报告(Markdown)。写得越详细,生成的 Skill 质量越高;若过短,系统会自动从候选知识中合成。'),
|
|
176
213
|
referencedFiles: z.array(z.string()).optional(),
|
|
177
214
|
keyFindings: z.array(z.string()).optional(),
|
|
178
215
|
candidateCount: z.number().int().min(0).optional(),
|
|
@@ -199,7 +236,8 @@ export const CapabilitiesInput = z.object({});
|
|
|
199
236
|
// 13. autosnippet_task
|
|
200
237
|
// ══════════════════════════════════════════════════════
|
|
201
238
|
export const TaskInput = z.object({
|
|
202
|
-
operation: z
|
|
239
|
+
operation: z
|
|
240
|
+
.enum([
|
|
203
241
|
'prime',
|
|
204
242
|
'ready',
|
|
205
243
|
'create',
|
|
@@ -219,7 +257,8 @@ export const TaskInput = z.object({
|
|
|
219
257
|
'revise_decision',
|
|
220
258
|
'unpin_decision',
|
|
221
259
|
'list_decisions',
|
|
222
|
-
])
|
|
260
|
+
])
|
|
261
|
+
.describe('会话: prime(首选) | ready。任务: create/claim/close/fail/defer/progress/show/list/stats/blocked。分解: decompose/dep_add/dep_tree。决策: record_decision/revise_decision/unpin_decision/list_decisions'),
|
|
223
262
|
title: z.string().optional(),
|
|
224
263
|
description: z.string().optional(),
|
|
225
264
|
design: z.string().optional(),
|
|
@@ -276,7 +315,8 @@ export const EnrichCandidatesInput = z.object({
|
|
|
276
315
|
// 15. autosnippet_knowledge_lifecycle
|
|
277
316
|
export const KnowledgeLifecycleInput = z.object({
|
|
278
317
|
id: IdField,
|
|
279
|
-
action: z
|
|
318
|
+
action: z
|
|
319
|
+
.enum([
|
|
280
320
|
'submit',
|
|
281
321
|
'approve',
|
|
282
322
|
'reject',
|
|
@@ -285,8 +325,9 @@ export const KnowledgeLifecycleInput = z.object({
|
|
|
285
325
|
'reactivate',
|
|
286
326
|
'to_draft',
|
|
287
327
|
'fast_track',
|
|
288
|
-
])
|
|
289
|
-
|
|
328
|
+
])
|
|
329
|
+
.describe('approve/fast_track=发布 | reject=拒绝 | deprecate=废弃 | reactivate=恢复 | to_draft=回草稿'),
|
|
330
|
+
reason: z.string().optional().describe('reject/deprecate 时的理由'),
|
|
290
331
|
});
|
|
291
332
|
// 16. autosnippet_validate_candidate
|
|
292
333
|
export const ValidateCandidateInput = z.object({
|
|
@@ -151,16 +151,26 @@ function createCopilotInstructions() {
|
|
|
151
151
|
log(`✓ 项目指令已存在,跳过创建`, 'yellow');
|
|
152
152
|
return true;
|
|
153
153
|
}
|
|
154
|
-
//
|
|
155
|
-
const templatePath = path.join(TEMPLATES_DIR, '
|
|
154
|
+
// 从 conventions 模板生成(读模板 + 包装 HTML markers)
|
|
155
|
+
const templatePath = path.join(TEMPLATES_DIR, 'instructions/conventions.md');
|
|
156
156
|
if (!fs.existsSync(templatePath)) {
|
|
157
157
|
error(`✗ 模板文件不存在: ${templatePath}`);
|
|
158
158
|
return false;
|
|
159
159
|
}
|
|
160
|
-
const
|
|
160
|
+
const body = fs.readFileSync(templatePath, 'utf8').trimEnd();
|
|
161
|
+
const content = [
|
|
162
|
+
'<!-- autosnippet:begin -->',
|
|
163
|
+
'',
|
|
164
|
+
'# AutoSnippet Conventions',
|
|
165
|
+
'',
|
|
166
|
+
body,
|
|
167
|
+
'',
|
|
168
|
+
'<!-- autosnippet:end -->',
|
|
169
|
+
'',
|
|
170
|
+
].join('\n');
|
|
161
171
|
try {
|
|
162
172
|
fs.mkdirSync(path.dirname(instructionsPath), { recursive: true });
|
|
163
|
-
fs.writeFileSync(instructionsPath,
|
|
173
|
+
fs.writeFileSync(instructionsPath, content, 'utf8');
|
|
164
174
|
log(`✅ 项目指令生成完成: ${instructionsPath}`, 'green');
|
|
165
175
|
return true;
|
|
166
176
|
}
|