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
|
@@ -65,10 +65,14 @@ export class TaskPipeline {
|
|
|
65
65
|
// ─── 公共 API ─────────────────────────────────────────
|
|
66
66
|
|
|
67
67
|
/** 管线 ID */
|
|
68
|
-
get id() {
|
|
68
|
+
get id() {
|
|
69
|
+
return this.#id;
|
|
70
|
+
}
|
|
69
71
|
|
|
70
72
|
/** 步骤数 */
|
|
71
|
-
get size() {
|
|
73
|
+
get size() {
|
|
74
|
+
return this.#steps.length;
|
|
75
|
+
}
|
|
72
76
|
|
|
73
77
|
/**
|
|
74
78
|
* 执行管线
|
|
@@ -97,12 +101,12 @@ export class TaskPipeline {
|
|
|
97
101
|
// 拓扑排序 → 按层并行
|
|
98
102
|
const phases = this.#topologicalSort();
|
|
99
103
|
|
|
100
|
-
this.#logger.info(
|
|
104
|
+
this.#logger.info(
|
|
105
|
+
`[TaskPipeline] "${this.#id}" start — ${this.#steps.length} steps, ${phases.length} phases`
|
|
106
|
+
);
|
|
101
107
|
|
|
102
108
|
for (const phase of phases) {
|
|
103
|
-
const promises = phase.map(stepName =>
|
|
104
|
-
this.#executeStep(stepName, executor, ctx, trace),
|
|
105
|
-
);
|
|
109
|
+
const promises = phase.map((stepName) => this.#executeStep(stepName, executor, ctx, trace));
|
|
106
110
|
const results = await Promise.allSettled(promises);
|
|
107
111
|
|
|
108
112
|
// 检查是否有 fail 策略的步骤失败
|
|
@@ -137,7 +141,7 @@ export class TaskPipeline {
|
|
|
137
141
|
* 执行单个步骤(含 when 判断、重试、erorrStrategy)
|
|
138
142
|
*/
|
|
139
143
|
async #executeStep(stepName, executor, ctx, trace) {
|
|
140
|
-
const step = this.#steps.find(s => s.name === stepName);
|
|
144
|
+
const step = this.#steps.find((s) => s.name === stepName);
|
|
141
145
|
const t0 = Date.now();
|
|
142
146
|
|
|
143
147
|
// ── when 条件 ──
|
|
@@ -172,14 +176,20 @@ export class TaskPipeline {
|
|
|
172
176
|
} catch (err) {
|
|
173
177
|
lastError = err;
|
|
174
178
|
if (attempt < maxAttempts && step.retryDelay) {
|
|
175
|
-
await new Promise(r => setTimeout(r, step.retryDelay));
|
|
179
|
+
await new Promise((r) => setTimeout(r, step.retryDelay));
|
|
176
180
|
}
|
|
177
181
|
}
|
|
178
182
|
}
|
|
179
183
|
|
|
180
184
|
// ── 全部重试失败 ──
|
|
181
185
|
const errorMsg = lastError?.message || 'unknown error';
|
|
182
|
-
trace.push({
|
|
186
|
+
trace.push({
|
|
187
|
+
step: stepName,
|
|
188
|
+
status: 'failed',
|
|
189
|
+
durationMs: Date.now() - t0,
|
|
190
|
+
error: errorMsg,
|
|
191
|
+
attempts: maxAttempts,
|
|
192
|
+
});
|
|
183
193
|
ctx._results[stepName] = { _error: errorMsg };
|
|
184
194
|
|
|
185
195
|
if ((step.errorStrategy || 'fail') === 'fail') {
|
|
@@ -227,7 +237,9 @@ export class TaskPipeline {
|
|
|
227
237
|
* 嵌套取值: 'a.b.c' → obj.a.b.c
|
|
228
238
|
*/
|
|
229
239
|
#getNestedValue(obj, path) {
|
|
230
|
-
if (obj == null)
|
|
240
|
+
if (obj == null) {
|
|
241
|
+
return undefined;
|
|
242
|
+
}
|
|
231
243
|
return path.split('.').reduce((acc, key) => acc?.[key], obj);
|
|
232
244
|
}
|
|
233
245
|
|
|
@@ -247,12 +259,14 @@ export class TaskPipeline {
|
|
|
247
259
|
const sorted = [];
|
|
248
260
|
|
|
249
261
|
const visit = (name) => {
|
|
250
|
-
if (visited.has(name))
|
|
262
|
+
if (visited.has(name)) {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
251
265
|
if (visiting.has(name)) {
|
|
252
266
|
throw new Error(`[TaskPipeline] Circular dependency: ${name}`);
|
|
253
267
|
}
|
|
254
268
|
visiting.add(name);
|
|
255
|
-
for (const dep of
|
|
269
|
+
for (const dep of graph.get(name) || []) {
|
|
256
270
|
visit(dep);
|
|
257
271
|
}
|
|
258
272
|
visiting.delete(name);
|
|
@@ -268,7 +282,7 @@ export class TaskPipeline {
|
|
|
268
282
|
const depth = new Map();
|
|
269
283
|
for (const name of sorted) {
|
|
270
284
|
const deps = graph.get(name) || [];
|
|
271
|
-
const d = deps.length === 0 ? 0 : Math.max(...deps.map(dep => (depth.get(dep) || 0) + 1));
|
|
285
|
+
const d = deps.length === 0 ? 0 : Math.max(...deps.map((dep) => (depth.get(dep) || 0) + 1));
|
|
272
286
|
depth.set(name, d);
|
|
273
287
|
}
|
|
274
288
|
|
|
@@ -278,7 +292,7 @@ export class TaskPipeline {
|
|
|
278
292
|
phases[d].push(name);
|
|
279
293
|
}
|
|
280
294
|
|
|
281
|
-
return phases.filter(p => p.length > 0);
|
|
295
|
+
return phases.filter((p) => p.length > 0);
|
|
282
296
|
}
|
|
283
297
|
|
|
284
298
|
/**
|
|
@@ -287,14 +301,20 @@ export class TaskPipeline {
|
|
|
287
301
|
#validate() {
|
|
288
302
|
const names = new Set();
|
|
289
303
|
for (const step of this.#steps) {
|
|
290
|
-
if (!step.name)
|
|
291
|
-
|
|
292
|
-
|
|
304
|
+
if (!step.name) {
|
|
305
|
+
throw new Error('[TaskPipeline] Step must have a name');
|
|
306
|
+
}
|
|
307
|
+
if (!step.tool) {
|
|
308
|
+
throw new Error(`[TaskPipeline] Step "${step.name}" must have a tool`);
|
|
309
|
+
}
|
|
310
|
+
if (names.has(step.name)) {
|
|
311
|
+
throw new Error(`[TaskPipeline] Duplicate step name: "${step.name}"`);
|
|
312
|
+
}
|
|
293
313
|
names.add(step.name);
|
|
294
314
|
}
|
|
295
315
|
// 检查 dependsOn 引用是否存在
|
|
296
316
|
for (const step of this.#steps) {
|
|
297
|
-
for (const dep of
|
|
317
|
+
for (const dep of step.dependsOn || []) {
|
|
298
318
|
if (!names.has(dep)) {
|
|
299
319
|
throw new Error(`[TaskPipeline] Step "${step.name}" depends on unknown step "${dep}"`);
|
|
300
320
|
}
|
|
@@ -309,7 +329,7 @@ export class TaskPipeline {
|
|
|
309
329
|
const phases = this.#topologicalSort();
|
|
310
330
|
return {
|
|
311
331
|
id: this.#id,
|
|
312
|
-
steps: this.#steps.map(s => ({
|
|
332
|
+
steps: this.#steps.map((s) => ({
|
|
313
333
|
name: s.name,
|
|
314
334
|
tool: s.tool,
|
|
315
335
|
dependsOn: s.dependsOn || [],
|
|
@@ -18,30 +18,30 @@ import Logger from '../../infrastructure/logging/Logger.js';
|
|
|
18
18
|
*/
|
|
19
19
|
const PARAM_ALIASES = {
|
|
20
20
|
// read_project_file 变体
|
|
21
|
-
file:
|
|
22
|
-
filename:
|
|
23
|
-
file_name:
|
|
24
|
-
filepath:
|
|
25
|
-
file_path:
|
|
26
|
-
path:
|
|
21
|
+
file: 'filePath',
|
|
22
|
+
filename: 'filePath',
|
|
23
|
+
file_name: 'filePath',
|
|
24
|
+
filepath: 'filePath',
|
|
25
|
+
file_path: 'filePath',
|
|
26
|
+
path: 'filePath',
|
|
27
27
|
// search_project_code 变体
|
|
28
|
-
query:
|
|
29
|
-
search:
|
|
30
|
-
keyword:
|
|
31
|
-
search_query:
|
|
32
|
-
search_text:
|
|
33
|
-
regex:
|
|
28
|
+
query: 'pattern',
|
|
29
|
+
search: 'pattern',
|
|
30
|
+
keyword: 'pattern',
|
|
31
|
+
search_query: 'pattern',
|
|
32
|
+
search_text: 'pattern',
|
|
33
|
+
regex: 'pattern',
|
|
34
34
|
// 通用变体
|
|
35
|
-
is_regex:
|
|
36
|
-
file_filter:
|
|
35
|
+
is_regex: 'isRegex',
|
|
36
|
+
file_filter: 'fileFilter',
|
|
37
37
|
context_lines: 'contextLines',
|
|
38
|
-
max_results:
|
|
39
|
-
start_line:
|
|
40
|
-
end_line:
|
|
41
|
-
max_lines:
|
|
42
|
-
candidate_id:
|
|
43
|
-
recipe_id:
|
|
44
|
-
skill_name:
|
|
38
|
+
max_results: 'maxResults',
|
|
39
|
+
start_line: 'startLine',
|
|
40
|
+
end_line: 'endLine',
|
|
41
|
+
max_lines: 'maxLines',
|
|
42
|
+
candidate_id: 'candidateId',
|
|
43
|
+
recipe_id: 'recipeId',
|
|
44
|
+
skill_name: 'skillName',
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
export class ToolRegistry {
|
|
@@ -62,7 +62,9 @@ export class ToolRegistry {
|
|
|
62
62
|
*/
|
|
63
63
|
register(toolDef) {
|
|
64
64
|
const { name, description, handler, parameters = {} } = toolDef;
|
|
65
|
-
if (!name || !handler)
|
|
65
|
+
if (!name || !handler) {
|
|
66
|
+
throw new Error('Tool must have name and handler');
|
|
67
|
+
}
|
|
66
68
|
this.#tools.set(name, { name, description, parameters, handler });
|
|
67
69
|
}
|
|
68
70
|
|
|
@@ -71,7 +73,9 @@ export class ToolRegistry {
|
|
|
71
73
|
* @param {Array<object>} defs
|
|
72
74
|
*/
|
|
73
75
|
registerAll(defs) {
|
|
74
|
-
for (const def of defs)
|
|
76
|
+
for (const def of defs) {
|
|
77
|
+
this.register(def);
|
|
78
|
+
}
|
|
75
79
|
this.#logger.info(`[ToolRegistry] ${defs.length} tools registered`);
|
|
76
80
|
}
|
|
77
81
|
|
|
@@ -83,7 +87,9 @@ export class ToolRegistry {
|
|
|
83
87
|
getToolSchemas(allowedTools) {
|
|
84
88
|
const schemas = [];
|
|
85
89
|
for (const [name, tool] of this.#tools) {
|
|
86
|
-
if (allowedTools && !allowedTools.includes(name))
|
|
90
|
+
if (allowedTools && !allowedTools.includes(name)) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
87
93
|
schemas.push({
|
|
88
94
|
name: tool.name,
|
|
89
95
|
description: tool.description,
|
|
@@ -102,7 +108,9 @@ export class ToolRegistry {
|
|
|
102
108
|
*/
|
|
103
109
|
async execute(name, params, context = {}) {
|
|
104
110
|
const tool = this.#tools.get(name);
|
|
105
|
-
if (!tool)
|
|
111
|
+
if (!tool) {
|
|
112
|
+
throw new Error(`Tool '${name}' not found`);
|
|
113
|
+
}
|
|
106
114
|
|
|
107
115
|
// 参数归一化: AI 可能用 snake_case / 不同命名传参,
|
|
108
116
|
// 将其映射到 tool schema 中定义的 camelCase 参数名
|
|
@@ -113,7 +121,12 @@ export class ToolRegistry {
|
|
|
113
121
|
const result = await tool.handler(normalized, context);
|
|
114
122
|
return result;
|
|
115
123
|
} catch (err) {
|
|
116
|
-
|
|
124
|
+
// API Key 缺失为配置问题,降为 info 级别
|
|
125
|
+
if (err.code === 'API_KEY_MISSING') {
|
|
126
|
+
this.#logger.info(`Tool '${name}' 跳过: ${err.message}`);
|
|
127
|
+
} else {
|
|
128
|
+
this.#logger.error(`Tool '${name}' failed`, { error: err.message });
|
|
129
|
+
}
|
|
117
130
|
return { error: err.message };
|
|
118
131
|
}
|
|
119
132
|
}
|
|
@@ -130,10 +143,14 @@ export class ToolRegistry {
|
|
|
130
143
|
* 3. 常用别名表兜底
|
|
131
144
|
*/
|
|
132
145
|
#normalizeParams(params, schema) {
|
|
133
|
-
if (!params || typeof params !== 'object')
|
|
146
|
+
if (!params || typeof params !== 'object') {
|
|
147
|
+
return params || {};
|
|
148
|
+
}
|
|
134
149
|
const properties = schema?.properties || {};
|
|
135
150
|
const schemaKeys = new Set(Object.keys(properties));
|
|
136
|
-
if (schemaKeys.size === 0)
|
|
151
|
+
if (schemaKeys.size === 0) {
|
|
152
|
+
return params;
|
|
153
|
+
}
|
|
137
154
|
|
|
138
155
|
const result = {};
|
|
139
156
|
const unmatched = [];
|
|
@@ -165,7 +182,9 @@ export class ToolRegistry {
|
|
|
165
182
|
}
|
|
166
183
|
|
|
167
184
|
if (unmatched.length > 0) {
|
|
168
|
-
this.#logger.debug(
|
|
185
|
+
this.#logger.debug(
|
|
186
|
+
`[ToolRegistry] param normalization: unmatched keys [${unmatched.join(', ')}]`
|
|
187
|
+
);
|
|
169
188
|
}
|
|
170
189
|
|
|
171
190
|
return result;
|
|
@@ -22,7 +22,9 @@ import Logger from '../../infrastructure/logging/Logger.js';
|
|
|
22
22
|
*/
|
|
23
23
|
const TOOL_COMPRESS_STRATEGIES = {
|
|
24
24
|
search_project_code(result) {
|
|
25
|
-
if (typeof result !== 'object')
|
|
25
|
+
if (typeof result !== 'object') {
|
|
26
|
+
return String(result).substring(0, 600);
|
|
27
|
+
}
|
|
26
28
|
const matches = result.matches || [];
|
|
27
29
|
const batchResults = result.batchResults || {};
|
|
28
30
|
|
|
@@ -32,7 +34,9 @@ const TOOL_COMPRESS_STRATEGIES = {
|
|
|
32
34
|
lines.push(`搜索到 ${matches.length} 个匹配`);
|
|
33
35
|
const fileGroups = {};
|
|
34
36
|
for (const m of matches) {
|
|
35
|
-
if (!fileGroups[m.file])
|
|
37
|
+
if (!fileGroups[m.file]) {
|
|
38
|
+
fileGroups[m.file] = [];
|
|
39
|
+
}
|
|
36
40
|
fileGroups[m.file].push(m.line);
|
|
37
41
|
}
|
|
38
42
|
for (const [file, lineNums] of Object.entries(fileGroups).slice(0, 8)) {
|
|
@@ -51,7 +55,9 @@ const TOOL_COMPRESS_STRATEGIES = {
|
|
|
51
55
|
},
|
|
52
56
|
|
|
53
57
|
read_project_file(result) {
|
|
54
|
-
if (typeof result !== 'object')
|
|
58
|
+
if (typeof result !== 'object') {
|
|
59
|
+
return String(result).substring(0, 600);
|
|
60
|
+
}
|
|
55
61
|
// 批量读取结果
|
|
56
62
|
if (result.files) {
|
|
57
63
|
const lines = [`读取 ${result.files.length} 个文件`];
|
|
@@ -68,28 +74,44 @@ const TOOL_COMPRESS_STRATEGIES = {
|
|
|
68
74
|
},
|
|
69
75
|
|
|
70
76
|
get_class_info(result) {
|
|
71
|
-
if (typeof result !== 'object')
|
|
77
|
+
if (typeof result !== 'object') {
|
|
78
|
+
return String(result).substring(0, 600);
|
|
79
|
+
}
|
|
72
80
|
const lines = [`类 ${result.className || '?'}`];
|
|
73
|
-
if (result.superClass)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (result.
|
|
81
|
+
if (result.superClass) {
|
|
82
|
+
lines.push(` 继承: ${result.superClass}`);
|
|
83
|
+
}
|
|
84
|
+
if (result.protocols?.length) {
|
|
85
|
+
lines.push(` 协议: ${result.protocols.join(', ')}`);
|
|
86
|
+
}
|
|
87
|
+
if (result.methods?.length) {
|
|
88
|
+
lines.push(` 方法数: ${result.methods.length}`);
|
|
89
|
+
}
|
|
90
|
+
if (result.properties?.length) {
|
|
91
|
+
lines.push(` 属性数: ${result.properties.length}`);
|
|
92
|
+
}
|
|
77
93
|
return lines.join('\n');
|
|
78
94
|
},
|
|
79
95
|
|
|
80
96
|
get_class_hierarchy(result) {
|
|
81
|
-
if (typeof result !== 'object')
|
|
97
|
+
if (typeof result !== 'object') {
|
|
98
|
+
return String(result).substring(0, 600);
|
|
99
|
+
}
|
|
82
100
|
const classes = result.classes || result.hierarchy || [];
|
|
83
101
|
return `类层级: ${Array.isArray(classes) ? classes.length : 0} 个类`;
|
|
84
102
|
},
|
|
85
103
|
|
|
86
104
|
get_project_overview(result) {
|
|
87
|
-
if (typeof result !== 'object')
|
|
105
|
+
if (typeof result !== 'object') {
|
|
106
|
+
return String(result).substring(0, 800);
|
|
107
|
+
}
|
|
88
108
|
return JSON.stringify(result).substring(0, 800);
|
|
89
109
|
},
|
|
90
110
|
|
|
91
111
|
list_project_structure(result) {
|
|
92
|
-
if (typeof result !== 'object')
|
|
112
|
+
if (typeof result !== 'object') {
|
|
113
|
+
return String(result).substring(0, 600);
|
|
114
|
+
}
|
|
93
115
|
const entries = result.entries || result.children || [];
|
|
94
116
|
return `目录结构: ${Array.isArray(entries) ? entries.length : 0} 个条目`;
|
|
95
117
|
},
|
|
@@ -100,8 +122,10 @@ const TOOL_COMPRESS_STRATEGIES = {
|
|
|
100
122
|
*/
|
|
101
123
|
function defaultCompress(result, maxChars = 600) {
|
|
102
124
|
const str = typeof result === 'string' ? result : JSON.stringify(result);
|
|
103
|
-
if (str.length <= maxChars)
|
|
104
|
-
|
|
125
|
+
if (str.length <= maxChars) {
|
|
126
|
+
return str;
|
|
127
|
+
}
|
|
128
|
+
return `${str.substring(0, maxChars)}…(truncated)`;
|
|
105
129
|
}
|
|
106
130
|
|
|
107
131
|
export class WorkingMemory {
|
|
@@ -205,7 +229,9 @@ export class WorkingMemory {
|
|
|
205
229
|
for (const f of sorted) {
|
|
206
230
|
const badge = f.importance >= 8 ? '⚠️' : f.importance >= 5 ? '📋' : '💡';
|
|
207
231
|
let line = `- ${badge} [${f.importance}/10] ${f.finding}`;
|
|
208
|
-
if (f.evidence)
|
|
232
|
+
if (f.evidence) {
|
|
233
|
+
line += ` (${f.evidence})`;
|
|
234
|
+
}
|
|
209
235
|
parts.push(line);
|
|
210
236
|
}
|
|
211
237
|
}
|
|
@@ -242,13 +268,13 @@ export class WorkingMemory {
|
|
|
242
268
|
*/
|
|
243
269
|
distill() {
|
|
244
270
|
return {
|
|
245
|
-
keyFindings: this.#scratchpad.map(f => ({
|
|
271
|
+
keyFindings: this.#scratchpad.map((f) => ({
|
|
246
272
|
finding: f.finding,
|
|
247
273
|
evidence: f.evidence,
|
|
248
274
|
importance: f.importance,
|
|
249
275
|
})),
|
|
250
|
-
toolCallSummary: this.#compressedObservations.map(
|
|
251
|
-
`[${s.toolName}] ${s.summary.substring(0, 150)}`
|
|
276
|
+
toolCallSummary: this.#compressedObservations.map(
|
|
277
|
+
(s) => `[${s.toolName}] ${s.summary.substring(0, 150)}`
|
|
252
278
|
),
|
|
253
279
|
totalObservations: this.#totalObservations,
|
|
254
280
|
compressedCount: this.#compressedObservations.length,
|
|
@@ -280,7 +306,7 @@ export class WorkingMemory {
|
|
|
280
306
|
*/
|
|
281
307
|
getHighPriorityFindings(minImportance = 7) {
|
|
282
308
|
return this.#scratchpad
|
|
283
|
-
.filter(f => f.importance >= minImportance)
|
|
309
|
+
.filter((f) => f.importance >= minImportance)
|
|
284
310
|
.sort((a, b) => b.importance - a.importance);
|
|
285
311
|
}
|
|
286
312
|
|