@sparkleideas/neural 3.5.2-patch.1

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.
Files changed (122) hide show
  1. package/README.md +260 -0
  2. package/__tests__/README.md +235 -0
  3. package/__tests__/algorithms.test.ts +582 -0
  4. package/__tests__/patterns.test.ts +549 -0
  5. package/__tests__/sona.test.ts +445 -0
  6. package/docs/SONA_INTEGRATION.md +460 -0
  7. package/docs/SONA_QUICKSTART.md +168 -0
  8. package/examples/sona-usage.ts +318 -0
  9. package/package.json +23 -0
  10. package/src/algorithms/a2c.d.ts +86 -0
  11. package/src/algorithms/a2c.d.ts.map +1 -0
  12. package/src/algorithms/a2c.js +361 -0
  13. package/src/algorithms/a2c.js.map +1 -0
  14. package/src/algorithms/a2c.ts +478 -0
  15. package/src/algorithms/curiosity.d.ts +82 -0
  16. package/src/algorithms/curiosity.d.ts.map +1 -0
  17. package/src/algorithms/curiosity.js +392 -0
  18. package/src/algorithms/curiosity.js.map +1 -0
  19. package/src/algorithms/curiosity.ts +509 -0
  20. package/src/algorithms/decision-transformer.d.ts +82 -0
  21. package/src/algorithms/decision-transformer.d.ts.map +1 -0
  22. package/src/algorithms/decision-transformer.js +415 -0
  23. package/src/algorithms/decision-transformer.js.map +1 -0
  24. package/src/algorithms/decision-transformer.ts +521 -0
  25. package/src/algorithms/dqn.d.ts +72 -0
  26. package/src/algorithms/dqn.d.ts.map +1 -0
  27. package/src/algorithms/dqn.js +303 -0
  28. package/src/algorithms/dqn.js.map +1 -0
  29. package/src/algorithms/dqn.ts +382 -0
  30. package/src/algorithms/index.d.ts +32 -0
  31. package/src/algorithms/index.d.ts.map +1 -0
  32. package/src/algorithms/index.js +74 -0
  33. package/src/algorithms/index.js.map +1 -0
  34. package/src/algorithms/index.ts +122 -0
  35. package/src/algorithms/ppo.d.ts +72 -0
  36. package/src/algorithms/ppo.d.ts.map +1 -0
  37. package/src/algorithms/ppo.js +331 -0
  38. package/src/algorithms/ppo.js.map +1 -0
  39. package/src/algorithms/ppo.ts +429 -0
  40. package/src/algorithms/q-learning.d.ts +77 -0
  41. package/src/algorithms/q-learning.d.ts.map +1 -0
  42. package/src/algorithms/q-learning.js +259 -0
  43. package/src/algorithms/q-learning.js.map +1 -0
  44. package/src/algorithms/q-learning.ts +333 -0
  45. package/src/algorithms/sarsa.d.ts +82 -0
  46. package/src/algorithms/sarsa.d.ts.map +1 -0
  47. package/src/algorithms/sarsa.js +297 -0
  48. package/src/algorithms/sarsa.js.map +1 -0
  49. package/src/algorithms/sarsa.ts +383 -0
  50. package/src/algorithms/tmp.json +0 -0
  51. package/src/application/index.ts +11 -0
  52. package/src/application/services/neural-application-service.ts +217 -0
  53. package/src/domain/entities/pattern.ts +169 -0
  54. package/src/domain/index.ts +18 -0
  55. package/src/domain/services/learning-service.ts +256 -0
  56. package/src/index.d.ts +118 -0
  57. package/src/index.d.ts.map +1 -0
  58. package/src/index.js +201 -0
  59. package/src/index.js.map +1 -0
  60. package/src/index.ts +363 -0
  61. package/src/modes/balanced.d.ts +60 -0
  62. package/src/modes/balanced.d.ts.map +1 -0
  63. package/src/modes/balanced.js +234 -0
  64. package/src/modes/balanced.js.map +1 -0
  65. package/src/modes/balanced.ts +299 -0
  66. package/src/modes/base.ts +163 -0
  67. package/src/modes/batch.d.ts +82 -0
  68. package/src/modes/batch.d.ts.map +1 -0
  69. package/src/modes/batch.js +316 -0
  70. package/src/modes/batch.js.map +1 -0
  71. package/src/modes/batch.ts +434 -0
  72. package/src/modes/edge.d.ts +85 -0
  73. package/src/modes/edge.d.ts.map +1 -0
  74. package/src/modes/edge.js +310 -0
  75. package/src/modes/edge.js.map +1 -0
  76. package/src/modes/edge.ts +409 -0
  77. package/src/modes/index.d.ts +55 -0
  78. package/src/modes/index.d.ts.map +1 -0
  79. package/src/modes/index.js +83 -0
  80. package/src/modes/index.js.map +1 -0
  81. package/src/modes/index.ts +16 -0
  82. package/src/modes/real-time.d.ts +58 -0
  83. package/src/modes/real-time.d.ts.map +1 -0
  84. package/src/modes/real-time.js +196 -0
  85. package/src/modes/real-time.js.map +1 -0
  86. package/src/modes/real-time.ts +257 -0
  87. package/src/modes/research.d.ts +79 -0
  88. package/src/modes/research.d.ts.map +1 -0
  89. package/src/modes/research.js +389 -0
  90. package/src/modes/research.js.map +1 -0
  91. package/src/modes/research.ts +486 -0
  92. package/src/modes/tmp.json +0 -0
  93. package/src/pattern-learner.d.ts +117 -0
  94. package/src/pattern-learner.d.ts.map +1 -0
  95. package/src/pattern-learner.js +603 -0
  96. package/src/pattern-learner.js.map +1 -0
  97. package/src/pattern-learner.ts +757 -0
  98. package/src/reasoning-bank.d.ts +259 -0
  99. package/src/reasoning-bank.d.ts.map +1 -0
  100. package/src/reasoning-bank.js +993 -0
  101. package/src/reasoning-bank.js.map +1 -0
  102. package/src/reasoning-bank.ts +1279 -0
  103. package/src/reasoningbank-adapter.ts +697 -0
  104. package/src/sona-integration.d.ts +168 -0
  105. package/src/sona-integration.d.ts.map +1 -0
  106. package/src/sona-integration.js +316 -0
  107. package/src/sona-integration.js.map +1 -0
  108. package/src/sona-integration.ts +432 -0
  109. package/src/sona-manager.d.ts +147 -0
  110. package/src/sona-manager.d.ts.map +1 -0
  111. package/src/sona-manager.js +695 -0
  112. package/src/sona-manager.js.map +1 -0
  113. package/src/sona-manager.ts +835 -0
  114. package/src/tmp.json +0 -0
  115. package/src/types.d.ts +431 -0
  116. package/src/types.d.ts.map +1 -0
  117. package/src/types.js +11 -0
  118. package/src/types.js.map +1 -0
  119. package/src/types.ts +590 -0
  120. package/tmp.json +0 -0
  121. package/tsconfig.json +9 -0
  122. package/vitest.config.ts +19 -0
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Neural Application Layer - Public Exports
3
+ *
4
+ * @module v3/neural/application
5
+ */
6
+
7
+ export {
8
+ NeuralApplicationService,
9
+ type TrainingSessionResult,
10
+ type NeuralMetrics,
11
+ } from './services/neural-application-service.js';
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Neural Application Service - Application Layer
3
+ *
4
+ * Orchestrates neural learning operations.
5
+ *
6
+ * @module v3/neural/application/services
7
+ */
8
+
9
+ import { Pattern, PatternType } from '../../domain/entities/pattern.js';
10
+ import { LearningDomainService, Trajectory, LearningResult, RouteRecommendation } from '../../domain/services/learning-service.js';
11
+
12
+ /**
13
+ * Training session result
14
+ */
15
+ export interface TrainingSessionResult {
16
+ trajectoriesProcessed: number;
17
+ patternsExtracted: number;
18
+ patternsUpdated: number;
19
+ averageConfidenceChange: number;
20
+ duration: number;
21
+ }
22
+
23
+ /**
24
+ * Neural metrics
25
+ */
26
+ export interface NeuralMetrics {
27
+ totalPatterns: number;
28
+ patternsByType: Record<PatternType, number>;
29
+ averageConfidence: number;
30
+ reliablePatterns: number;
31
+ totalSuccesses: number;
32
+ totalFailures: number;
33
+ }
34
+
35
+ /**
36
+ * Neural Application Service
37
+ */
38
+ export class NeuralApplicationService {
39
+ private readonly learningService: LearningDomainService;
40
+
41
+ constructor() {
42
+ this.learningService = new LearningDomainService();
43
+ }
44
+
45
+ // ============================================================================
46
+ // Learning Operations
47
+ // ============================================================================
48
+
49
+ /**
50
+ * Learn from a single trajectory
51
+ */
52
+ learn(trajectory: Trajectory): LearningResult {
53
+ return this.learningService.updatePatterns(trajectory);
54
+ }
55
+
56
+ /**
57
+ * Train on batch of trajectories
58
+ */
59
+ train(trajectories: Trajectory[]): TrainingSessionResult {
60
+ const start = Date.now();
61
+ let totalPatternsExtracted = 0;
62
+ let totalPatternsUpdated = 0;
63
+ let totalConfidenceChange = 0;
64
+
65
+ for (const trajectory of trajectories) {
66
+ const result = this.learningService.updatePatterns(trajectory);
67
+ totalPatternsExtracted += result.patternsExtracted;
68
+ totalPatternsUpdated += result.patternsUpdated;
69
+ totalConfidenceChange += result.confidenceChange;
70
+ }
71
+
72
+ return {
73
+ trajectoriesProcessed: trajectories.length,
74
+ patternsExtracted: totalPatternsExtracted,
75
+ patternsUpdated: totalPatternsUpdated,
76
+ averageConfidenceChange: trajectories.length > 0 ? totalConfidenceChange / trajectories.length : 0,
77
+ duration: Date.now() - start,
78
+ };
79
+ }
80
+
81
+ // ============================================================================
82
+ // Routing
83
+ // ============================================================================
84
+
85
+ /**
86
+ * Get route recommendation for task
87
+ */
88
+ route(taskDescription: string): RouteRecommendation {
89
+ return this.learningService.getRouteRecommendation(taskDescription);
90
+ }
91
+
92
+ /**
93
+ * Explain routing decision
94
+ */
95
+ explain(taskDescription: string): {
96
+ recommendation: RouteRecommendation;
97
+ matchingPatterns: Pattern[];
98
+ reasoning: string[];
99
+ } {
100
+ const recommendation = this.route(taskDescription);
101
+ const matchingPatterns = this.learningService
102
+ .getPatternsByType('task-routing')
103
+ .filter((p) => p.matches(taskDescription));
104
+
105
+ const reasoning: string[] = [];
106
+ if (matchingPatterns.length > 0) {
107
+ reasoning.push(`Found ${matchingPatterns.length} matching patterns`);
108
+ for (const p of matchingPatterns.slice(0, 3)) {
109
+ reasoning.push(`- Pattern "${p.name}": ${p.successRate.toFixed(2)} success rate, ${p.confidence.toFixed(2)} confidence`);
110
+ }
111
+ } else {
112
+ reasoning.push('No matching patterns found, using keyword-based routing');
113
+ }
114
+ reasoning.push(`Recommended: ${recommendation.agentRole} (${(recommendation.confidence * 100).toFixed(0)}% confidence)`);
115
+
116
+ return {
117
+ recommendation,
118
+ matchingPatterns,
119
+ reasoning,
120
+ };
121
+ }
122
+
123
+ // ============================================================================
124
+ // Pattern Management
125
+ // ============================================================================
126
+
127
+ /**
128
+ * Get all patterns
129
+ */
130
+ getPatterns(): Pattern[] {
131
+ return this.learningService.getPatterns();
132
+ }
133
+
134
+ /**
135
+ * Get patterns by type
136
+ */
137
+ getPatternsByType(type: PatternType): Pattern[] {
138
+ return this.learningService.getPatternsByType(type);
139
+ }
140
+
141
+ /**
142
+ * Add custom pattern
143
+ */
144
+ addPattern(props: {
145
+ type: PatternType;
146
+ name: string;
147
+ description: string;
148
+ condition: string;
149
+ action: string;
150
+ confidence?: number;
151
+ }): Pattern {
152
+ const pattern = Pattern.create({
153
+ type: props.type,
154
+ name: props.name,
155
+ description: props.description,
156
+ condition: props.condition,
157
+ action: props.action,
158
+ confidence: props.confidence ?? 0.5,
159
+ });
160
+ this.learningService.addPattern(pattern);
161
+ return pattern;
162
+ }
163
+
164
+ /**
165
+ * Remove pattern
166
+ */
167
+ removePattern(id: string): boolean {
168
+ return this.learningService.removePattern(id);
169
+ }
170
+
171
+ /**
172
+ * Consolidate patterns
173
+ */
174
+ consolidate(minConfidence?: number): { merged: number; pruned: number } {
175
+ return this.learningService.consolidate(minConfidence);
176
+ }
177
+
178
+ // ============================================================================
179
+ // Metrics
180
+ // ============================================================================
181
+
182
+ /**
183
+ * Get neural metrics
184
+ */
185
+ getMetrics(): NeuralMetrics {
186
+ const patterns = this.learningService.getPatterns();
187
+
188
+ const patternsByType: Record<PatternType, number> = {
189
+ 'task-routing': 0,
190
+ 'error-recovery': 0,
191
+ optimization: 0,
192
+ learning: 0,
193
+ };
194
+
195
+ let totalConfidence = 0;
196
+ let reliablePatterns = 0;
197
+ let totalSuccesses = 0;
198
+ let totalFailures = 0;
199
+
200
+ for (const pattern of patterns) {
201
+ patternsByType[pattern.type]++;
202
+ totalConfidence += pattern.confidence;
203
+ if (pattern.isReliable()) reliablePatterns++;
204
+ totalSuccesses += pattern.successCount;
205
+ totalFailures += pattern.failureCount;
206
+ }
207
+
208
+ return {
209
+ totalPatterns: patterns.length,
210
+ patternsByType,
211
+ averageConfidence: patterns.length > 0 ? totalConfidence / patterns.length : 0,
212
+ reliablePatterns,
213
+ totalSuccesses,
214
+ totalFailures,
215
+ };
216
+ }
217
+ }
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Pattern Entity - Domain Layer
3
+ *
4
+ * Represents a learned pattern for intelligent routing and optimization.
5
+ *
6
+ * @module v3/neural/domain/entities
7
+ */
8
+
9
+ import { randomUUID } from 'crypto';
10
+
11
+ /**
12
+ * Pattern type
13
+ */
14
+ export type PatternType = 'task-routing' | 'error-recovery' | 'optimization' | 'learning';
15
+
16
+ /**
17
+ * Pattern properties
18
+ */
19
+ export interface PatternProps {
20
+ id?: string;
21
+ type: PatternType;
22
+ name: string;
23
+ description: string;
24
+ condition: string;
25
+ action: string;
26
+ confidence: number;
27
+ successCount?: number;
28
+ failureCount?: number;
29
+ metadata?: Record<string, unknown>;
30
+ createdAt?: Date;
31
+ updatedAt?: Date;
32
+ lastMatchedAt?: Date;
33
+ }
34
+
35
+ /**
36
+ * Pattern Entity
37
+ */
38
+ export class Pattern {
39
+ private _id: string;
40
+ private _type: PatternType;
41
+ private _name: string;
42
+ private _description: string;
43
+ private _condition: string;
44
+ private _action: string;
45
+ private _confidence: number;
46
+ private _successCount: number;
47
+ private _failureCount: number;
48
+ private _metadata: Record<string, unknown>;
49
+ private _createdAt: Date;
50
+ private _updatedAt: Date;
51
+ private _lastMatchedAt?: Date;
52
+
53
+ private constructor(props: PatternProps) {
54
+ const now = new Date();
55
+ this._id = props.id ?? randomUUID();
56
+ this._type = props.type;
57
+ this._name = props.name;
58
+ this._description = props.description;
59
+ this._condition = props.condition;
60
+ this._action = props.action;
61
+ this._confidence = props.confidence;
62
+ this._successCount = props.successCount ?? 0;
63
+ this._failureCount = props.failureCount ?? 0;
64
+ this._metadata = props.metadata ?? {};
65
+ this._createdAt = props.createdAt ?? now;
66
+ this._updatedAt = props.updatedAt ?? now;
67
+ this._lastMatchedAt = props.lastMatchedAt;
68
+ }
69
+
70
+ static create(props: PatternProps): Pattern {
71
+ return new Pattern(props);
72
+ }
73
+
74
+ static fromPersistence(props: PatternProps): Pattern {
75
+ return new Pattern(props);
76
+ }
77
+
78
+ get id(): string { return this._id; }
79
+ get type(): PatternType { return this._type; }
80
+ get name(): string { return this._name; }
81
+ get description(): string { return this._description; }
82
+ get condition(): string { return this._condition; }
83
+ get action(): string { return this._action; }
84
+ get confidence(): number { return this._confidence; }
85
+ get successCount(): number { return this._successCount; }
86
+ get failureCount(): number { return this._failureCount; }
87
+ get metadata(): Record<string, unknown> { return { ...this._metadata }; }
88
+ get createdAt(): Date { return new Date(this._createdAt); }
89
+ get updatedAt(): Date { return new Date(this._updatedAt); }
90
+ get lastMatchedAt(): Date | undefined { return this._lastMatchedAt ? new Date(this._lastMatchedAt) : undefined; }
91
+
92
+ /**
93
+ * Calculate success rate
94
+ */
95
+ get successRate(): number {
96
+ const total = this._successCount + this._failureCount;
97
+ return total > 0 ? this._successCount / total : 0;
98
+ }
99
+
100
+ /**
101
+ * Record successful match
102
+ */
103
+ recordSuccess(): void {
104
+ this._successCount++;
105
+ this._confidence = this.calculateConfidence();
106
+ this._lastMatchedAt = new Date();
107
+ this._updatedAt = new Date();
108
+ }
109
+
110
+ /**
111
+ * Record failed match
112
+ */
113
+ recordFailure(): void {
114
+ this._failureCount++;
115
+ this._confidence = this.calculateConfidence();
116
+ this._lastMatchedAt = new Date();
117
+ this._updatedAt = new Date();
118
+ }
119
+
120
+ /**
121
+ * Calculate confidence based on success rate
122
+ */
123
+ private calculateConfidence(): number {
124
+ const total = this._successCount + this._failureCount;
125
+ if (total < 5) return this._confidence; // Not enough data
126
+
127
+ const newConfidence = this.successRate;
128
+ // Weighted average with existing confidence
129
+ return this._confidence * 0.3 + newConfidence * 0.7;
130
+ }
131
+
132
+ /**
133
+ * Check if pattern matches input
134
+ */
135
+ matches(input: string): boolean {
136
+ try {
137
+ const regex = new RegExp(this._condition, 'i');
138
+ return regex.test(input);
139
+ } catch {
140
+ return input.toLowerCase().includes(this._condition.toLowerCase());
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Check if pattern is reliable (high confidence, sufficient data)
146
+ */
147
+ isReliable(): boolean {
148
+ const total = this._successCount + this._failureCount;
149
+ return total >= 10 && this._confidence >= 0.7;
150
+ }
151
+
152
+ toPersistence(): Record<string, unknown> {
153
+ return {
154
+ id: this._id,
155
+ type: this._type,
156
+ name: this._name,
157
+ description: this._description,
158
+ condition: this._condition,
159
+ action: this._action,
160
+ confidence: this._confidence,
161
+ successCount: this._successCount,
162
+ failureCount: this._failureCount,
163
+ metadata: this._metadata,
164
+ createdAt: this._createdAt.toISOString(),
165
+ updatedAt: this._updatedAt.toISOString(),
166
+ lastMatchedAt: this._lastMatchedAt?.toISOString(),
167
+ };
168
+ }
169
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Neural Domain Layer - Public Exports
3
+ *
4
+ * @module v3/neural/domain
5
+ */
6
+
7
+ export {
8
+ Pattern,
9
+ type PatternType,
10
+ type PatternProps,
11
+ } from './entities/pattern.js';
12
+
13
+ export {
14
+ LearningDomainService,
15
+ type Trajectory,
16
+ type LearningResult,
17
+ type RouteRecommendation,
18
+ } from './services/learning-service.js';
@@ -0,0 +1,256 @@
1
+ /**
2
+ * Learning Domain Service - Domain Layer
3
+ *
4
+ * Contains learning logic for pattern recognition and optimization.
5
+ *
6
+ * @module v3/neural/domain/services
7
+ */
8
+
9
+ import { Pattern, PatternType } from '../entities/pattern.js';
10
+
11
+ /**
12
+ * Learning trajectory
13
+ */
14
+ export interface Trajectory {
15
+ id: string;
16
+ input: string;
17
+ actions: string[];
18
+ outcome: 'success' | 'failure' | 'partial';
19
+ reward: number;
20
+ metadata?: Record<string, unknown>;
21
+ timestamp: Date;
22
+ }
23
+
24
+ /**
25
+ * Learning result
26
+ */
27
+ export interface LearningResult {
28
+ patternsExtracted: number;
29
+ patternsUpdated: number;
30
+ confidenceChange: number;
31
+ }
32
+
33
+ /**
34
+ * Route recommendation
35
+ */
36
+ export interface RouteRecommendation {
37
+ agentRole: string;
38
+ confidence: number;
39
+ reasoning: string;
40
+ alternates: Array<{ role: string; confidence: number }>;
41
+ }
42
+
43
+ /**
44
+ * Learning Domain Service
45
+ */
46
+ export class LearningDomainService {
47
+ private patterns: Map<string, Pattern> = new Map();
48
+
49
+ /**
50
+ * Extract patterns from trajectory
51
+ */
52
+ extractPatterns(trajectory: Trajectory): Pattern[] {
53
+ const extracted: Pattern[] = [];
54
+
55
+ // Extract task-routing pattern
56
+ if (trajectory.outcome === 'success') {
57
+ const taskPattern = Pattern.create({
58
+ type: 'task-routing',
59
+ name: `route_${trajectory.id}`,
60
+ description: `Learned from successful trajectory`,
61
+ condition: this.extractCondition(trajectory.input),
62
+ action: trajectory.actions[0] ?? 'default',
63
+ confidence: 0.6 + trajectory.reward * 0.2,
64
+ metadata: { source: trajectory.id },
65
+ });
66
+ extracted.push(taskPattern);
67
+ }
68
+
69
+ // Extract error recovery pattern if failure
70
+ if (trajectory.outcome === 'failure' && trajectory.actions.length > 1) {
71
+ const lastAction = trajectory.actions[trajectory.actions.length - 1];
72
+ const recoveryPattern = Pattern.create({
73
+ type: 'error-recovery',
74
+ name: `recovery_${trajectory.id}`,
75
+ description: `Recovery action from failure`,
76
+ condition: `error:${trajectory.actions[0]}`,
77
+ action: lastAction,
78
+ confidence: 0.5,
79
+ metadata: { source: trajectory.id },
80
+ });
81
+ extracted.push(recoveryPattern);
82
+ }
83
+
84
+ return extracted;
85
+ }
86
+
87
+ /**
88
+ * Update patterns based on trajectory outcome
89
+ */
90
+ updatePatterns(trajectory: Trajectory): LearningResult {
91
+ let patternsUpdated = 0;
92
+ let totalConfidenceChange = 0;
93
+
94
+ for (const pattern of this.patterns.values()) {
95
+ if (pattern.matches(trajectory.input)) {
96
+ const oldConfidence = pattern.confidence;
97
+
98
+ if (trajectory.outcome === 'success') {
99
+ pattern.recordSuccess();
100
+ } else {
101
+ pattern.recordFailure();
102
+ }
103
+
104
+ totalConfidenceChange += pattern.confidence - oldConfidence;
105
+ patternsUpdated++;
106
+ }
107
+ }
108
+
109
+ // Extract and add new patterns
110
+ const newPatterns = this.extractPatterns(trajectory);
111
+ for (const pattern of newPatterns) {
112
+ this.patterns.set(pattern.id, pattern);
113
+ }
114
+
115
+ return {
116
+ patternsExtracted: newPatterns.length,
117
+ patternsUpdated,
118
+ confidenceChange: totalConfidenceChange,
119
+ };
120
+ }
121
+
122
+ /**
123
+ * Get route recommendation for task
124
+ */
125
+ getRouteRecommendation(taskDescription: string): RouteRecommendation {
126
+ const matchingPatterns: Array<{ pattern: Pattern; score: number }> = [];
127
+
128
+ for (const pattern of this.patterns.values()) {
129
+ if (pattern.type !== 'task-routing') continue;
130
+
131
+ if (pattern.matches(taskDescription)) {
132
+ const score = pattern.confidence * (pattern.isReliable() ? 1.2 : 1.0);
133
+ matchingPatterns.push({ pattern, score });
134
+ }
135
+ }
136
+
137
+ // Sort by score
138
+ matchingPatterns.sort((a, b) => b.score - a.score);
139
+
140
+ if (matchingPatterns.length === 0) {
141
+ return this.getDefaultRecommendation(taskDescription);
142
+ }
143
+
144
+ const best = matchingPatterns[0];
145
+ const alternates = matchingPatterns.slice(1, 4).map((m) => ({
146
+ role: m.pattern.action,
147
+ confidence: m.score,
148
+ }));
149
+
150
+ return {
151
+ agentRole: best.pattern.action,
152
+ confidence: best.score,
153
+ reasoning: `Based on pattern "${best.pattern.name}" with ${best.pattern.successCount} successes`,
154
+ alternates,
155
+ };
156
+ }
157
+
158
+ /**
159
+ * Get default recommendation based on keywords
160
+ */
161
+ private getDefaultRecommendation(task: string): RouteRecommendation {
162
+ const taskLower = task.toLowerCase();
163
+ const keywordMap: Record<string, string> = {
164
+ code: 'coder',
165
+ implement: 'coder',
166
+ write: 'coder',
167
+ test: 'tester',
168
+ review: 'reviewer',
169
+ plan: 'planner',
170
+ research: 'researcher',
171
+ security: 'security-architect',
172
+ performance: 'performance-engineer',
173
+ memory: 'memory-specialist',
174
+ };
175
+
176
+ for (const [keyword, role] of Object.entries(keywordMap)) {
177
+ if (taskLower.includes(keyword)) {
178
+ return {
179
+ agentRole: role,
180
+ confidence: 0.5,
181
+ reasoning: `Keyword match: "${keyword}"`,
182
+ alternates: [],
183
+ };
184
+ }
185
+ }
186
+
187
+ return {
188
+ agentRole: 'coder',
189
+ confidence: 0.3,
190
+ reasoning: 'Default fallback',
191
+ alternates: [],
192
+ };
193
+ }
194
+
195
+ /**
196
+ * Extract condition from input
197
+ */
198
+ private extractCondition(input: string): string {
199
+ // Extract key terms from input
200
+ const words = input.toLowerCase().split(/\s+/);
201
+ const keyWords = words.filter((w) => w.length > 4).slice(0, 5);
202
+ return keyWords.join('|');
203
+ }
204
+
205
+ /**
206
+ * Consolidate patterns (merge duplicates, prune low-confidence)
207
+ */
208
+ consolidate(minConfidence: number = 0.3): { merged: number; pruned: number } {
209
+ let merged = 0;
210
+ let pruned = 0;
211
+
212
+ const toRemove: string[] = [];
213
+
214
+ for (const [id, pattern] of this.patterns) {
215
+ // Prune low confidence patterns with enough data
216
+ if (pattern.confidence < minConfidence && pattern.successCount + pattern.failureCount > 20) {
217
+ toRemove.push(id);
218
+ pruned++;
219
+ }
220
+ }
221
+
222
+ for (const id of toRemove) {
223
+ this.patterns.delete(id);
224
+ }
225
+
226
+ return { merged, pruned };
227
+ }
228
+
229
+ /**
230
+ * Get all patterns
231
+ */
232
+ getPatterns(): Pattern[] {
233
+ return Array.from(this.patterns.values());
234
+ }
235
+
236
+ /**
237
+ * Get patterns by type
238
+ */
239
+ getPatternsByType(type: PatternType): Pattern[] {
240
+ return Array.from(this.patterns.values()).filter((p) => p.type === type);
241
+ }
242
+
243
+ /**
244
+ * Add pattern
245
+ */
246
+ addPattern(pattern: Pattern): void {
247
+ this.patterns.set(pattern.id, pattern);
248
+ }
249
+
250
+ /**
251
+ * Remove pattern
252
+ */
253
+ removePattern(id: string): boolean {
254
+ return this.patterns.delete(id);
255
+ }
256
+ }