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
|
@@ -37,7 +37,7 @@ export class BaseRepository {
|
|
|
37
37
|
if (!this.#columnWhitelist) {
|
|
38
38
|
try {
|
|
39
39
|
const cols = this.db.prepare(`PRAGMA table_info(${this.tableName})`).all();
|
|
40
|
-
this.#columnWhitelist = new Set(cols.map(c => c.name));
|
|
40
|
+
this.#columnWhitelist = new Set(cols.map((c) => c.name));
|
|
41
41
|
} catch {
|
|
42
42
|
this.#columnWhitelist = new Set();
|
|
43
43
|
}
|
|
@@ -63,7 +63,7 @@ export class BaseRepository {
|
|
|
63
63
|
SELECT * FROM ${this.tableName} WHERE id = ? LIMIT 1
|
|
64
64
|
`);
|
|
65
65
|
const row = stmt.get(id);
|
|
66
|
-
|
|
66
|
+
|
|
67
67
|
if (!row) {
|
|
68
68
|
return null;
|
|
69
69
|
}
|
|
@@ -141,11 +141,7 @@ export class BaseRepository {
|
|
|
141
141
|
// 获取分页数据
|
|
142
142
|
query += ' ORDER BY created_at DESC LIMIT ? OFFSET ?';
|
|
143
143
|
const dataStmt = this.db.prepare(query);
|
|
144
|
-
const data = dataStmt.all(
|
|
145
|
-
...params.slice(0, Object.keys(filters).length),
|
|
146
|
-
pageSize,
|
|
147
|
-
offset
|
|
148
|
-
);
|
|
144
|
+
const data = dataStmt.all(...params.slice(0, Object.keys(filters).length), pageSize, offset);
|
|
149
145
|
|
|
150
146
|
return {
|
|
151
147
|
data: data.map((row) => this._mapRowToEntity(row)),
|
|
@@ -171,8 +167,10 @@ export class BaseRepository {
|
|
|
171
167
|
try {
|
|
172
168
|
const updateKeys = Object.keys(updates);
|
|
173
169
|
const updateValues = Object.values(updates);
|
|
174
|
-
|
|
175
|
-
for (const key of updateKeys)
|
|
170
|
+
|
|
171
|
+
for (const key of updateKeys) {
|
|
172
|
+
this._assertSafeColumn(key);
|
|
173
|
+
}
|
|
176
174
|
const setClause = updateKeys.map((key) => `${key} = ?`).join(', ');
|
|
177
175
|
const query = `
|
|
178
176
|
UPDATE ${this.tableName}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { KnowledgeEntry, Lifecycle, inferKind } from '../../domain/knowledge/index.js';
|
|
1
|
+
import { inferKind, KnowledgeEntry } from '../../domain/knowledge/index.js';
|
|
3
2
|
import Logger from '../../infrastructure/logging/Logger.js';
|
|
4
3
|
import { safeJsonParse, safeJsonStringify, unixNow } from '../../shared/utils/common.js';
|
|
4
|
+
import { BaseRepository } from '../base/BaseRepository.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* KnowledgeRepositoryImpl — 统一知识实体仓储实现
|
|
@@ -52,7 +52,9 @@ export class KnowledgeRepositoryImpl extends BaseRepository {
|
|
|
52
52
|
async update(id, updates) {
|
|
53
53
|
try {
|
|
54
54
|
const existing = await this.findById(id);
|
|
55
|
-
if (!existing)
|
|
55
|
+
if (!existing) {
|
|
56
|
+
throw new Error(`Knowledge entry not found: ${id}`);
|
|
57
|
+
}
|
|
56
58
|
|
|
57
59
|
if (updates instanceof KnowledgeEntry) {
|
|
58
60
|
const row = this._entityToRow(updates);
|
|
@@ -60,8 +62,11 @@ export class KnowledgeRepositoryImpl extends BaseRepository {
|
|
|
60
62
|
delete row.createdAt;
|
|
61
63
|
row.updatedAt = unixNow();
|
|
62
64
|
|
|
63
|
-
const setClauses = Object.keys(row)
|
|
64
|
-
|
|
65
|
+
const setClauses = Object.keys(row)
|
|
66
|
+
.map((k) => `${k} = ?`)
|
|
67
|
+
.join(', ');
|
|
68
|
+
this.db
|
|
69
|
+
.prepare(`UPDATE knowledge_entries SET ${setClauses} WHERE id = ?`)
|
|
65
70
|
.run(...Object.values(row), id);
|
|
66
71
|
return this.findById(id);
|
|
67
72
|
}
|
|
@@ -76,8 +81,11 @@ export class KnowledgeRepositoryImpl extends BaseRepository {
|
|
|
76
81
|
delete row.id;
|
|
77
82
|
delete row.createdAt;
|
|
78
83
|
|
|
79
|
-
const setClauses = Object.keys(row)
|
|
80
|
-
|
|
84
|
+
const setClauses = Object.keys(row)
|
|
85
|
+
.map((k) => `${k} = ?`)
|
|
86
|
+
.join(', ');
|
|
87
|
+
this.db
|
|
88
|
+
.prepare(`UPDATE knowledge_entries SET ${setClauses} WHERE id = ?`)
|
|
81
89
|
.run(...Object.values(row), id);
|
|
82
90
|
return this.findById(id);
|
|
83
91
|
} catch (error) {
|
|
@@ -125,7 +133,9 @@ export class KnowledgeRepositoryImpl extends BaseRepository {
|
|
|
125
133
|
}
|
|
126
134
|
|
|
127
135
|
for (const [key, value] of Object.entries(normalFilters)) {
|
|
128
|
-
if (value == null)
|
|
136
|
+
if (value == null) {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
129
139
|
this._assertSafeColumn(key);
|
|
130
140
|
conditions.push(`${key} = ?`);
|
|
131
141
|
params.push(value);
|
|
@@ -133,14 +143,16 @@ export class KnowledgeRepositoryImpl extends BaseRepository {
|
|
|
133
143
|
|
|
134
144
|
if (_tagLike) {
|
|
135
145
|
conditions.push(`tags LIKE ?`);
|
|
136
|
-
const escaped = _tagLike.replace(/[%_\\]/g, ch => `\\${ch}`);
|
|
146
|
+
const escaped = _tagLike.replace(/[%_\\]/g, (ch) => `\\${ch}`);
|
|
137
147
|
params.push(`%"${escaped}"%`);
|
|
138
148
|
}
|
|
139
149
|
|
|
140
150
|
if (_search) {
|
|
141
|
-
const escaped = _search.replace(/[%_\\]/g, ch => `\\${ch}`);
|
|
151
|
+
const escaped = _search.replace(/[%_\\]/g, (ch) => `\\${ch}`);
|
|
142
152
|
const like = `%${escaped}%`;
|
|
143
|
-
conditions.push(
|
|
153
|
+
conditions.push(
|
|
154
|
+
`(title LIKE ? ESCAPE '\\' OR description LIKE ? ESCAPE '\\' OR trigger LIKE ? ESCAPE '\\' OR content LIKE ? ESCAPE '\\' OR tags LIKE ? ESCAPE '\\')`
|
|
155
|
+
);
|
|
144
156
|
params.push(like, like, like, like, like);
|
|
145
157
|
}
|
|
146
158
|
|
|
@@ -149,12 +161,15 @@ export class KnowledgeRepositoryImpl extends BaseRepository {
|
|
|
149
161
|
this._assertSafeColumn(orderBy);
|
|
150
162
|
const orderClause = ` ORDER BY ${orderBy} ${order === 'ASC' ? 'ASC' : 'DESC'}`;
|
|
151
163
|
|
|
152
|
-
const total = this.db
|
|
153
|
-
|
|
164
|
+
const total = this.db
|
|
165
|
+
.prepare(`SELECT COUNT(*) as count FROM knowledge_entries${where}`)
|
|
166
|
+
.get(...params).count;
|
|
167
|
+
const data = this.db
|
|
168
|
+
.prepare(`SELECT * FROM knowledge_entries${where}${orderClause} LIMIT ? OFFSET ?`)
|
|
154
169
|
.all(...params, pageSize, offset);
|
|
155
170
|
|
|
156
171
|
return {
|
|
157
|
-
data: data.map(row => this._rowToEntity(row)),
|
|
172
|
+
data: data.map((row) => this._rowToEntity(row)),
|
|
158
173
|
pagination: { page, pageSize, total, pages: Math.ceil(total / pageSize) },
|
|
159
174
|
};
|
|
160
175
|
}
|
|
@@ -172,7 +187,9 @@ export class KnowledgeRepositoryImpl extends BaseRepository {
|
|
|
172
187
|
async findByKind(kind, options = {}) {
|
|
173
188
|
const { lifecycle, ...pagination } = options;
|
|
174
189
|
const filters = { kind };
|
|
175
|
-
if (lifecycle)
|
|
190
|
+
if (lifecycle) {
|
|
191
|
+
filters.lifecycle = lifecycle;
|
|
192
|
+
}
|
|
176
193
|
return this.findWithPagination(filters, pagination);
|
|
177
194
|
}
|
|
178
195
|
|
|
@@ -182,11 +199,13 @@ export class KnowledgeRepositoryImpl extends BaseRepository {
|
|
|
182
199
|
*/
|
|
183
200
|
async findActiveRules() {
|
|
184
201
|
try {
|
|
185
|
-
const rows = this.db
|
|
202
|
+
const rows = this.db
|
|
203
|
+
.prepare(`
|
|
186
204
|
SELECT * FROM knowledge_entries
|
|
187
205
|
WHERE kind = 'rule' AND lifecycle = 'active'
|
|
188
|
-
`)
|
|
189
|
-
|
|
206
|
+
`)
|
|
207
|
+
.all();
|
|
208
|
+
return rows.map((row) => this._rowToEntity(row));
|
|
190
209
|
} catch (error) {
|
|
191
210
|
this.logger.error('Error finding active rules', { error: error.message });
|
|
192
211
|
throw error;
|
|
@@ -219,7 +238,8 @@ export class KnowledgeRepositoryImpl extends BaseRepository {
|
|
|
219
238
|
*/
|
|
220
239
|
async getStats() {
|
|
221
240
|
try {
|
|
222
|
-
return this.db
|
|
241
|
+
return this.db
|
|
242
|
+
.prepare(`
|
|
223
243
|
SELECT
|
|
224
244
|
COUNT(*) as total,
|
|
225
245
|
SUM(CASE WHEN lifecycle = 'pending' THEN 1 ELSE 0 END) as pending,
|
|
@@ -229,7 +249,8 @@ export class KnowledgeRepositoryImpl extends BaseRepository {
|
|
|
229
249
|
SUM(CASE WHEN kind = 'pattern' THEN 1 ELSE 0 END) as patterns,
|
|
230
250
|
SUM(CASE WHEN kind = 'fact' THEN 1 ELSE 0 END) as facts
|
|
231
251
|
FROM knowledge_entries
|
|
232
|
-
`)
|
|
252
|
+
`)
|
|
253
|
+
.get();
|
|
233
254
|
} catch (error) {
|
|
234
255
|
this.logger.error('Error getting knowledge stats', { error: error.message });
|
|
235
256
|
throw error;
|
|
@@ -244,25 +265,27 @@ export class KnowledgeRepositoryImpl extends BaseRepository {
|
|
|
244
265
|
* @returns {KnowledgeEntry}
|
|
245
266
|
*/
|
|
246
267
|
_rowToEntity(row) {
|
|
247
|
-
if (!row)
|
|
268
|
+
if (!row) {
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
248
271
|
|
|
249
272
|
return new KnowledgeEntry({
|
|
250
273
|
...row,
|
|
251
274
|
// JSON 列需要 parse
|
|
252
275
|
lifecycleHistory: safeJsonParse(row.lifecycleHistory, []),
|
|
253
|
-
tags:
|
|
254
|
-
content:
|
|
255
|
-
relations:
|
|
256
|
-
constraints:
|
|
257
|
-
reasoning:
|
|
258
|
-
quality:
|
|
259
|
-
stats:
|
|
260
|
-
headers:
|
|
261
|
-
headerPaths:
|
|
262
|
-
agentNotes:
|
|
276
|
+
tags: safeJsonParse(row.tags, []),
|
|
277
|
+
content: safeJsonParse(row.content, {}),
|
|
278
|
+
relations: safeJsonParse(row.relations, {}),
|
|
279
|
+
constraints: safeJsonParse(row.constraints, {}),
|
|
280
|
+
reasoning: safeJsonParse(row.reasoning, {}),
|
|
281
|
+
quality: safeJsonParse(row.quality, {}),
|
|
282
|
+
stats: safeJsonParse(row.stats, {}),
|
|
283
|
+
headers: safeJsonParse(row.headers, []),
|
|
284
|
+
headerPaths: safeJsonParse(row.headerPaths, []),
|
|
285
|
+
agentNotes: safeJsonParse(row.agentNotes, null),
|
|
263
286
|
// SQLite INTEGER → boolean
|
|
264
|
-
autoApprovable:
|
|
265
|
-
includeHeaders:
|
|
287
|
+
autoApprovable: !!row.autoApprovable,
|
|
288
|
+
includeHeaders: !!row.includeHeaders,
|
|
266
289
|
});
|
|
267
290
|
}
|
|
268
291
|
|
|
@@ -274,49 +297,49 @@ export class KnowledgeRepositoryImpl extends BaseRepository {
|
|
|
274
297
|
_entityToRow(e) {
|
|
275
298
|
const now = unixNow();
|
|
276
299
|
return {
|
|
277
|
-
id:
|
|
278
|
-
title:
|
|
279
|
-
description:
|
|
280
|
-
lifecycle:
|
|
281
|
-
lifecycleHistory:
|
|
282
|
-
autoApprovable:
|
|
283
|
-
language:
|
|
284
|
-
category:
|
|
285
|
-
kind:
|
|
286
|
-
knowledgeType:
|
|
287
|
-
complexity:
|
|
288
|
-
scope:
|
|
289
|
-
difficulty:
|
|
290
|
-
tags:
|
|
291
|
-
trigger:
|
|
292
|
-
topicHint:
|
|
293
|
-
whenClause:
|
|
294
|
-
doClause:
|
|
295
|
-
dontClause:
|
|
296
|
-
coreCode:
|
|
297
|
-
content:
|
|
298
|
-
relations:
|
|
299
|
-
constraints:
|
|
300
|
-
reasoning:
|
|
301
|
-
quality:
|
|
302
|
-
stats:
|
|
303
|
-
headers:
|
|
304
|
-
headerPaths:
|
|
305
|
-
moduleName:
|
|
306
|
-
includeHeaders:
|
|
307
|
-
agentNotes:
|
|
308
|
-
aiInsight:
|
|
309
|
-
reviewedBy:
|
|
310
|
-
reviewedAt:
|
|
311
|
-
rejectionReason:
|
|
312
|
-
source:
|
|
313
|
-
sourceFile:
|
|
300
|
+
id: e.id,
|
|
301
|
+
title: e.title,
|
|
302
|
+
description: e.description || '',
|
|
303
|
+
lifecycle: e.lifecycle,
|
|
304
|
+
lifecycleHistory: safeJsonStringify(e.lifecycleHistory || [], '[]'),
|
|
305
|
+
autoApprovable: e.autoApprovable ? 1 : 0,
|
|
306
|
+
language: e.language,
|
|
307
|
+
category: e.category,
|
|
308
|
+
kind: e.kind || inferKind(e.knowledgeType),
|
|
309
|
+
knowledgeType: e.knowledgeType || 'code-pattern',
|
|
310
|
+
complexity: e.complexity || 'intermediate',
|
|
311
|
+
scope: e.scope || null,
|
|
312
|
+
difficulty: e.difficulty || null,
|
|
313
|
+
tags: safeJsonStringify(e.tags || [], '[]'),
|
|
314
|
+
trigger: e.trigger || '',
|
|
315
|
+
topicHint: e.topicHint || '',
|
|
316
|
+
whenClause: e.whenClause || '',
|
|
317
|
+
doClause: e.doClause || '',
|
|
318
|
+
dontClause: e.dontClause || '',
|
|
319
|
+
coreCode: e.coreCode || '',
|
|
320
|
+
content: safeJsonStringify(e.content || {}),
|
|
321
|
+
relations: safeJsonStringify(e.relations || {}),
|
|
322
|
+
constraints: safeJsonStringify(e.constraints || {}),
|
|
323
|
+
reasoning: safeJsonStringify(e.reasoning || {}),
|
|
324
|
+
quality: safeJsonStringify(e.quality || {}),
|
|
325
|
+
stats: safeJsonStringify(e.stats || {}),
|
|
326
|
+
headers: safeJsonStringify(e.headers || [], '[]'),
|
|
327
|
+
headerPaths: safeJsonStringify(e.headerPaths || [], '[]'),
|
|
328
|
+
moduleName: e.moduleName || null,
|
|
329
|
+
includeHeaders: e.includeHeaders ? 1 : 0,
|
|
330
|
+
agentNotes: e.agentNotes ? safeJsonStringify(e.agentNotes) : null,
|
|
331
|
+
aiInsight: e.aiInsight || null,
|
|
332
|
+
reviewedBy: e.reviewedBy || null,
|
|
333
|
+
reviewedAt: e.reviewedAt || null,
|
|
334
|
+
rejectionReason: e.rejectionReason || null,
|
|
335
|
+
source: e.source || 'manual',
|
|
336
|
+
sourceFile: e.sourceFile || null,
|
|
314
337
|
sourceCandidateId: e.sourceCandidateId || null,
|
|
315
|
-
createdBy:
|
|
316
|
-
createdAt:
|
|
317
|
-
updatedAt:
|
|
318
|
-
publishedAt:
|
|
319
|
-
publishedBy:
|
|
338
|
+
createdBy: e.createdBy || 'system',
|
|
339
|
+
createdAt: e.createdAt || now,
|
|
340
|
+
updatedAt: e.updatedAt || now,
|
|
341
|
+
publishedAt: e.publishedAt || null,
|
|
342
|
+
publishedBy: e.publishedBy || null,
|
|
320
343
|
};
|
|
321
344
|
}
|
|
322
345
|
|
|
@@ -81,7 +81,9 @@ export class TokenUsageStore {
|
|
|
81
81
|
try {
|
|
82
82
|
const now = Date.now();
|
|
83
83
|
const total = (record.inputTokens || 0) + (record.outputTokens || 0);
|
|
84
|
-
if (total === 0)
|
|
84
|
+
if (total === 0) {
|
|
85
|
+
return; // 跳过无消耗的调用
|
|
86
|
+
}
|
|
85
87
|
|
|
86
88
|
this.#insertStmt.run(
|
|
87
89
|
now,
|
|
@@ -94,7 +96,7 @@ export class TokenUsageStore {
|
|
|
94
96
|
total,
|
|
95
97
|
record.durationMs || null,
|
|
96
98
|
record.toolCalls || 0,
|
|
97
|
-
record.sessionId || null
|
|
99
|
+
record.sessionId || null
|
|
98
100
|
);
|
|
99
101
|
|
|
100
102
|
// 写入后使缓存失效
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import Logger from '../../infrastructure/logging/Logger.js';
|
|
7
|
-
import { TriggerResolver } from './TriggerResolver.js';
|
|
8
|
-
import { ContextCollector } from './ContextCollector.js';
|
|
9
7
|
import { ActionPipeline } from './ActionPipeline.js';
|
|
8
|
+
import { ContextCollector } from './ContextCollector.js';
|
|
9
|
+
import { TriggerResolver } from './TriggerResolver.js';
|
|
10
10
|
|
|
11
11
|
export class AutomationOrchestrator {
|
|
12
12
|
#triggerResolver;
|
|
@@ -33,7 +33,9 @@ export class AutomationOrchestrator {
|
|
|
33
33
|
const resolvedTrigger = this.#triggerResolver.resolve(trigger);
|
|
34
34
|
const collectedContext = this.#contextCollector.collect(context);
|
|
35
35
|
|
|
36
|
-
this.#logger.info(
|
|
36
|
+
this.#logger.info(
|
|
37
|
+
`[AutomationOrchestrator] run type=${resolvedTrigger.type} name=${resolvedTrigger.name || ''}`
|
|
38
|
+
);
|
|
37
39
|
|
|
38
40
|
const pipelineResult = await this.#pipeline.execute(resolvedTrigger, collectedContext);
|
|
39
41
|
|
|
@@ -44,7 +46,9 @@ export class AutomationOrchestrator {
|
|
|
44
46
|
timestamp: new Date().toISOString(),
|
|
45
47
|
};
|
|
46
48
|
this.#history.push(record);
|
|
47
|
-
if (this.#history.length > 200)
|
|
49
|
+
if (this.#history.length > 200) {
|
|
50
|
+
this.#history = this.#history.slice(-200);
|
|
51
|
+
}
|
|
48
52
|
|
|
49
53
|
return { ...pipelineResult, resolvedTrigger };
|
|
50
54
|
}
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
* 收集并规范化自动化执行所需的上下文信息
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
import { LanguageService } from '../../shared/LanguageService.js';
|
|
7
7
|
|
|
8
|
+
export class ContextCollector {
|
|
8
9
|
/**
|
|
9
10
|
* 收集上下文
|
|
10
11
|
* @param {object} rawContext - 原始上下文
|
|
@@ -27,9 +28,10 @@ export class ContextCollector {
|
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
#detectLanguage(filePath) {
|
|
30
|
-
if (!filePath)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
if (!filePath) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
const lang = LanguageService.inferLang(filePath);
|
|
35
|
+
return lang === 'unknown' ? null : lang;
|
|
34
36
|
}
|
|
35
37
|
}
|
|
@@ -5,10 +5,8 @@
|
|
|
5
5
|
* V2 ESM 版本,对应 V1 DirectiveDetector.js
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
stripTriggerPrefix,
|
|
11
|
-
} from '../../infrastructure/config/TriggerSymbol.js';
|
|
8
|
+
import { stripTriggerPrefix, TRIGGER_SYMBOL } from '../../infrastructure/config/TriggerSymbol.js';
|
|
9
|
+
import { LanguageService } from '../../shared/LanguageService.js';
|
|
12
10
|
|
|
13
11
|
/**
|
|
14
12
|
* 指令标记常量
|
|
@@ -43,6 +41,15 @@ export const REGEX = {
|
|
|
43
41
|
DRAFT_FILE: /^_draft_.*\.md$/i,
|
|
44
42
|
};
|
|
45
43
|
|
|
44
|
+
/**
|
|
45
|
+
* 推断文件语言 —— 委托给 LanguageService
|
|
46
|
+
* @param {string} filename
|
|
47
|
+
* @returns {string}
|
|
48
|
+
*/
|
|
49
|
+
function _inferLanguage(filename) {
|
|
50
|
+
return LanguageService.inferLang(filename);
|
|
51
|
+
}
|
|
52
|
+
|
|
46
53
|
/**
|
|
47
54
|
* 检测文件内容中的所有触发指令
|
|
48
55
|
*
|
|
@@ -50,12 +57,15 @@ export const REGEX = {
|
|
|
50
57
|
* @param {string} filename 文件名
|
|
51
58
|
* @returns {{ importArray: string[], headerLine: string|null, alinkLine: string|null,
|
|
52
59
|
* createLine: string|null, createOption: string|null,
|
|
53
|
-
* guardLine: string|null, searchLine: string|null, isSwift: boolean }}
|
|
60
|
+
* guardLine: string|null, searchLine: string|null, isSwift: boolean, language: string }}
|
|
54
61
|
*/
|
|
55
62
|
export function detectTriggers(data, filename) {
|
|
56
|
-
const
|
|
63
|
+
const language = _inferLanguage(filename);
|
|
64
|
+
const isSwift = language === 'swift';
|
|
65
|
+
// Import/header 自动插入目前仅支持 ObjC/Swift(Xcode 工作流)
|
|
66
|
+
const isApple = isSwift || language === 'objectivec';
|
|
57
67
|
const currImportReg = isSwift ? REGEX.IMPORT_SWIFT : REGEX.IMPORT_OBJC;
|
|
58
|
-
const
|
|
68
|
+
const _currHeaderReg = isSwift ? REGEX.HEADER_SWIFT : REGEX.HEADER_OBJC;
|
|
59
69
|
|
|
60
70
|
const triggers = {
|
|
61
71
|
importArray: [],
|
|
@@ -65,7 +75,8 @@ export function detectTriggers(data, filename) {
|
|
|
65
75
|
createOption: null,
|
|
66
76
|
guardLine: null,
|
|
67
77
|
searchLine: null,
|
|
68
|
-
isSwift,
|
|
78
|
+
isSwift, // backward compat
|
|
79
|
+
language, // v3.1 多语言标识
|
|
69
80
|
};
|
|
70
81
|
|
|
71
82
|
const lines = data.split('\n');
|
|
@@ -73,8 +84,8 @@ export function detectTriggers(data, filename) {
|
|
|
73
84
|
const lineVal = line.trim();
|
|
74
85
|
const normalizedLineVal = stripTriggerPrefix(lineVal);
|
|
75
86
|
|
|
76
|
-
// import
|
|
77
|
-
if (currImportReg.test(lineVal)) {
|
|
87
|
+
// import 收集(仅 ObjC/Swift — Xcode 头文件工作流)
|
|
88
|
+
if (isApple && currImportReg.test(lineVal)) {
|
|
78
89
|
triggers.importArray.push(lineVal);
|
|
79
90
|
}
|
|
80
91
|
|
|
@@ -84,10 +95,7 @@ export function detectTriggers(data, filename) {
|
|
|
84
95
|
}
|
|
85
96
|
|
|
86
97
|
// alink 指令
|
|
87
|
-
if (
|
|
88
|
-
lineVal.startsWith(TRIGGER_SYMBOL) &&
|
|
89
|
-
lineVal.endsWith(TRIGGER_SYMBOL + MARKS.ALINK)
|
|
90
|
-
) {
|
|
98
|
+
if (lineVal.startsWith(TRIGGER_SYMBOL) && lineVal.endsWith(TRIGGER_SYMBOL + MARKS.ALINK)) {
|
|
91
99
|
triggers.alinkLine = lineVal;
|
|
92
100
|
}
|
|
93
101
|
|
|
@@ -95,8 +103,7 @@ export function detectTriggers(data, filename) {
|
|
|
95
103
|
const createMatch = normalizedLineVal.match(REGEX.CREATE_LINE);
|
|
96
104
|
if (createMatch) {
|
|
97
105
|
triggers.createLine = lineVal;
|
|
98
|
-
triggers.createOption =
|
|
99
|
-
createMatch[1] === '-c' ? 'c' : createMatch[1] === '-f' ? 'f' : null;
|
|
106
|
+
triggers.createOption = createMatch[1] === '-c' ? 'c' : createMatch[1] === '-f' ? 'f' : null;
|
|
100
107
|
}
|
|
101
108
|
|
|
102
109
|
// guard/audit 指令
|