agentic-qe 3.7.20 → 3.7.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/v3/qe-deployment-advisor.md +14 -0
- package/.claude/agents/v3/qe-gap-detector.md +8 -0
- package/.claude/agents/v3/qe-impact-analyzer.md +11 -0
- package/.claude/agents/v3/qe-queen-coordinator.md +45 -0
- package/.claude/agents/v3/qe-root-cause-analyzer.md +11 -0
- package/.claude/agents/v3/qe-security-scanner.md +25 -16
- package/.claude/helpers/brain-checkpoint.cjs +3 -3
- package/.claude/helpers/statusline-v3.cjs +4 -3
- package/.claude/skills/skills-manifest.json +1 -1
- package/CHANGELOG.md +20 -0
- package/assets/agents/v3/qe-deployment-advisor.md +14 -0
- package/assets/agents/v3/qe-gap-detector.md +8 -0
- package/assets/agents/v3/qe-impact-analyzer.md +11 -0
- package/assets/agents/v3/qe-queen-coordinator.md +45 -0
- package/assets/agents/v3/qe-root-cause-analyzer.md +11 -0
- package/assets/agents/v3/qe-security-scanner.md +25 -16
- package/assets/helpers/statusline-v3.cjs +4 -3
- package/dist/adapters/claude-flow/model-router-bridge.d.ts +0 -6
- package/dist/adapters/claude-flow/model-router-bridge.js +4 -17
- package/dist/adapters/claude-flow/pretrain-bridge.d.ts +0 -6
- package/dist/adapters/claude-flow/pretrain-bridge.js +6 -19
- package/dist/adapters/claude-flow/trajectory-bridge.d.ts +0 -6
- package/dist/adapters/claude-flow/trajectory-bridge.js +21 -23
- package/dist/cli/bundle.js +1814 -981
- package/dist/coordination/protocols/security-audit.d.ts +3 -6
- package/dist/coordination/protocols/security-audit.js +8 -88
- package/dist/coordination/queen-coordinator.d.ts +13 -0
- package/dist/coordination/queen-coordinator.js +76 -0
- package/dist/coordination/queen-task-management.d.ts +2 -0
- package/dist/coordination/queen-task-management.js +10 -0
- package/dist/coordination/queen-types.d.ts +3 -0
- package/dist/coordination/task-executor.js +7 -5
- package/dist/domains/security-compliance/services/scanners/sast-scanner.d.ts +25 -1
- package/dist/domains/security-compliance/services/scanners/sast-scanner.js +140 -11
- package/dist/domains/security-compliance/services/scanners/scanner-types.d.ts +2 -0
- package/dist/domains/security-compliance/services/scanners/scanner-types.js +1 -0
- package/dist/domains/test-execution/services/mincut-test-optimizer.js +2 -0
- package/dist/init/agents-installer.d.ts +2 -0
- package/dist/init/agents-installer.js +13 -0
- package/dist/init/enhancements/claude-flow-adapter.js +51 -24
- package/dist/init/init-wizard.js +1 -1
- package/dist/init/phases/07-hooks.js +6 -6
- package/dist/integrations/ruvector/brain-rvf-exporter.js +14 -2
- package/dist/learning/experience-capture-middleware.js +3 -1
- package/dist/learning/qe-reasoning-bank.js +3 -3
- package/dist/learning/sqlite-persistence.js +16 -0
- package/dist/learning/token-tracker.js +4 -2
- package/dist/mcp/bundle.js +1179 -500
- package/dist/routing/agent-dependency-graph.d.ts +77 -0
- package/dist/routing/agent-dependency-graph.js +359 -0
- package/dist/routing/co-execution-repository.d.ts +68 -0
- package/dist/routing/co-execution-repository.js +184 -0
- package/dist/routing/index.d.ts +6 -0
- package/dist/routing/index.js +6 -0
- package/dist/routing/qe-task-router.d.ts +7 -0
- package/dist/routing/qe-task-router.js +63 -1
- package/dist/routing/signal-merger.d.ts +81 -0
- package/dist/routing/signal-merger.js +136 -0
- package/dist/routing/types.d.ts +1 -0
- package/dist/shared/llm/providers/azure-openai.js +3 -2
- package/dist/shared/llm/providers/bedrock.js +3 -2
- package/dist/shared/llm/providers/claude.js +3 -2
- package/dist/shared/llm/providers/gemini.js +3 -2
- package/dist/shared/llm/providers/openai.js +3 -2
- package/dist/shared/llm/providers/openrouter.js +3 -2
- package/dist/shared/llm/retry.d.ts +10 -0
- package/dist/shared/llm/retry.js +16 -0
- package/dist/shared/llm/router/agent-router-config.d.ts +2 -1
- package/dist/shared/llm/router/agent-router-config.js +38 -88
- package/dist/validation/index.d.ts +2 -0
- package/dist/validation/index.js +4 -0
- package/dist/validation/steps/agent-mcp-validator.d.ts +88 -0
- package/dist/validation/steps/agent-mcp-validator.js +254 -0
- package/package.json +1 -1
package/dist/routing/index.d.ts
CHANGED
|
@@ -11,6 +11,10 @@ export type { QEAgentProfile, QETask, QERoutingDecision, AgentScore, RoutingWeig
|
|
|
11
11
|
export { DEFAULT_ROUTER_CONFIG } from './types.js';
|
|
12
12
|
export { QE_AGENT_REGISTRY, getAgentsByDomain, getAgentsByCapability, getAgentsByLanguage, getAgentsByFramework, getAgentsByComplexity, getAgentById, getAgentCounts, } from './qe-agent-registry.js';
|
|
13
13
|
export { QETaskRouter, createQETaskRouter, } from './qe-task-router.js';
|
|
14
|
+
export { CoExecutionRepository, getCoExecutionRepository, } from './co-execution-repository.js';
|
|
15
|
+
export type { CoExecutionRecord, CoExecutionStats, } from './co-execution-repository.js';
|
|
16
|
+
export { SignalMerger, createSignalMerger, DEFAULT_SIGNAL_MERGER_CONFIG, } from './signal-merger.js';
|
|
17
|
+
export type { SignalSource, RoutingSignal, MergedAgentScore, SignalMergerConfig, } from './signal-merger.js';
|
|
14
18
|
export { RoutingFeedbackCollector, createRoutingFeedbackCollector, } from './routing-feedback.js';
|
|
15
19
|
export { classifyTask, isSimpleTask, requiresOpus, getRecommendedModel, getComplexityScore, COMPLEX_DOMAINS, MODERATE_DOMAINS, COMPLEX_CAPABILITIES, COMPLEXITY_THRESHOLDS, COMPLEXITY_TO_MODEL, } from './task-classifier.js';
|
|
16
20
|
export type { TaskComplexity, ClaudeModel, ComplexityFactor, ClassificationResult, ClassifiableTask, } from './task-classifier.js';
|
|
@@ -18,6 +22,8 @@ export { TinyDancerRouter, createTinyDancerRouter, } from './tiny-dancer-router.
|
|
|
18
22
|
export type { RouteResult, TinyDancerConfig, RoutingOutcome as TinyDancerRoutingOutcome, RouterStats, } from './tiny-dancer-router.js';
|
|
19
23
|
export { DEFAULT_ROUTING_CONFIG, DEFAULT_CONFIDENCE_THRESHOLDS, DEFAULT_TIER_MAPPING, DEFAULT_COST_OPTIMIZATION, DEFAULT_FALLBACK_CONFIG, loadRoutingConfigFromEnv, mapComplexityToTier, getNextFallbackTier, tierToModel, estimateTaskCost, validateRoutingConfig, } from './routing-config.js';
|
|
20
24
|
export type { AgentTier, ConfidenceThresholds, ComplexityTierMapping, CostOptimizationConfig, FallbackConfig, RoutingConfig, } from './routing-config.js';
|
|
25
|
+
export { parseDependenciesFromFrontmatter, buildDependencyGraph, createSpawnPlan, getAgentDependencies, } from './agent-dependency-graph.js';
|
|
26
|
+
export type { DependencyType, AgentDependency, McpServerDependency, ModelRequirement, AgentDependencies, DependencyNode, DependencyGraphResult, SpawnPlan, } from './agent-dependency-graph.js';
|
|
21
27
|
export { EMACalibrator, DEFAULT_EMA_CONFIG, } from './calibration/index.js';
|
|
22
28
|
export type { CalibrationRecord, EMAConfig, } from './calibration/index.js';
|
|
23
29
|
export { AutoEscalationTracker, DEFAULT_ESCALATION_CONFIG, } from './escalation/index.js';
|
package/dist/routing/index.js
CHANGED
|
@@ -12,6 +12,10 @@ export { DEFAULT_ROUTER_CONFIG } from './types.js';
|
|
|
12
12
|
export { QE_AGENT_REGISTRY, getAgentsByDomain, getAgentsByCapability, getAgentsByLanguage, getAgentsByFramework, getAgentsByComplexity, getAgentById, getAgentCounts, } from './qe-agent-registry.js';
|
|
13
13
|
// Router
|
|
14
14
|
export { QETaskRouter, createQETaskRouter, } from './qe-task-router.js';
|
|
15
|
+
// Co-Execution Repository (Issue #342 Item 3)
|
|
16
|
+
export { CoExecutionRepository, getCoExecutionRepository, } from './co-execution-repository.js';
|
|
17
|
+
// Signal Merger (Issue #342 Item 3)
|
|
18
|
+
export { SignalMerger, createSignalMerger, DEFAULT_SIGNAL_MERGER_CONFIG, } from './signal-merger.js';
|
|
15
19
|
// Feedback
|
|
16
20
|
export { RoutingFeedbackCollector, createRoutingFeedbackCollector, } from './routing-feedback.js';
|
|
17
21
|
// Task Classifier (TD-002)
|
|
@@ -20,6 +24,8 @@ export { classifyTask, isSimpleTask, requiresOpus, getRecommendedModel, getCompl
|
|
|
20
24
|
export { TinyDancerRouter, createTinyDancerRouter, } from './tiny-dancer-router.js';
|
|
21
25
|
// Routing Configuration (TD-004)
|
|
22
26
|
export { DEFAULT_ROUTING_CONFIG, DEFAULT_CONFIDENCE_THRESHOLDS, DEFAULT_TIER_MAPPING, DEFAULT_COST_OPTIMIZATION, DEFAULT_FALLBACK_CONFIG, loadRoutingConfigFromEnv, mapComplexityToTier, getNextFallbackTier, tierToModel, estimateTaskCost, validateRoutingConfig, } from './routing-config.js';
|
|
27
|
+
// Agent Dependency Graph (Issue #342 Item 2)
|
|
28
|
+
export { parseDependenciesFromFrontmatter, buildDependencyGraph, createSpawnPlan, getAgentDependencies, } from './agent-dependency-graph.js';
|
|
23
29
|
// EMA Calibration (loki-mode inspired)
|
|
24
30
|
export { EMACalibrator, DEFAULT_EMA_CONFIG, } from './calibration/index.js';
|
|
25
31
|
// Auto-Escalation Tracker (loki-mode inspired)
|
|
@@ -18,6 +18,8 @@ export declare class QETaskRouter {
|
|
|
18
18
|
private initialized;
|
|
19
19
|
private embeddingCache;
|
|
20
20
|
private contextCompiler;
|
|
21
|
+
private coExecutionRepo;
|
|
22
|
+
private signalMerger;
|
|
21
23
|
/** Optional witness chain for audit trail of routing decisions (ADR-070) */
|
|
22
24
|
private _witnessChain;
|
|
23
25
|
set witnessChain(wc: WitnessChain | null);
|
|
@@ -66,6 +68,11 @@ export declare class QETaskRouter {
|
|
|
66
68
|
* Update agent performance based on feedback
|
|
67
69
|
*/
|
|
68
70
|
updateAgentPerformance(agentId: string, success: boolean, qualityScore: number, durationMs: number): void;
|
|
71
|
+
/**
|
|
72
|
+
* Record a co-execution outcome for behavioral learning (Issue #342 Item 3).
|
|
73
|
+
* Call this after a swarm task completes to track which agent combinations work well together.
|
|
74
|
+
*/
|
|
75
|
+
recordCoExecution(agentIds: string[], domain: string, success: boolean, taskDescription?: string): void;
|
|
69
76
|
/**
|
|
70
77
|
* Get router statistics
|
|
71
78
|
*/
|
|
@@ -12,6 +12,8 @@ import { DEFAULT_ROUTER_CONFIG } from './types.js';
|
|
|
12
12
|
import { QE_AGENT_REGISTRY, getAgentById, getAgentOverlayConfig, initializeOverlays } from './qe-agent-registry.js';
|
|
13
13
|
import { computeRealEmbedding, cosineSimilarity, } from '../learning/real-embeddings.js';
|
|
14
14
|
import { ContextCompiler, formatContextForPrompt } from '../context/compiler.js';
|
|
15
|
+
import { getCoExecutionRepository } from './co-execution-repository.js';
|
|
16
|
+
import { createSignalMerger } from './signal-merger.js';
|
|
15
17
|
// ============================================================================
|
|
16
18
|
// Task Keyword Detection
|
|
17
19
|
// ============================================================================
|
|
@@ -132,11 +134,14 @@ export class QETaskRouter {
|
|
|
132
134
|
initialized = false;
|
|
133
135
|
embeddingCache = new Map();
|
|
134
136
|
contextCompiler = null;
|
|
137
|
+
coExecutionRepo = null;
|
|
138
|
+
signalMerger;
|
|
135
139
|
/** Optional witness chain for audit trail of routing decisions (ADR-070) */
|
|
136
140
|
_witnessChain = null;
|
|
137
141
|
set witnessChain(wc) { this._witnessChain = wc; }
|
|
138
142
|
constructor(config = {}) {
|
|
139
143
|
this.config = { ...DEFAULT_ROUTER_CONFIG, ...config };
|
|
144
|
+
this.signalMerger = createSignalMerger();
|
|
140
145
|
}
|
|
141
146
|
/**
|
|
142
147
|
* Initialize router by computing agent embeddings
|
|
@@ -153,6 +158,18 @@ export class QETaskRouter {
|
|
|
153
158
|
this.agentEmbeddings.set(agent.id, embedding);
|
|
154
159
|
}
|
|
155
160
|
this.contextCompiler = new ContextCompiler();
|
|
161
|
+
// Initialize co-execution repository for behavioral signals (Issue #342 Item 3)
|
|
162
|
+
try {
|
|
163
|
+
const { getUnifiedMemory } = await import('../kernel/unified-memory.js');
|
|
164
|
+
const unifiedMemory = getUnifiedMemory();
|
|
165
|
+
await unifiedMemory.initialize();
|
|
166
|
+
this.coExecutionRepo = getCoExecutionRepository();
|
|
167
|
+
this.coExecutionRepo.initialize(unifiedMemory.getDatabase());
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
// Non-blocking: behavioral signals unavailable if DB init fails
|
|
171
|
+
console.debug('[QETaskRouter] Co-execution repository unavailable (behavioral signals disabled)');
|
|
172
|
+
}
|
|
156
173
|
this.initialized = true;
|
|
157
174
|
}
|
|
158
175
|
/**
|
|
@@ -195,7 +212,45 @@ export class QETaskRouter {
|
|
|
195
212
|
const score = await this.scoreAgent(agent, task, taskEmbedding, detectedCapabilities);
|
|
196
213
|
scores.push(score);
|
|
197
214
|
}
|
|
198
|
-
// 4.
|
|
215
|
+
// 4. Multi-signal merge (Issue #342 Item 3)
|
|
216
|
+
// Build static analysis signal map from base scores
|
|
217
|
+
const staticAnalysisMap = new Map();
|
|
218
|
+
for (const score of scores) {
|
|
219
|
+
staticAnalysisMap.set(score.agent, {
|
|
220
|
+
confidence: score.combinedScore,
|
|
221
|
+
reason: score.reason,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
// Build behavioral signal map from co-execution data
|
|
225
|
+
const behavioralMap = new Map();
|
|
226
|
+
if (this.coExecutionRepo && task.context?.previousAgent) {
|
|
227
|
+
for (const score of scores) {
|
|
228
|
+
const stats = this.coExecutionRepo.getCoExecutionStats(task.context.previousAgent, score.agent);
|
|
229
|
+
if (stats) {
|
|
230
|
+
behavioralMap.set(score.agent, stats);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
// Merge signals with precedence: user > static > behavioral
|
|
235
|
+
const mergedResults = this.signalMerger.merge(scores.map(s => s.agent), {
|
|
236
|
+
userDeclaration: task.context?.preferredAgent,
|
|
237
|
+
staticAnalysis: staticAnalysisMap,
|
|
238
|
+
behavioral: behavioralMap,
|
|
239
|
+
});
|
|
240
|
+
// Apply merged scores back
|
|
241
|
+
for (const merged of mergedResults) {
|
|
242
|
+
const score = scores.find(s => s.agent === merged.agentId);
|
|
243
|
+
if (score) {
|
|
244
|
+
score.combinedScore = merged.mergedConfidence;
|
|
245
|
+
if (merged.determinedBy === 'user-declaration') {
|
|
246
|
+
score.reason = 'user-declared agent (confidence: 1.0)';
|
|
247
|
+
}
|
|
248
|
+
else if (merged.signals.length > 1) {
|
|
249
|
+
score.reason += `, ${merged.determinedBy} signal dominant`;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// 4.5. Sort by combined score
|
|
199
254
|
scores.sort((a, b) => b.combinedScore - a.combinedScore);
|
|
200
255
|
// 5. Build routing decision
|
|
201
256
|
const topScore = scores[0];
|
|
@@ -470,6 +525,13 @@ export class QETaskRouter {
|
|
|
470
525
|
agent.avgDurationMs =
|
|
471
526
|
(agent.avgDurationMs * prevTotal + durationMs) / agent.tasksCompleted;
|
|
472
527
|
}
|
|
528
|
+
/**
|
|
529
|
+
* Record a co-execution outcome for behavioral learning (Issue #342 Item 3).
|
|
530
|
+
* Call this after a swarm task completes to track which agent combinations work well together.
|
|
531
|
+
*/
|
|
532
|
+
recordCoExecution(agentIds, domain, success, taskDescription) {
|
|
533
|
+
this.coExecutionRepo?.recordSwarmCoExecution(agentIds, domain, success, taskDescription);
|
|
534
|
+
}
|
|
473
535
|
/**
|
|
474
536
|
* Get router statistics
|
|
475
537
|
*/
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-Signal Confidence Merger (Issue #342, Item 3)
|
|
3
|
+
*
|
|
4
|
+
* Combines three independent routing signals with clear precedence:
|
|
5
|
+
*
|
|
6
|
+
* | Signal | AQE Equivalent | Confidence | Precedence |
|
|
7
|
+
* |--------|---------------|------------|------------|
|
|
8
|
+
* | User declaration | preferredAgent in task context or CLAUDE.md | 1.0 | Overrides all |
|
|
9
|
+
* | Static analysis | Code pattern scanning (domain + capability match) | 0.5-0.9 | Overrides behavioral |
|
|
10
|
+
* | Behavioral co-usage | Learning DB: which agents succeed together | 0.0-1.0 (linear ramp) | Lowest |
|
|
11
|
+
*
|
|
12
|
+
* Key rules from Skillsmith:
|
|
13
|
+
* - When declaration and inference agree, keep declaration, drop inferred (dedup)
|
|
14
|
+
* - Behavioral confidence ramps linearly: min(1.0, success_count / 20)
|
|
15
|
+
*/
|
|
16
|
+
import type { CoExecutionStats } from './co-execution-repository.js';
|
|
17
|
+
/** Signal source type */
|
|
18
|
+
export type SignalSource = 'user-declaration' | 'static-analysis' | 'behavioral';
|
|
19
|
+
/** A single routing signal */
|
|
20
|
+
export interface RoutingSignal {
|
|
21
|
+
/** Signal source */
|
|
22
|
+
readonly source: SignalSource;
|
|
23
|
+
/** Recommended agent ID */
|
|
24
|
+
readonly agentId: string;
|
|
25
|
+
/** Confidence score (0-1) */
|
|
26
|
+
readonly confidence: number;
|
|
27
|
+
/** Human-readable reason */
|
|
28
|
+
readonly reason: string;
|
|
29
|
+
}
|
|
30
|
+
/** Merged signal result for one agent */
|
|
31
|
+
export interface MergedAgentScore {
|
|
32
|
+
/** Agent ID */
|
|
33
|
+
readonly agentId: string;
|
|
34
|
+
/** Final merged confidence */
|
|
35
|
+
readonly mergedConfidence: number;
|
|
36
|
+
/** Individual signal contributions */
|
|
37
|
+
readonly signals: RoutingSignal[];
|
|
38
|
+
/** Which signal determined the final score */
|
|
39
|
+
readonly determinedBy: SignalSource;
|
|
40
|
+
/** Whether signals agreed */
|
|
41
|
+
readonly signalsAgreed: boolean;
|
|
42
|
+
}
|
|
43
|
+
/** Configuration for the signal merger */
|
|
44
|
+
export interface SignalMergerConfig {
|
|
45
|
+
/** Weight for static analysis signal when no declaration present */
|
|
46
|
+
readonly staticAnalysisWeight: number;
|
|
47
|
+
/** Weight for behavioral signal when no declaration present */
|
|
48
|
+
readonly behavioralWeight: number;
|
|
49
|
+
/** Minimum behavioral confidence to contribute to scoring */
|
|
50
|
+
readonly minBehavioralConfidence: number;
|
|
51
|
+
}
|
|
52
|
+
export declare const DEFAULT_SIGNAL_MERGER_CONFIG: SignalMergerConfig;
|
|
53
|
+
export declare class SignalMerger {
|
|
54
|
+
private readonly config;
|
|
55
|
+
constructor(config?: Partial<SignalMergerConfig>);
|
|
56
|
+
/**
|
|
57
|
+
* Merge multiple routing signals for a set of candidate agents.
|
|
58
|
+
*
|
|
59
|
+
* Precedence rules:
|
|
60
|
+
* 1. User declaration (confidence 1.0) overrides everything
|
|
61
|
+
* 2. Static analysis (0.5-0.9) overrides behavioral
|
|
62
|
+
* 3. Behavioral co-usage (0.0-1.0 linear ramp) is lowest priority
|
|
63
|
+
*
|
|
64
|
+
* Deduplication: when declaration and analysis agree on the same agent,
|
|
65
|
+
* keep declaration, drop analysis (Skillsmith rule).
|
|
66
|
+
*/
|
|
67
|
+
merge(candidateAgentIds: string[], signals: {
|
|
68
|
+
/** User-declared preferred agent (confidence 1.0) */
|
|
69
|
+
userDeclaration?: string;
|
|
70
|
+
/** Static analysis scores per agent */
|
|
71
|
+
staticAnalysis: Map<string, {
|
|
72
|
+
confidence: number;
|
|
73
|
+
reason: string;
|
|
74
|
+
}>;
|
|
75
|
+
/** Behavioral co-execution data per agent */
|
|
76
|
+
behavioral: Map<string, CoExecutionStats>;
|
|
77
|
+
}): MergedAgentScore[];
|
|
78
|
+
}
|
|
79
|
+
/** Create a signal merger instance */
|
|
80
|
+
export declare function createSignalMerger(config?: Partial<SignalMergerConfig>): SignalMerger;
|
|
81
|
+
//# sourceMappingURL=signal-merger.d.ts.map
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-Signal Confidence Merger (Issue #342, Item 3)
|
|
3
|
+
*
|
|
4
|
+
* Combines three independent routing signals with clear precedence:
|
|
5
|
+
*
|
|
6
|
+
* | Signal | AQE Equivalent | Confidence | Precedence |
|
|
7
|
+
* |--------|---------------|------------|------------|
|
|
8
|
+
* | User declaration | preferredAgent in task context or CLAUDE.md | 1.0 | Overrides all |
|
|
9
|
+
* | Static analysis | Code pattern scanning (domain + capability match) | 0.5-0.9 | Overrides behavioral |
|
|
10
|
+
* | Behavioral co-usage | Learning DB: which agents succeed together | 0.0-1.0 (linear ramp) | Lowest |
|
|
11
|
+
*
|
|
12
|
+
* Key rules from Skillsmith:
|
|
13
|
+
* - When declaration and inference agree, keep declaration, drop inferred (dedup)
|
|
14
|
+
* - Behavioral confidence ramps linearly: min(1.0, success_count / 20)
|
|
15
|
+
*/
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Default Configuration
|
|
18
|
+
// ============================================================================
|
|
19
|
+
export const DEFAULT_SIGNAL_MERGER_CONFIG = {
|
|
20
|
+
staticAnalysisWeight: 0.7,
|
|
21
|
+
behavioralWeight: 0.3,
|
|
22
|
+
minBehavioralConfidence: 0.05, // At least 1 successful co-execution
|
|
23
|
+
};
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// Signal Merger
|
|
26
|
+
// ============================================================================
|
|
27
|
+
export class SignalMerger {
|
|
28
|
+
config;
|
|
29
|
+
constructor(config = {}) {
|
|
30
|
+
this.config = { ...DEFAULT_SIGNAL_MERGER_CONFIG, ...config };
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Merge multiple routing signals for a set of candidate agents.
|
|
34
|
+
*
|
|
35
|
+
* Precedence rules:
|
|
36
|
+
* 1. User declaration (confidence 1.0) overrides everything
|
|
37
|
+
* 2. Static analysis (0.5-0.9) overrides behavioral
|
|
38
|
+
* 3. Behavioral co-usage (0.0-1.0 linear ramp) is lowest priority
|
|
39
|
+
*
|
|
40
|
+
* Deduplication: when declaration and analysis agree on the same agent,
|
|
41
|
+
* keep declaration, drop analysis (Skillsmith rule).
|
|
42
|
+
*/
|
|
43
|
+
merge(candidateAgentIds, signals) {
|
|
44
|
+
const results = [];
|
|
45
|
+
for (const agentId of candidateAgentIds) {
|
|
46
|
+
const agentSignals = [];
|
|
47
|
+
let determinedBy = 'static-analysis';
|
|
48
|
+
let mergedConfidence;
|
|
49
|
+
// Signal 1: User declaration (highest precedence)
|
|
50
|
+
const isUserDeclared = signals.userDeclaration === agentId;
|
|
51
|
+
if (isUserDeclared) {
|
|
52
|
+
agentSignals.push({
|
|
53
|
+
source: 'user-declaration',
|
|
54
|
+
agentId,
|
|
55
|
+
confidence: 1.0,
|
|
56
|
+
reason: 'User explicitly selected this agent',
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
// Signal 2: Static analysis
|
|
60
|
+
const staticScore = signals.staticAnalysis.get(agentId);
|
|
61
|
+
if (staticScore) {
|
|
62
|
+
// Dedup: if user declared the same agent, don't add static signal
|
|
63
|
+
if (!isUserDeclared) {
|
|
64
|
+
agentSignals.push({
|
|
65
|
+
source: 'static-analysis',
|
|
66
|
+
agentId,
|
|
67
|
+
confidence: staticScore.confidence,
|
|
68
|
+
reason: staticScore.reason,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Signal 3: Behavioral co-execution
|
|
73
|
+
const behavioralStats = signals.behavioral.get(agentId);
|
|
74
|
+
if (behavioralStats && behavioralStats.behavioralConfidence >= this.config.minBehavioralConfidence) {
|
|
75
|
+
agentSignals.push({
|
|
76
|
+
source: 'behavioral',
|
|
77
|
+
agentId,
|
|
78
|
+
confidence: behavioralStats.behavioralConfidence,
|
|
79
|
+
reason: `${behavioralStats.successCount} successful co-executions (${(behavioralStats.successRate * 100).toFixed(0)}% success rate)`,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
// Merge using precedence rules
|
|
83
|
+
if (isUserDeclared) {
|
|
84
|
+
// User declaration overrides everything
|
|
85
|
+
mergedConfidence = 1.0;
|
|
86
|
+
determinedBy = 'user-declaration';
|
|
87
|
+
}
|
|
88
|
+
else if (staticScore && behavioralStats) {
|
|
89
|
+
// Both static and behavioral available -- weighted merge
|
|
90
|
+
const behavioralConf = behavioralStats.behavioralConfidence >= this.config.minBehavioralConfidence
|
|
91
|
+
? behavioralStats.behavioralConfidence * behavioralStats.successRate
|
|
92
|
+
: 0;
|
|
93
|
+
mergedConfidence =
|
|
94
|
+
this.config.staticAnalysisWeight * staticScore.confidence +
|
|
95
|
+
this.config.behavioralWeight * behavioralConf;
|
|
96
|
+
// Clamp to [0, 1]
|
|
97
|
+
mergedConfidence = Math.min(1.0, Math.max(0, mergedConfidence));
|
|
98
|
+
determinedBy = staticScore.confidence >= behavioralConf
|
|
99
|
+
? 'static-analysis'
|
|
100
|
+
: 'behavioral';
|
|
101
|
+
}
|
|
102
|
+
else if (staticScore) {
|
|
103
|
+
// Only static analysis
|
|
104
|
+
mergedConfidence = staticScore.confidence;
|
|
105
|
+
determinedBy = 'static-analysis';
|
|
106
|
+
}
|
|
107
|
+
else if (behavioralStats && behavioralStats.behavioralConfidence >= this.config.minBehavioralConfidence) {
|
|
108
|
+
// Only behavioral
|
|
109
|
+
mergedConfidence = behavioralStats.behavioralConfidence * behavioralStats.successRate;
|
|
110
|
+
determinedBy = 'behavioral';
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
// No signals -- baseline
|
|
114
|
+
mergedConfidence = 0;
|
|
115
|
+
determinedBy = 'static-analysis';
|
|
116
|
+
}
|
|
117
|
+
const signalsAgreed = agentSignals.length > 1 &&
|
|
118
|
+
agentSignals.every(s => s.agentId === agentSignals[0].agentId);
|
|
119
|
+
results.push({
|
|
120
|
+
agentId,
|
|
121
|
+
mergedConfidence,
|
|
122
|
+
signals: agentSignals,
|
|
123
|
+
determinedBy,
|
|
124
|
+
signalsAgreed,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
// Sort by merged confidence descending
|
|
128
|
+
results.sort((a, b) => b.mergedConfidence - a.mergedConfidence);
|
|
129
|
+
return results;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/** Create a signal merger instance */
|
|
133
|
+
export function createSignalMerger(config) {
|
|
134
|
+
return new SignalMerger(config);
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=signal-merger.js.map
|
package/dist/routing/types.d.ts
CHANGED
|
@@ -198,6 +198,7 @@ export interface AgentPerformanceMetrics {
|
|
|
198
198
|
/** Last updated */
|
|
199
199
|
readonly updatedAt: Date;
|
|
200
200
|
}
|
|
201
|
+
export type { DependencyType, AgentDependency, McpServerDependency, ModelRequirement, AgentDependencies } from './agent-dependency-graph.js';
|
|
201
202
|
/**
|
|
202
203
|
* Task router configuration
|
|
203
204
|
*/
|
|
@@ -31,6 +31,7 @@ import { createLLMError, } from '../interfaces';
|
|
|
31
31
|
import { CostTracker } from '../cost-tracker';
|
|
32
32
|
import { TokenMetricsCollector } from '../../../learning/token-tracker.js';
|
|
33
33
|
import { toError } from '../../error-utils.js';
|
|
34
|
+
import { backoffDelay } from '../retry.js';
|
|
34
35
|
/**
|
|
35
36
|
* Default Azure OpenAI configuration
|
|
36
37
|
*/
|
|
@@ -517,7 +518,7 @@ export class AzureOpenAIProvider {
|
|
|
517
518
|
// Retry on server errors and rate limiting
|
|
518
519
|
if (response.status >= 500 || response.status === 429) {
|
|
519
520
|
if (attempt < maxRetries - 1) {
|
|
520
|
-
const delay =
|
|
521
|
+
const delay = backoffDelay(attempt);
|
|
521
522
|
await this.sleep(delay);
|
|
522
523
|
continue;
|
|
523
524
|
}
|
|
@@ -528,7 +529,7 @@ export class AzureOpenAIProvider {
|
|
|
528
529
|
lastError = toError(error);
|
|
529
530
|
// Only retry on network/timeout errors
|
|
530
531
|
if (attempt < maxRetries - 1) {
|
|
531
|
-
const delay =
|
|
532
|
+
const delay = backoffDelay(attempt);
|
|
532
533
|
await this.sleep(delay);
|
|
533
534
|
}
|
|
534
535
|
}
|
|
@@ -15,6 +15,7 @@ import { createLLMError, } from '../interfaces';
|
|
|
15
15
|
import { CostTracker } from '../cost-tracker';
|
|
16
16
|
import { TokenMetricsCollector } from '../../../learning/token-tracker.js';
|
|
17
17
|
import { toError } from '../../error-utils.js';
|
|
18
|
+
import { backoffDelay } from '../retry.js';
|
|
18
19
|
/**
|
|
19
20
|
* Default Bedrock configuration
|
|
20
21
|
*/
|
|
@@ -353,7 +354,7 @@ export class BedrockProvider {
|
|
|
353
354
|
// Retry on server errors and throttling
|
|
354
355
|
if (response.status >= 500 || response.status === 429) {
|
|
355
356
|
if (attempt < maxRetries - 1) {
|
|
356
|
-
const delay =
|
|
357
|
+
const delay = backoffDelay(attempt);
|
|
357
358
|
await this.sleep(delay);
|
|
358
359
|
continue;
|
|
359
360
|
}
|
|
@@ -363,7 +364,7 @@ export class BedrockProvider {
|
|
|
363
364
|
catch (error) {
|
|
364
365
|
lastError = toError(error);
|
|
365
366
|
if (attempt < maxRetries - 1) {
|
|
366
|
-
const delay =
|
|
367
|
+
const delay = backoffDelay(attempt);
|
|
367
368
|
await this.sleep(delay);
|
|
368
369
|
}
|
|
369
370
|
}
|
|
@@ -9,6 +9,7 @@ import { createLLMError, } from '../interfaces';
|
|
|
9
9
|
import { CostTracker } from '../cost-tracker';
|
|
10
10
|
import { TokenMetricsCollector } from '../../../learning/token-tracker.js';
|
|
11
11
|
import { toError } from '../../error-utils.js';
|
|
12
|
+
import { backoffDelay } from '../retry.js';
|
|
12
13
|
/**
|
|
13
14
|
* Default Claude configuration
|
|
14
15
|
*/
|
|
@@ -375,7 +376,7 @@ export class ClaudeProvider {
|
|
|
375
376
|
// Retry on server errors and rate limiting
|
|
376
377
|
if (response.status >= 500 || response.status === 429) {
|
|
377
378
|
if (attempt < maxRetries - 1) {
|
|
378
|
-
const delay =
|
|
379
|
+
const delay = backoffDelay(attempt);
|
|
379
380
|
await this.sleep(delay);
|
|
380
381
|
continue;
|
|
381
382
|
}
|
|
@@ -386,7 +387,7 @@ export class ClaudeProvider {
|
|
|
386
387
|
lastError = toError(error);
|
|
387
388
|
// Only retry on network/timeout errors
|
|
388
389
|
if (attempt < maxRetries - 1) {
|
|
389
|
-
const delay =
|
|
390
|
+
const delay = backoffDelay(attempt);
|
|
390
391
|
await this.sleep(delay);
|
|
391
392
|
}
|
|
392
393
|
}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import { createLLMError, } from '../interfaces';
|
|
12
12
|
import { TokenMetricsCollector } from '../../../learning/token-tracker.js';
|
|
13
13
|
import { toError } from '../../error-utils.js';
|
|
14
|
+
import { backoffDelay } from '../retry.js';
|
|
14
15
|
import { safeJsonParse } from '../../safe-json.js';
|
|
15
16
|
/**
|
|
16
17
|
* Default Gemini configuration
|
|
@@ -582,7 +583,7 @@ export class GeminiProvider {
|
|
|
582
583
|
}
|
|
583
584
|
if (response.status >= 500 || response.status === 429) {
|
|
584
585
|
if (attempt < maxRetries - 1) {
|
|
585
|
-
const delay =
|
|
586
|
+
const delay = backoffDelay(attempt);
|
|
586
587
|
await this.sleep(delay);
|
|
587
588
|
continue;
|
|
588
589
|
}
|
|
@@ -592,7 +593,7 @@ export class GeminiProvider {
|
|
|
592
593
|
catch (error) {
|
|
593
594
|
lastError = toError(error);
|
|
594
595
|
if (attempt < maxRetries - 1) {
|
|
595
|
-
const delay =
|
|
596
|
+
const delay = backoffDelay(attempt);
|
|
596
597
|
await this.sleep(delay);
|
|
597
598
|
}
|
|
598
599
|
}
|
|
@@ -9,6 +9,7 @@ import { createLLMError, } from '../interfaces';
|
|
|
9
9
|
import { CostTracker } from '../cost-tracker';
|
|
10
10
|
import { TokenMetricsCollector } from '../../../learning/token-tracker.js';
|
|
11
11
|
import { toError } from '../../error-utils.js';
|
|
12
|
+
import { backoffDelay } from '../retry.js';
|
|
12
13
|
/**
|
|
13
14
|
* Default OpenAI configuration
|
|
14
15
|
*/
|
|
@@ -421,7 +422,7 @@ export class OpenAIProvider {
|
|
|
421
422
|
// Retry on server errors and rate limiting
|
|
422
423
|
if (response.status >= 500 || response.status === 429) {
|
|
423
424
|
if (attempt < maxRetries - 1) {
|
|
424
|
-
const delay =
|
|
425
|
+
const delay = backoffDelay(attempt);
|
|
425
426
|
await this.sleep(delay);
|
|
426
427
|
continue;
|
|
427
428
|
}
|
|
@@ -432,7 +433,7 @@ export class OpenAIProvider {
|
|
|
432
433
|
lastError = toError(error);
|
|
433
434
|
// Only retry on network/timeout errors
|
|
434
435
|
if (attempt < maxRetries - 1) {
|
|
435
|
-
const delay =
|
|
436
|
+
const delay = backoffDelay(attempt);
|
|
436
437
|
await this.sleep(delay);
|
|
437
438
|
}
|
|
438
439
|
}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
import { createLLMError, } from '../interfaces';
|
|
13
13
|
import { TokenMetricsCollector } from '../../../learning/token-tracker.js';
|
|
14
14
|
import { toError } from '../../error-utils.js';
|
|
15
|
+
import { backoffDelay } from '../retry.js';
|
|
15
16
|
import { safeJsonParse } from '../../safe-json.js';
|
|
16
17
|
/**
|
|
17
18
|
* Default OpenRouter configuration
|
|
@@ -618,7 +619,7 @@ export class OpenRouterProvider {
|
|
|
618
619
|
// Retry on server errors and rate limiting
|
|
619
620
|
if (response.status >= 500 || response.status === 429) {
|
|
620
621
|
if (attempt < maxRetries - 1) {
|
|
621
|
-
const delay =
|
|
622
|
+
const delay = backoffDelay(attempt);
|
|
622
623
|
await this.sleep(delay);
|
|
623
624
|
continue;
|
|
624
625
|
}
|
|
@@ -629,7 +630,7 @@ export class OpenRouterProvider {
|
|
|
629
630
|
lastError = toError(error);
|
|
630
631
|
// Only retry on network/timeout errors
|
|
631
632
|
if (attempt < maxRetries - 1) {
|
|
632
|
-
const delay =
|
|
633
|
+
const delay = backoffDelay(attempt);
|
|
633
634
|
await this.sleep(delay);
|
|
634
635
|
}
|
|
635
636
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared retry utilities for LLM providers.
|
|
3
|
+
* Extracts the common exponential backoff pattern used across all providers.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Compute exponential backoff delay: min(base * 2^attempt, max).
|
|
7
|
+
* Used by all LLM provider retry loops.
|
|
8
|
+
*/
|
|
9
|
+
export declare function backoffDelay(attempt: number, baseMs?: number, maxMs?: number): number;
|
|
10
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared retry utilities for LLM providers.
|
|
3
|
+
* Extracts the common exponential backoff pattern used across all providers.
|
|
4
|
+
*/
|
|
5
|
+
/** Default base delay (1 second) */
|
|
6
|
+
const DEFAULT_BASE_MS = 1000;
|
|
7
|
+
/** Default maximum delay cap (30 seconds) */
|
|
8
|
+
const DEFAULT_MAX_MS = 30000;
|
|
9
|
+
/**
|
|
10
|
+
* Compute exponential backoff delay: min(base * 2^attempt, max).
|
|
11
|
+
* Used by all LLM provider retry loops.
|
|
12
|
+
*/
|
|
13
|
+
export function backoffDelay(attempt, baseMs = DEFAULT_BASE_MS, maxMs = DEFAULT_MAX_MS) {
|
|
14
|
+
return Math.min(baseMs * Math.pow(2, attempt), maxMs);
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -109,7 +109,8 @@ export declare const DEFAULT_CATEGORY_MODELS: Record<AgentCategory, ModelPrefere
|
|
|
109
109
|
*/
|
|
110
110
|
export declare const AGENT_CATEGORY_MAP: Record<string, AgentCategory>;
|
|
111
111
|
/**
|
|
112
|
-
* Default capability requirements for each agent category
|
|
112
|
+
* Default capability requirements for each agent category.
|
|
113
|
+
* Categories map to one of 4 presets, with per-category overrides where needed.
|
|
113
114
|
*/
|
|
114
115
|
export declare const DEFAULT_CATEGORY_CAPABILITIES: Record<AgentCategory, AgentCapabilityRequirements>;
|
|
115
116
|
/**
|