autosnippet 3.0.1 → 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 +655 -260
- 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
|
@@ -9,28 +9,77 @@
|
|
|
9
9
|
* watcher.start();
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {
|
|
13
|
-
import { readFileSync, accessSync, statSync } from 'node:fs';
|
|
12
|
+
import { accessSync, readFileSync, statSync } from 'node:fs';
|
|
14
13
|
import { basename, join, normalize } from 'node:path';
|
|
15
|
-
import {
|
|
16
|
-
import { saveEventFilter } from './SaveEventFilter.js';
|
|
14
|
+
import { watch as chokidarWatch } from 'chokidar';
|
|
17
15
|
import { FILE_WATCHER } from '../../shared/constants.js';
|
|
16
|
+
import { detectTriggers, REGEX } from './DirectiveDetector.js';
|
|
17
|
+
import { handleAlink } from './handlers/AlinkHandler.js';
|
|
18
18
|
|
|
19
19
|
/* ── Handler imports ── */
|
|
20
20
|
import { handleCreate } from './handlers/CreateHandler.js';
|
|
21
|
+
import { handleDraft } from './handlers/DraftHandler.js';
|
|
21
22
|
import { handleGuard } from './handlers/GuardHandler.js';
|
|
22
|
-
import { handleSearch } from './handlers/SearchHandler.js';
|
|
23
|
-
import { handleAlink } from './handlers/AlinkHandler.js';
|
|
24
23
|
import { handleHeader } from './handlers/HeaderHandler.js';
|
|
25
|
-
import {
|
|
24
|
+
import { handleSearch } from './handlers/SearchHandler.js';
|
|
25
|
+
import { saveEventFilter } from '../../platform/ios/xcode/SaveEventFilter.js';
|
|
26
26
|
|
|
27
27
|
/* ────────── 配置 ────────── */
|
|
28
28
|
|
|
29
|
-
const DEFAULT_FILE_PATTERN = [
|
|
29
|
+
const DEFAULT_FILE_PATTERN = [
|
|
30
|
+
// ObjC/Swift
|
|
31
|
+
'**/*.m',
|
|
32
|
+
'**/*.h',
|
|
33
|
+
'**/*.mm',
|
|
34
|
+
'**/*.swift',
|
|
35
|
+
// JS/TS
|
|
36
|
+
'**/*.js',
|
|
37
|
+
'**/*.ts',
|
|
38
|
+
'**/*.jsx',
|
|
39
|
+
'**/*.tsx',
|
|
40
|
+
'**/*.vue',
|
|
41
|
+
'**/*.svelte',
|
|
42
|
+
// Python
|
|
43
|
+
'**/*.py',
|
|
44
|
+
// JVM
|
|
45
|
+
'**/*.java',
|
|
46
|
+
'**/*.kt',
|
|
47
|
+
'**/*.kts',
|
|
48
|
+
// Other languages
|
|
49
|
+
'**/*.go',
|
|
50
|
+
'**/*.rs',
|
|
51
|
+
'**/*.rb',
|
|
52
|
+
// C/C++
|
|
53
|
+
'**/*.c',
|
|
54
|
+
'**/*.cpp',
|
|
55
|
+
'**/*.cc',
|
|
56
|
+
'**/*.hpp',
|
|
57
|
+
// Draft
|
|
58
|
+
'**/_draft_*.md',
|
|
59
|
+
];
|
|
30
60
|
const IGNORED = [
|
|
31
|
-
'**/node_modules/**',
|
|
32
|
-
'
|
|
33
|
-
'
|
|
61
|
+
'**/node_modules/**',
|
|
62
|
+
'**/.git/**',
|
|
63
|
+
'**/.mgit/**',
|
|
64
|
+
'**/.easybox/**',
|
|
65
|
+
'**/xcuserdata/**',
|
|
66
|
+
'**/.build/**',
|
|
67
|
+
'**/*.swp',
|
|
68
|
+
'**/*.tmp',
|
|
69
|
+
'**/*~.m',
|
|
70
|
+
'**/*~.h',
|
|
71
|
+
'**/DerivedData/**',
|
|
72
|
+
'**/Pods/**',
|
|
73
|
+
'**/Carthage/**',
|
|
74
|
+
'**/__pycache__/**',
|
|
75
|
+
'**/.venv/**',
|
|
76
|
+
'**/venv/**',
|
|
77
|
+
'**/build/**',
|
|
78
|
+
'**/target/**',
|
|
79
|
+
'**/.gradle/**',
|
|
80
|
+
'**/dist/**',
|
|
81
|
+
'**/.next/**',
|
|
82
|
+
'**/.nuxt/**',
|
|
34
83
|
];
|
|
35
84
|
const DEBOUNCE_DELAY = FILE_WATCHER.DEBOUNCE_DELAY_MS;
|
|
36
85
|
|
|
@@ -65,11 +114,11 @@ export class FileWatcher {
|
|
|
65
114
|
start() {
|
|
66
115
|
const watchRoot = this.projectRoot;
|
|
67
116
|
const filePattern = this.exts
|
|
68
|
-
? this.exts.map((e) => `**/*${e.startsWith('.') ? e :
|
|
117
|
+
? this.exts.map((e) => `**/*${e.startsWith('.') ? e : `.${e}`}`)
|
|
69
118
|
: DEFAULT_FILE_PATTERN;
|
|
70
119
|
|
|
71
120
|
if (!this.quiet) {
|
|
72
|
-
console.log(
|
|
121
|
+
console.log('\n👁️ 文件监听已启动 — Xcode 模式');
|
|
73
122
|
}
|
|
74
123
|
|
|
75
124
|
this._watcher = chokidarWatch(filePattern, {
|
|
@@ -77,7 +126,10 @@ export class FileWatcher {
|
|
|
77
126
|
ignored: IGNORED,
|
|
78
127
|
ignoreInitial: true,
|
|
79
128
|
persistent: true,
|
|
80
|
-
awaitWriteFinish: {
|
|
129
|
+
awaitWriteFinish: {
|
|
130
|
+
stabilityThreshold: FILE_WATCHER.STABILITY_THRESHOLD_MS,
|
|
131
|
+
pollInterval: FILE_WATCHER.POLL_INTERVAL_MS,
|
|
132
|
+
},
|
|
81
133
|
usePolling: process.env.ASD_WATCH_POLLING === 'true',
|
|
82
134
|
interval: FILE_WATCHER.POLL_INTERVAL_MS,
|
|
83
135
|
binaryInterval: FILE_WATCHER.BINARY_INTERVAL_MS,
|
|
@@ -87,7 +139,6 @@ export class FileWatcher {
|
|
|
87
139
|
const fullPath = join(watchRoot, relativePath);
|
|
88
140
|
|
|
89
141
|
if (process.env.ASD_DEBUG === '1') {
|
|
90
|
-
console.log(`[Watch] 检测到文件变化: ${relativePath}`);
|
|
91
142
|
}
|
|
92
143
|
|
|
93
144
|
if (this.pathPrefix && !normalize(relativePath).startsWith(normalize(this.pathPrefix))) {
|
|
@@ -104,11 +155,8 @@ export class FileWatcher {
|
|
|
104
155
|
this._watcher.on('error', (err) => console.error('文件监听错误:', err.message));
|
|
105
156
|
this._watcher.on('ready', () => {
|
|
106
157
|
if (!this.quiet) {
|
|
107
|
-
console.log('文件监听器已就绪,等待文件变更...');
|
|
108
158
|
}
|
|
109
159
|
if (process.env.ASD_DEBUG === '1') {
|
|
110
|
-
console.log(`[Watch] 监听目录: ${watchRoot}`);
|
|
111
|
-
console.log(`[Watch] 监听模式: ${filePattern.join(', ')}`);
|
|
112
160
|
}
|
|
113
161
|
});
|
|
114
162
|
|
|
@@ -147,7 +195,9 @@ export class FileWatcher {
|
|
|
147
195
|
try {
|
|
148
196
|
accessSync(fullPath);
|
|
149
197
|
const stat = statSync(fullPath);
|
|
150
|
-
if (stat.isDirectory() || stat.size > FILE_WATCHER.MAX_FILE_SIZE_BYTES)
|
|
198
|
+
if (stat.isDirectory() || stat.size > FILE_WATCHER.MAX_FILE_SIZE_BYTES) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
151
201
|
} catch {
|
|
152
202
|
return;
|
|
153
203
|
}
|
|
@@ -164,13 +214,11 @@ export class FileWatcher {
|
|
|
164
214
|
const verdict = saveEventFilter.shouldProcess(fullPath, data);
|
|
165
215
|
if (!verdict.process) {
|
|
166
216
|
if (process.env.ASD_DEBUG === '1') {
|
|
167
|
-
console.log(`[Watch] 保存事件已过滤 (${verdict.reason}): ${relativePath}`);
|
|
168
217
|
}
|
|
169
218
|
return;
|
|
170
219
|
}
|
|
171
220
|
|
|
172
221
|
if (process.env.ASD_DEBUG === '1') {
|
|
173
|
-
console.log(`[Watch] 读取文件内容成功,检查指令...`);
|
|
174
222
|
}
|
|
175
223
|
|
|
176
224
|
const filename = basename(fullPath);
|
|
@@ -184,13 +232,6 @@ export class FileWatcher {
|
|
|
184
232
|
const triggers = detectTriggers(data, filename);
|
|
185
233
|
|
|
186
234
|
if (process.env.ASD_DEBUG === '1') {
|
|
187
|
-
console.log(`[Watch] 指令检测结果:`, {
|
|
188
|
-
createLine: !!triggers.createLine,
|
|
189
|
-
guardLine: !!triggers.guardLine,
|
|
190
|
-
searchLine: !!triggers.searchLine,
|
|
191
|
-
alinkLine: !!triggers.alinkLine,
|
|
192
|
-
headerLine: !!triggers.headerLine,
|
|
193
|
-
});
|
|
194
235
|
}
|
|
195
236
|
|
|
196
237
|
// // as:c — 创建候选
|
|
@@ -212,7 +253,7 @@ export class FileWatcher {
|
|
|
212
253
|
if (triggers.alinkLine) {
|
|
213
254
|
clearTimeout(this._timeoutLink);
|
|
214
255
|
this._timeoutLink = setTimeout(() => {
|
|
215
|
-
handleAlink(triggers.alinkLine).catch(err => {
|
|
256
|
+
handleAlink(triggers.alinkLine).catch((err) => {
|
|
216
257
|
console.warn(`[Watcher] alink handler failed: ${err.message}`);
|
|
217
258
|
});
|
|
218
259
|
}, DEBOUNCE_DELAY);
|
|
@@ -229,7 +270,13 @@ export class FileWatcher {
|
|
|
229
270
|
if (isMatch) {
|
|
230
271
|
clearTimeout(this._timeoutHead);
|
|
231
272
|
this._timeoutHead = setTimeout(() => {
|
|
232
|
-
handleHeader(
|
|
273
|
+
handleHeader(
|
|
274
|
+
this,
|
|
275
|
+
fullPath,
|
|
276
|
+
triggers.headerLine,
|
|
277
|
+
triggers.importArray,
|
|
278
|
+
triggers.isSwift
|
|
279
|
+
).catch((err) => {
|
|
233
280
|
console.warn(`[Watcher] header handler failed: ${err.message}`);
|
|
234
281
|
});
|
|
235
282
|
}, DEBOUNCE_DELAY);
|
|
@@ -244,11 +291,13 @@ export class FileWatcher {
|
|
|
244
291
|
*/
|
|
245
292
|
async _appendCandidates(items, source) {
|
|
246
293
|
// 过滤空 title / 空 code 的无效条目
|
|
247
|
-
const validItems = items.filter(item => {
|
|
294
|
+
const validItems = items.filter((item) => {
|
|
248
295
|
const title = (item.title || '').trim();
|
|
249
296
|
const code = (item.code || '').trim();
|
|
250
297
|
if (!title || !code) {
|
|
251
|
-
console.warn(
|
|
298
|
+
console.warn(
|
|
299
|
+
`[Watcher] 跳过无效候选: title=${JSON.stringify(title)}, code length=${code.length}`
|
|
300
|
+
);
|
|
252
301
|
return false;
|
|
253
302
|
}
|
|
254
303
|
return true;
|
|
@@ -265,20 +314,23 @@ export class FileWatcher {
|
|
|
265
314
|
const knowledgeService = container.get('knowledgeService');
|
|
266
315
|
const context = { userId: 'filewatcher' };
|
|
267
316
|
for (const item of validItems) {
|
|
268
|
-
await knowledgeService.create(
|
|
269
|
-
|
|
270
|
-
|
|
317
|
+
await knowledgeService.create(
|
|
318
|
+
{
|
|
319
|
+
content: {
|
|
320
|
+
pattern: item.code || '',
|
|
321
|
+
},
|
|
322
|
+
language: item.language || 'objc',
|
|
323
|
+
category: item.category || 'Utility',
|
|
324
|
+
source: source || 'watch',
|
|
325
|
+
title: item.title,
|
|
326
|
+
description: item.summary || item.description || '',
|
|
327
|
+
moduleName: item.moduleName || 'watch-create',
|
|
328
|
+
trigger: item.trigger || '',
|
|
329
|
+
headers: item.headers || [],
|
|
330
|
+
tags: item.tags || [],
|
|
271
331
|
},
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
source: source || 'watch',
|
|
275
|
-
title: item.title,
|
|
276
|
-
description: item.summary || item.description || '',
|
|
277
|
-
moduleName: item.moduleName || 'watch-create',
|
|
278
|
-
trigger: item.trigger || '',
|
|
279
|
-
headers: item.headers || [],
|
|
280
|
-
tags: item.tags || [],
|
|
281
|
-
}, context);
|
|
332
|
+
context
|
|
333
|
+
);
|
|
282
334
|
}
|
|
283
335
|
return;
|
|
284
336
|
} catch (err) {
|
|
@@ -305,7 +357,9 @@ export class FileWatcher {
|
|
|
305
357
|
headers: item.headers || [],
|
|
306
358
|
}),
|
|
307
359
|
});
|
|
308
|
-
if (!resp.ok)
|
|
360
|
+
if (!resp.ok) {
|
|
361
|
+
throw new Error(`HTTP ${resp.status}`);
|
|
362
|
+
}
|
|
309
363
|
}
|
|
310
364
|
return;
|
|
311
365
|
} catch (err) {
|
|
@@ -328,7 +382,7 @@ export class FileWatcher {
|
|
|
328
382
|
relativePath,
|
|
329
383
|
text
|
|
330
384
|
);
|
|
331
|
-
if (resolved
|
|
385
|
+
if (resolved?.headers && resolved.headers.length > 0) {
|
|
332
386
|
item.headers = resolved.headers;
|
|
333
387
|
item.headerPaths = resolved.headerPaths;
|
|
334
388
|
item.moduleName = resolved.moduleName;
|
|
@@ -347,9 +401,7 @@ export class FileWatcher {
|
|
|
347
401
|
const url = `${base}${path}`;
|
|
348
402
|
import('../../infrastructure/external/OpenBrowser.js')
|
|
349
403
|
.then(({ openBrowserReuseTab }) => openBrowserReuseTab(url, base))
|
|
350
|
-
.catch(() => {
|
|
351
|
-
console.log(`💡 请手动访问: ${url}`);
|
|
352
|
-
});
|
|
404
|
+
.catch(() => {});
|
|
353
405
|
}
|
|
354
406
|
|
|
355
407
|
/**
|
|
@@ -357,8 +409,8 @@ export class FileWatcher {
|
|
|
357
409
|
*/
|
|
358
410
|
_notify(msg) {
|
|
359
411
|
import('../../infrastructure/external/NativeUi.js')
|
|
360
|
-
.then(NU => NU.notify(msg))
|
|
361
|
-
.catch(() =>
|
|
412
|
+
.then((NU) => NU.notify(msg))
|
|
413
|
+
.catch(() => {});
|
|
362
414
|
}
|
|
363
415
|
|
|
364
416
|
/**
|
|
@@ -372,10 +424,14 @@ export class FileWatcher {
|
|
|
372
424
|
key,
|
|
373
425
|
setTimeout(() => {
|
|
374
426
|
this._debounceTimers.delete(key);
|
|
375
|
-
Promise.resolve()
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
427
|
+
Promise.resolve()
|
|
428
|
+
.then(() => fn())
|
|
429
|
+
.catch((err) => {
|
|
430
|
+
console.error('[Watch] 处理文件失败:', err.message);
|
|
431
|
+
if (process.env.ASD_DEBUG === '1') {
|
|
432
|
+
console.error(err.stack);
|
|
433
|
+
}
|
|
434
|
+
});
|
|
379
435
|
}, DEBOUNCE_DELAY)
|
|
380
436
|
);
|
|
381
437
|
}
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
export class TriggerResolver {
|
|
7
|
-
|
|
8
7
|
/**
|
|
9
8
|
* 规范化触发器
|
|
10
9
|
* @param {object|string} trigger
|
|
@@ -57,9 +56,12 @@ export class TriggerResolver {
|
|
|
57
56
|
|
|
58
57
|
#mapDirectiveType(name) {
|
|
59
58
|
const map = {
|
|
60
|
-
search: 'search',
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
search: 'search',
|
|
60
|
+
s: 'search',
|
|
61
|
+
create: 'create',
|
|
62
|
+
c: 'create',
|
|
63
|
+
audit: 'audit',
|
|
64
|
+
a: 'audit',
|
|
63
65
|
include: 'injection',
|
|
64
66
|
import: 'injection',
|
|
65
67
|
alink: 'alink',
|
|
@@ -16,7 +16,10 @@ export async function handleAlink(alinkLine) {
|
|
|
16
16
|
const alinkMark = 'alink';
|
|
17
17
|
|
|
18
18
|
if (alinkLine.includes(TRIGGER_SYMBOL)) {
|
|
19
|
-
const parts = alinkLine
|
|
19
|
+
const parts = alinkLine
|
|
20
|
+
.split(TRIGGER_SYMBOL)
|
|
21
|
+
.map((p) => p.trim())
|
|
22
|
+
.filter(Boolean);
|
|
20
23
|
if (parts.length >= 2 && parts[parts.length - 1] === alinkMark) {
|
|
21
24
|
completionKey = parts[parts.length - 2];
|
|
22
25
|
}
|
|
@@ -32,10 +35,14 @@ export async function handleAlink(alinkLine) {
|
|
|
32
35
|
if (db) {
|
|
33
36
|
const rawDb = typeof db.getDb === 'function' ? db.getDb() : db;
|
|
34
37
|
try {
|
|
35
|
-
const row = rawDb
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
const row = rawDb
|
|
39
|
+
.prepare(
|
|
40
|
+
"SELECT id FROM knowledge_entries WHERE trigger = ? AND lifecycle = 'active' LIMIT 1"
|
|
41
|
+
)
|
|
42
|
+
.get(completionKey);
|
|
43
|
+
if (row) {
|
|
44
|
+
recipeId = row.id;
|
|
45
|
+
}
|
|
39
46
|
} catch {
|
|
40
47
|
// DB 查询失败时回退到搜索
|
|
41
48
|
}
|
|
@@ -43,12 +50,18 @@ export async function handleAlink(alinkLine) {
|
|
|
43
50
|
// 若精确匹配失败,尝试模糊搜索
|
|
44
51
|
if (!recipeId) {
|
|
45
52
|
try {
|
|
46
|
-
const escaped = completionKey.replace(/[%_\\]/g, ch => `\\${ch}`);
|
|
47
|
-
const row = rawDb
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
53
|
+
const escaped = completionKey.replace(/[%_\\]/g, (ch) => `\\${ch}`);
|
|
54
|
+
const row = rawDb
|
|
55
|
+
.prepare(
|
|
56
|
+
"SELECT id FROM knowledge_entries WHERE (trigger LIKE ? ESCAPE '\\' OR title LIKE ? ESCAPE '\\') AND lifecycle = 'active' LIMIT 1"
|
|
57
|
+
)
|
|
58
|
+
.get(`%${escaped}%`, `%${escaped}%`);
|
|
59
|
+
if (row) {
|
|
60
|
+
recipeId = row.id;
|
|
61
|
+
}
|
|
62
|
+
} catch {
|
|
63
|
+
/* silent */
|
|
64
|
+
}
|
|
52
65
|
}
|
|
53
66
|
}
|
|
54
67
|
|
|
@@ -61,7 +74,6 @@ export async function handleAlink(alinkLine) {
|
|
|
61
74
|
|
|
62
75
|
const open = (await import('open')).default;
|
|
63
76
|
await open(url);
|
|
64
|
-
console.log(`[alink] completionKey=${completionKey} → ${url}`);
|
|
65
77
|
} catch (err) {
|
|
66
78
|
console.warn(`[alink] Failed to open link: ${err.message}`);
|
|
67
79
|
}
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { readFileSync, writeFileSync } from 'node:fs';
|
|
7
|
+
import { LanguageService } from '../../../shared/LanguageService.js';
|
|
7
8
|
import { REGEX } from '../DirectiveDetector.js';
|
|
8
|
-
import { saveEventFilter } from '
|
|
9
|
+
import { saveEventFilter } from '../../../platform/ios/xcode/SaveEventFilter.js';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* 处理 // as:c 指令
|
|
@@ -51,18 +52,12 @@ export async function handleCreate(watcher, fullPath, relativePath, createOption
|
|
|
51
52
|
// 3. 无 -c 选项:打开 Dashboard
|
|
52
53
|
if (createOption !== 'c') {
|
|
53
54
|
const autoScan = createOption === 'f' ? '&autoScan=1' : '';
|
|
54
|
-
console.log(
|
|
55
|
-
createOption === 'f'
|
|
56
|
-
? '[as:create -f] 已打开 Dashboard,自动执行 Scan File'
|
|
57
|
-
: '[as:create] 已打开 Dashboard,请选择 Scan File 或 Use Copied Code'
|
|
58
|
-
);
|
|
59
55
|
watcher._openDashboard(`/?action=create&path=${encodeURIComponent(relativePath)}${autoScan}`);
|
|
60
56
|
return;
|
|
61
57
|
}
|
|
62
58
|
|
|
63
59
|
// 4. -c 模式:剪贴板为空则打开 Dashboard
|
|
64
60
|
if (textToExtract.length === 0) {
|
|
65
|
-
console.log('[as:create -c] 剪贴板为空,已打开 Dashboard');
|
|
66
61
|
watcher._openDashboard(`/?action=create&path=${encodeURIComponent(relativePath)}`);
|
|
67
62
|
return;
|
|
68
63
|
}
|
|
@@ -72,7 +67,9 @@ export async function handleCreate(watcher, fullPath, relativePath, createOption
|
|
|
72
67
|
await silentCreateCandidate(watcher, textToExtract, relativePath);
|
|
73
68
|
} catch (e) {
|
|
74
69
|
console.warn('[Watcher] 静默创建候选失败,回退到打开浏览器:', e.message);
|
|
75
|
-
watcher._openDashboard(
|
|
70
|
+
watcher._openDashboard(
|
|
71
|
+
`/?action=create&path=${encodeURIComponent(relativePath)}&source=clipboard`
|
|
72
|
+
);
|
|
76
73
|
}
|
|
77
74
|
}
|
|
78
75
|
|
|
@@ -89,7 +86,7 @@ async function silentCreateCandidate(watcher, text, relativePath) {
|
|
|
89
86
|
summary: r.summary || r.description || '',
|
|
90
87
|
trigger: r.trigger,
|
|
91
88
|
category: r.category || 'Utility',
|
|
92
|
-
language: r.language
|
|
89
|
+
language: r.language || 'unknown',
|
|
93
90
|
code: r.code,
|
|
94
91
|
usageGuide: r.usageGuide || '',
|
|
95
92
|
headers: r.headers || [],
|
|
@@ -97,7 +94,7 @@ async function silentCreateCandidate(watcher, text, relativePath) {
|
|
|
97
94
|
|
|
98
95
|
// 先尝试批量解析(仅对 Recipe Markdown 格式有效)
|
|
99
96
|
const allRecipes = parser.parseAll(text);
|
|
100
|
-
const validRecipes = allRecipes.filter(r => r.title
|
|
97
|
+
const validRecipes = allRecipes.filter((r) => r.title?.trim());
|
|
101
98
|
if (validRecipes.length > 0) {
|
|
102
99
|
const items = normalize(validRecipes);
|
|
103
100
|
await watcher._resolveHeadersIfNeeded(items[0], relativePath, text);
|
|
@@ -106,7 +103,6 @@ async function silentCreateCandidate(watcher, text, relativePath) {
|
|
|
106
103
|
validRecipes.length === 1
|
|
107
104
|
? `已创建候选「${validRecipes[0].title}」,请在 Dashboard Candidates 页审核`
|
|
108
105
|
: `已创建 ${validRecipes.length} 条候选,请在 Dashboard Candidates 页审核`;
|
|
109
|
-
console.log(`✅ [as:create] ${msg}`);
|
|
110
106
|
watcher._notify(msg);
|
|
111
107
|
return;
|
|
112
108
|
}
|
|
@@ -114,11 +110,10 @@ async function silentCreateCandidate(watcher, text, relativePath) {
|
|
|
114
110
|
// 尝试单条解析
|
|
115
111
|
if (parser.isCompleteRecipe(text)) {
|
|
116
112
|
const one = parser.parse(text);
|
|
117
|
-
if (one
|
|
113
|
+
if (one?.title?.trim()) {
|
|
118
114
|
const item = normalize([one])[0];
|
|
119
115
|
await watcher._resolveHeadersIfNeeded(item, relativePath, text);
|
|
120
116
|
await watcher._appendCandidates([item], 'watch-create');
|
|
121
|
-
console.log(`✅ [as:create] 已静默创建候选「${one.title}」,请在 Dashboard Candidates 页审核`);
|
|
122
117
|
watcher._notify(`已创建候选「${one.title}」,请在 Candidates 页审核`);
|
|
123
118
|
return;
|
|
124
119
|
}
|
|
@@ -126,10 +121,11 @@ async function silentCreateCandidate(watcher, text, relativePath) {
|
|
|
126
121
|
|
|
127
122
|
// -c 模式:剪贴板内容整体作为一条候选(不拆分)
|
|
128
123
|
// 先用 AI 生成标题和摘要,code 保持剪贴板原文
|
|
129
|
-
const lang = relativePath
|
|
124
|
+
const lang = relativePath ? (LanguageService.inferLang(relativePath) || 'unknown') : 'unknown';
|
|
125
|
+
const ext = LanguageService.extForLang(lang) || '.txt';
|
|
130
126
|
const fileName = relativePath
|
|
131
127
|
? relativePath.split('/').pop()
|
|
132
|
-
: `clipboard
|
|
128
|
+
: `clipboard${ext}`;
|
|
133
129
|
|
|
134
130
|
let title = fileName.replace(/\.\w+$/, '') || 'Clipboard Snippet';
|
|
135
131
|
let summary = '';
|
|
@@ -154,7 +150,9 @@ async function silentCreateCandidate(watcher, text, relativePath) {
|
|
|
154
150
|
tags = aiResult.tags || [];
|
|
155
151
|
trigger = aiResult.trigger || '';
|
|
156
152
|
}
|
|
157
|
-
} catch {
|
|
153
|
+
} catch {
|
|
154
|
+
/* AI 不可用,使用默认值 */
|
|
155
|
+
}
|
|
158
156
|
|
|
159
157
|
const item = {
|
|
160
158
|
title,
|
|
@@ -163,7 +161,7 @@ async function silentCreateCandidate(watcher, text, relativePath) {
|
|
|
163
161
|
trigger,
|
|
164
162
|
category,
|
|
165
163
|
language: lang,
|
|
166
|
-
code: text,
|
|
164
|
+
code: text, // 剪贴板原文整体
|
|
167
165
|
usageGuide,
|
|
168
166
|
headers,
|
|
169
167
|
tags,
|
|
@@ -171,7 +169,6 @@ async function silentCreateCandidate(watcher, text, relativePath) {
|
|
|
171
169
|
|
|
172
170
|
await watcher._resolveHeadersIfNeeded(item, relativePath, text);
|
|
173
171
|
await watcher._appendCandidates([item], 'watch-create');
|
|
174
|
-
console.log(`✅ [as:create -c] 已创建候选「${title}」,请在 Candidates 页审核`);
|
|
175
172
|
watcher._notify(`已创建候选「${title}」,请在 Candidates 页审核`);
|
|
176
173
|
}
|
|
177
174
|
|
|
@@ -179,7 +176,9 @@ async function silentCreateCandidate(watcher, text, relativePath) {
|
|
|
179
176
|
* 查找 // as:c 的行号 (1-based)
|
|
180
177
|
*/
|
|
181
178
|
export function findCreateLineNumber(content) {
|
|
182
|
-
if (!content)
|
|
179
|
+
if (!content) {
|
|
180
|
+
return -1;
|
|
181
|
+
}
|
|
183
182
|
const lines = content.split(/\r?\n/);
|
|
184
183
|
for (let i = 0; i < lines.length; i++) {
|
|
185
184
|
const t = lines[i].trim();
|
|
@@ -191,5 +190,5 @@ export function findCreateLineNumber(content) {
|
|
|
191
190
|
}
|
|
192
191
|
|
|
193
192
|
function _sleep(ms) {
|
|
194
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
193
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
195
194
|
}
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* DraftHandler — 处理 _draft_*.md 文件保存
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import { LanguageService } from '../../../shared/LanguageService.js';
|
|
6
|
+
|
|
5
7
|
/**
|
|
6
8
|
* @param {import('../FileWatcher.js').FileWatcher} watcher
|
|
7
9
|
* @param {string} fullPath
|
|
@@ -9,7 +11,9 @@
|
|
|
9
11
|
* @param {string} content
|
|
10
12
|
*/
|
|
11
13
|
export async function handleDraft(watcher, fullPath, relativePath, content) {
|
|
12
|
-
if (!content || content.trim().length < 20)
|
|
14
|
+
if (!content || content.trim().length < 20) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
13
17
|
|
|
14
18
|
try {
|
|
15
19
|
const { RecipeParser } = await import('../../recipe/RecipeParser.js');
|
|
@@ -21,7 +25,7 @@ export async function handleDraft(watcher, fullPath, relativePath, content) {
|
|
|
21
25
|
summary: r.summary || r.description || '',
|
|
22
26
|
trigger: r.trigger,
|
|
23
27
|
category: r.category || 'Utility',
|
|
24
|
-
language: r.language
|
|
28
|
+
language: r.language || 'unknown',
|
|
25
29
|
code: r.code,
|
|
26
30
|
usageGuide: r.usageGuide || '',
|
|
27
31
|
headers: r.headers || [],
|
|
@@ -35,7 +39,6 @@ export async function handleDraft(watcher, fullPath, relativePath, content) {
|
|
|
35
39
|
allRecipes.length === 1
|
|
36
40
|
? `已创建候选「${allRecipes[0].title}」`
|
|
37
41
|
: `已创建 ${allRecipes.length} 条候选`;
|
|
38
|
-
console.log(`✅ [_draft] ${msg},请在 Dashboard Candidates 页审核`);
|
|
39
42
|
watcher._notify(msg);
|
|
40
43
|
return;
|
|
41
44
|
}
|
|
@@ -45,7 +48,6 @@ export async function handleDraft(watcher, fullPath, relativePath, content) {
|
|
|
45
48
|
if (one) {
|
|
46
49
|
const item = normalize([one])[0];
|
|
47
50
|
await watcher._appendCandidates([item], 'draft-file');
|
|
48
|
-
console.log(`✅ [_draft] 已创建候选「${one.title}」`);
|
|
49
51
|
watcher._notify(`已创建候选「${one.title}」`);
|
|
50
52
|
return;
|
|
51
53
|
}
|
|
@@ -56,14 +58,18 @@ export async function handleDraft(watcher, fullPath, relativePath, content) {
|
|
|
56
58
|
const { getServiceContainer } = await import('../../../injection/ServiceContainer.js');
|
|
57
59
|
const container = getServiceContainer();
|
|
58
60
|
const chatAgent = container.get('chatAgent');
|
|
59
|
-
const lang =
|
|
60
|
-
const result = await chatAgent.executeTool('summarize_code', {
|
|
61
|
+
const lang = LanguageService.inferLang(relativePath) || 'unknown';
|
|
62
|
+
const result = await chatAgent.executeTool('summarize_code', {
|
|
63
|
+
code: content,
|
|
64
|
+
language: lang,
|
|
65
|
+
});
|
|
61
66
|
if (result && !result.error && result.title && result.code) {
|
|
62
67
|
await watcher._appendCandidates([result], 'draft-file');
|
|
63
|
-
console.log(`✅ [_draft] 已创建候选「${result.title}」`);
|
|
64
68
|
watcher._notify(`已创建候选「${result.title}」`);
|
|
65
69
|
}
|
|
66
|
-
} catch {
|
|
70
|
+
} catch {
|
|
71
|
+
/* ChatAgent 不可用 */
|
|
72
|
+
}
|
|
67
73
|
} catch (e) {
|
|
68
74
|
console.warn('[Watcher] 草稿文件解析失败:', e.message);
|
|
69
75
|
}
|