@gotza02/seq-thinking 1.1.0

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 (106) hide show
  1. package/README.md +149 -0
  2. package/SYSTEM_INSTRUCTIONS.md +50 -0
  3. package/agents_test.log +15 -0
  4. package/dist/__tests__/agents.test.d.ts +2 -0
  5. package/dist/__tests__/agents.test.d.ts.map +1 -0
  6. package/dist/__tests__/agents.test.js +673 -0
  7. package/dist/__tests__/agents.test.js.map +1 -0
  8. package/dist/__tests__/mcp-server.test.d.ts +2 -0
  9. package/dist/__tests__/mcp-server.test.d.ts.map +1 -0
  10. package/dist/__tests__/mcp-server.test.js +315 -0
  11. package/dist/__tests__/mcp-server.test.js.map +1 -0
  12. package/dist/__tests__/sequential-thinking.test.d.ts +2 -0
  13. package/dist/__tests__/sequential-thinking.test.d.ts.map +1 -0
  14. package/dist/__tests__/sequential-thinking.test.js +545 -0
  15. package/dist/__tests__/sequential-thinking.test.js.map +1 -0
  16. package/dist/__tests__/swarm-coordinator.test.d.ts +2 -0
  17. package/dist/__tests__/swarm-coordinator.test.d.ts.map +1 -0
  18. package/dist/__tests__/swarm-coordinator.test.js +606 -0
  19. package/dist/__tests__/swarm-coordinator.test.js.map +1 -0
  20. package/dist/__tests__/types.test.d.ts +2 -0
  21. package/dist/__tests__/types.test.d.ts.map +1 -0
  22. package/dist/__tests__/types.test.js +741 -0
  23. package/dist/__tests__/types.test.js.map +1 -0
  24. package/dist/__tests__/utils.test.d.ts +2 -0
  25. package/dist/__tests__/utils.test.d.ts.map +1 -0
  26. package/dist/__tests__/utils.test.js +264 -0
  27. package/dist/__tests__/utils.test.js.map +1 -0
  28. package/dist/agents/base-agent.d.ts +126 -0
  29. package/dist/agents/base-agent.d.ts.map +1 -0
  30. package/dist/agents/base-agent.js +214 -0
  31. package/dist/agents/base-agent.js.map +1 -0
  32. package/dist/agents/critic-agent.d.ts +134 -0
  33. package/dist/agents/critic-agent.d.ts.map +1 -0
  34. package/dist/agents/critic-agent.js +484 -0
  35. package/dist/agents/critic-agent.js.map +1 -0
  36. package/dist/agents/index.d.ts +11 -0
  37. package/dist/agents/index.d.ts.map +1 -0
  38. package/dist/agents/index.js +11 -0
  39. package/dist/agents/index.js.map +1 -0
  40. package/dist/agents/meta-reasoning-agent.d.ts +143 -0
  41. package/dist/agents/meta-reasoning-agent.d.ts.map +1 -0
  42. package/dist/agents/meta-reasoning-agent.js +532 -0
  43. package/dist/agents/meta-reasoning-agent.js.map +1 -0
  44. package/dist/agents/reasoner-agent.d.ts +75 -0
  45. package/dist/agents/reasoner-agent.d.ts.map +1 -0
  46. package/dist/agents/reasoner-agent.js +226 -0
  47. package/dist/agents/reasoner-agent.js.map +1 -0
  48. package/dist/agents/synthesizer-agent.d.ts +174 -0
  49. package/dist/agents/synthesizer-agent.d.ts.map +1 -0
  50. package/dist/agents/synthesizer-agent.js +583 -0
  51. package/dist/agents/synthesizer-agent.js.map +1 -0
  52. package/dist/index.d.ts +21 -0
  53. package/dist/index.d.ts.map +1 -0
  54. package/dist/index.js +27 -0
  55. package/dist/index.js.map +1 -0
  56. package/dist/mcp-server.d.ts +823 -0
  57. package/dist/mcp-server.d.ts.map +1 -0
  58. package/dist/mcp-server.js +377 -0
  59. package/dist/mcp-server.js.map +1 -0
  60. package/dist/sequential-thinking.d.ts +91 -0
  61. package/dist/sequential-thinking.d.ts.map +1 -0
  62. package/dist/sequential-thinking.js +540 -0
  63. package/dist/sequential-thinking.js.map +1 -0
  64. package/dist/swarm-coordinator.d.ts +188 -0
  65. package/dist/swarm-coordinator.d.ts.map +1 -0
  66. package/dist/swarm-coordinator.js +627 -0
  67. package/dist/swarm-coordinator.js.map +1 -0
  68. package/dist/types/index.d.ts +806 -0
  69. package/dist/types/index.d.ts.map +1 -0
  70. package/dist/types/index.js +279 -0
  71. package/dist/types/index.js.map +1 -0
  72. package/dist/utils/index.d.ts +421 -0
  73. package/dist/utils/index.d.ts.map +1 -0
  74. package/dist/utils/index.js +864 -0
  75. package/dist/utils/index.js.map +1 -0
  76. package/dist/utils/llm-adapter.d.ts +23 -0
  77. package/dist/utils/llm-adapter.d.ts.map +1 -0
  78. package/dist/utils/llm-adapter.js +68 -0
  79. package/dist/utils/llm-adapter.js.map +1 -0
  80. package/dist/utils/persistence.d.ts +33 -0
  81. package/dist/utils/persistence.d.ts.map +1 -0
  82. package/dist/utils/persistence.js +108 -0
  83. package/dist/utils/persistence.js.map +1 -0
  84. package/package.json +41 -0
  85. package/src/__tests__/agents.test.ts +858 -0
  86. package/src/__tests__/mcp-server.test.ts +380 -0
  87. package/src/__tests__/sequential-thinking.test.ts +687 -0
  88. package/src/__tests__/swarm-coordinator.test.ts +903 -0
  89. package/src/__tests__/types.test.ts +839 -0
  90. package/src/__tests__/utils.test.ts +322 -0
  91. package/src/agents/base-agent.ts +285 -0
  92. package/src/agents/critic-agent.ts +582 -0
  93. package/src/agents/index.ts +11 -0
  94. package/src/agents/meta-reasoning-agent.ts +672 -0
  95. package/src/agents/reasoner-agent.ts +312 -0
  96. package/src/agents/synthesizer-agent.ts +758 -0
  97. package/src/index.ts +118 -0
  98. package/src/mcp-server.ts +387 -0
  99. package/src/sequential-thinking.ts +560 -0
  100. package/src/swarm-coordinator.ts +744 -0
  101. package/src/types/index.ts +915 -0
  102. package/src/utils/index.ts +1004 -0
  103. package/src/utils/llm-adapter.ts +76 -0
  104. package/src/utils/persistence.ts +108 -0
  105. package/test_output.log +0 -0
  106. package/tsconfig.json +21 -0
@@ -0,0 +1,758 @@
1
+ /**
2
+ * Synthesizer Agent Implementation
3
+ * @module agents/synthesizer-agent
4
+ * @version 1.0.0
5
+ */
6
+
7
+ import { BaseAgent } from './base-agent.js';
8
+ import {
9
+ AgentType,
10
+ SynthesizerType,
11
+ type Task,
12
+ type TaskResult,
13
+ type AgentCapability
14
+ } from '../types/index.js';
15
+
16
+ /**
17
+ * Synthesis input
18
+ */
19
+ interface SynthesisInput {
20
+ outputs: Array<{
21
+ agentId: string;
22
+ output: unknown;
23
+ confidence: number;
24
+ }>;
25
+ context?: unknown;
26
+ }
27
+
28
+ /**
29
+ * Synthesis result
30
+ */
31
+ interface Synthesis {
32
+ synthesizedOutput: unknown;
33
+ confidence: number;
34
+ contributingAgents: string[];
35
+ synthesisMethod: string;
36
+ consensusLevel?: number;
37
+ dissentPoints?: unknown[];
38
+ }
39
+
40
+ /**
41
+ * Synthesizer agent that combines multiple agent outputs
42
+ */
43
+ export class SynthesizerAgent extends BaseAgent {
44
+ /** Synthesizer type */
45
+ private synthesizerType: SynthesizerType;
46
+
47
+ /**
48
+ * Create a new synthesizer agent
49
+ * @param config - Agent configuration
50
+ */
51
+ constructor(config: {
52
+ name: string;
53
+ synthesizerType?: SynthesizerType;
54
+ capabilities?: AgentCapability[];
55
+ }) {
56
+ const defaultCapabilities: AgentCapability[] = [
57
+ {
58
+ name: 'consensus_building',
59
+ description: 'Build consensus from multiple outputs',
60
+ confidence: 0.85,
61
+ performanceMetrics: { tasksCompleted: 0, averageQuality: 0, averageTimeMs: 0 }
62
+ },
63
+ {
64
+ name: 'conflict_resolution',
65
+ description: 'Resolve conflicts between outputs',
66
+ confidence: 0.8,
67
+ performanceMetrics: { tasksCompleted: 0, averageQuality: 0, averageTimeMs: 0 }
68
+ },
69
+ {
70
+ name: 'creative_synthesis',
71
+ description: 'Create creative combinations',
72
+ confidence: 0.75,
73
+ performanceMetrics: { tasksCompleted: 0, averageQuality: 0, averageTimeMs: 0 }
74
+ },
75
+ {
76
+ name: 'integration',
77
+ description: 'Integrate multiple perspectives',
78
+ confidence: 0.85,
79
+ performanceMetrics: { tasksCompleted: 0, averageQuality: 0, averageTimeMs: 0 }
80
+ }
81
+ ];
82
+
83
+ super({
84
+ name: config.name,
85
+ type: AgentType.SYNTHESIZER,
86
+ subtype: config.synthesizerType || SynthesizerType.CONSENSUS,
87
+ capabilities: config.capabilities || defaultCapabilities,
88
+ maxConcurrentTasks: 3,
89
+ confidenceThreshold: 0.7
90
+ });
91
+
92
+ this.synthesizerType = config.synthesizerType || SynthesizerType.CONSENSUS;
93
+ }
94
+
95
+ /**
96
+ * Get agent type
97
+ * @returns Agent type
98
+ */
99
+ getType(): string {
100
+ return AgentType.SYNTHESIZER;
101
+ }
102
+
103
+ /**
104
+ * Get agent capabilities
105
+ * @returns Array of capabilities
106
+ */
107
+ getCapabilities(): AgentCapability[] {
108
+ return this.config.capabilities;
109
+ }
110
+
111
+ /**
112
+ * Process a task - synthesize inputs
113
+ * @param task - Task to process
114
+ * @returns Task result
115
+ */
116
+ async process(task: Task): Promise<TaskResult> {
117
+ const startTime = Date.now();
118
+ const input = task.input as SynthesisInput;
119
+
120
+ let result: Synthesis;
121
+
122
+ switch (this.synthesizerType) {
123
+ case SynthesizerType.CONSENSUS:
124
+ result = await this.buildConsensus(input);
125
+ break;
126
+ case SynthesizerType.CREATIVE:
127
+ result = await this.creativeSynthesis(input);
128
+ break;
129
+ case SynthesizerType.CONFLICT_RESOLUTION:
130
+ result = await this.resolveConflicts(input);
131
+ break;
132
+ default:
133
+ result = await this.buildConsensus(input);
134
+ }
135
+
136
+ return this.createTaskResult(
137
+ task.id,
138
+ result,
139
+ result.confidence,
140
+ Date.now() - startTime,
141
+ {
142
+ reasoningSteps: input.outputs.length,
143
+ intermediateResults: input.outputs.map(o => o.output)
144
+ }
145
+ );
146
+ }
147
+
148
+ /**
149
+ * Build consensus from multiple outputs
150
+ * @param input - Synthesis input
151
+ * @returns Synthesis result
152
+ */
153
+ private async buildConsensus(input: SynthesisInput): Promise<Synthesis> {
154
+ const { outputs } = input;
155
+
156
+ if (outputs.length === 0) {
157
+ return {
158
+ synthesizedOutput: null,
159
+ confidence: 0,
160
+ contributingAgents: [],
161
+ synthesisMethod: 'consensus'
162
+ };
163
+ }
164
+
165
+ if (outputs.length === 1) {
166
+ return {
167
+ synthesizedOutput: outputs[0].output,
168
+ confidence: outputs[0].confidence,
169
+ contributingAgents: [outputs[0].agentId],
170
+ synthesisMethod: 'consensus'
171
+ };
172
+ }
173
+
174
+ // Extract key points from each output
175
+ const keyPoints = outputs.map(o => this.extractKeyPoints(o.output));
176
+
177
+ // Find consensus points (common across multiple outputs)
178
+ const consensusPoints = this.findConsensusPoints(keyPoints);
179
+
180
+ // Find points of divergence
181
+ const divergencePoints = this.findDivergencePoints(keyPoints);
182
+
183
+ // Weight by confidence
184
+ const weightedConsensus = this.applyConfidenceWeights(consensusPoints, outputs);
185
+
186
+ // Calculate consensus level
187
+ const consensusLevel = consensusPoints.length / Math.max(...keyPoints.map(kp => kp.length));
188
+
189
+ // Generate unified output
190
+ const unified = this.generateUnifiedOutput(weightedConsensus, divergencePoints);
191
+
192
+ // Calculate overall confidence
193
+ const avgConfidence = outputs.reduce((sum, o) => sum + o.confidence, 0) / outputs.length;
194
+ const consensusBoost = consensusLevel * 0.1;
195
+
196
+ return {
197
+ synthesizedOutput: unified,
198
+ confidence: Math.min(1, avgConfidence + consensusBoost),
199
+ contributingAgents: outputs.map(o => o.agentId),
200
+ synthesisMethod: 'consensus',
201
+ consensusLevel,
202
+ dissentPoints: divergencePoints
203
+ };
204
+ }
205
+
206
+ /**
207
+ * Creative synthesis
208
+ * @param input - Synthesis input
209
+ * @returns Synthesis result
210
+ */
211
+ private async creativeSynthesis(input: SynthesisInput): Promise<Synthesis> {
212
+ const { outputs } = input;
213
+
214
+ if (outputs.length === 0) {
215
+ return {
216
+ synthesizedOutput: null,
217
+ confidence: 0,
218
+ contributingAgents: [],
219
+ synthesisMethod: 'creative_combination'
220
+ };
221
+ }
222
+
223
+ // Extract creative elements
224
+ const creativeElements = outputs.map(o => this.extractCreativeElements(o.output));
225
+
226
+ // Find unexpected connections
227
+ const connections = this.findUnexpectedConnections(creativeElements);
228
+
229
+ // Generate novel combinations
230
+ const combinations = this.generateNovelCombinations(creativeElements, connections);
231
+
232
+ // Create creative output
233
+ const creativeOutput = {
234
+ combinations,
235
+ connections,
236
+ originalElements: creativeElements,
237
+ novelInsights: this.generateNovelInsights(combinations)
238
+ };
239
+
240
+ // Calculate confidence based on diversity and novelty
241
+ const diversityScore = this.calculateDiversity(creativeElements);
242
+ const noveltyScore = connections.length > 0 ? 0.8 : 0.5;
243
+ const confidence = (diversityScore + noveltyScore) / 2;
244
+
245
+ return {
246
+ synthesizedOutput: creativeOutput,
247
+ confidence,
248
+ contributingAgents: outputs.map(o => o.agentId),
249
+ synthesisMethod: 'creative_combination'
250
+ };
251
+ }
252
+
253
+ /**
254
+ * Resolve conflicts between outputs
255
+ * @param input - Synthesis input
256
+ * @returns Synthesis result
257
+ */
258
+ private async resolveConflicts(input: SynthesisInput): Promise<Synthesis> {
259
+ const { outputs } = input;
260
+
261
+ if (outputs.length === 0) {
262
+ return {
263
+ synthesizedOutput: null,
264
+ confidence: 0,
265
+ contributingAgents: [],
266
+ synthesisMethod: 'conflict_resolution'
267
+ };
268
+ }
269
+
270
+ if (outputs.length === 1) {
271
+ return {
272
+ synthesizedOutput: outputs[0].output,
273
+ confidence: outputs[0].confidence,
274
+ contributingAgents: [outputs[0].agentId],
275
+ synthesisMethod: 'conflict_resolution'
276
+ };
277
+ }
278
+
279
+ // Identify conflicts
280
+ const conflicts = this.identifyConflicts(outputs);
281
+
282
+ if (conflicts.length === 0) {
283
+ // No conflicts, use consensus
284
+ return this.buildConsensus(input);
285
+ }
286
+
287
+ // Resolve each conflict
288
+ const resolutions = conflicts.map(conflict => ({
289
+ conflict,
290
+ resolution: this.resolveConflict(conflict, outputs)
291
+ }));
292
+
293
+ // Merge resolved conflicts with non-conflicting content
294
+ const finalOutput = this.mergeResolutions(outputs, resolutions);
295
+
296
+ // Calculate confidence
297
+ const avgConfidence = outputs.reduce((sum, o) => sum + o.confidence, 0) / outputs.length;
298
+ const resolutionQuality = resolutions.length > 0
299
+ ? resolutions.reduce((sum, r) => sum + r.resolution.confidence, 0) / resolutions.length
300
+ : 1;
301
+
302
+ return {
303
+ synthesizedOutput: finalOutput,
304
+ confidence: (avgConfidence + resolutionQuality) / 2,
305
+ contributingAgents: outputs.map(o => o.agentId),
306
+ synthesisMethod: 'conflict_resolution',
307
+ dissentPoints: conflicts.map(c => c.description)
308
+ };
309
+ }
310
+
311
+ // ============================================================================
312
+ // Helper Methods
313
+ // ============================================================================
314
+
315
+ /**
316
+ * Extract key points from output
317
+ * @param output - Output to extract from
318
+ * @returns Array of key points
319
+ */
320
+ private extractKeyPoints(output: unknown): string[] {
321
+ if (typeof output === 'string') {
322
+ return output.split(/[.!?]+/).filter(s => s.trim().length > 10);
323
+ }
324
+
325
+ if (output && typeof output === 'object') {
326
+ const obj = output as Record<string, unknown>;
327
+
328
+ if ('conclusion' in obj && typeof obj.conclusion === 'string') {
329
+ return [obj.conclusion];
330
+ }
331
+
332
+ if ('keyPoints' in obj && Array.isArray(obj.keyPoints)) {
333
+ return obj.keyPoints as string[];
334
+ }
335
+
336
+ return [JSON.stringify(output)];
337
+ }
338
+
339
+ return [String(output)];
340
+ }
341
+
342
+ /**
343
+ * Find consensus points
344
+ * @param keyPointsArray - Array of key points arrays
345
+ * @returns Consensus points
346
+ */
347
+ private findConsensusPoints(keyPointsArray: string[][]): string[] {
348
+ if (keyPointsArray.length === 0) return [];
349
+ if (keyPointsArray.length === 1) return keyPointsArray[0];
350
+
351
+ const consensus: string[] = [];
352
+ const firstSet = keyPointsArray[0];
353
+
354
+ for (const point of firstSet) {
355
+ const normalizedPoint = this.normalizePoint(point);
356
+ let matchCount = 1;
357
+
358
+ for (let i = 1; i < keyPointsArray.length; i++) {
359
+ const otherSet = keyPointsArray[i];
360
+ const hasMatch = otherSet.some(otherPoint =>
361
+ this.pointsAreSimilar(normalizedPoint, this.normalizePoint(otherPoint))
362
+ );
363
+ if (hasMatch) matchCount++;
364
+ }
365
+
366
+ // Point is in consensus if it appears in majority
367
+ if (matchCount > keyPointsArray.length / 2) {
368
+ consensus.push(point);
369
+ }
370
+ }
371
+
372
+ return consensus;
373
+ }
374
+
375
+ /**
376
+ * Find divergence points
377
+ * @param keyPointsArray - Array of key points arrays
378
+ * @returns Divergence points
379
+ */
380
+ private findDivergencePoints(keyPointsArray: string[][]): string[] {
381
+ if (keyPointsArray.length <= 1) return [];
382
+
383
+ const allPoints = keyPointsArray.flat();
384
+ const uniquePoints = [...new Set(allPoints.map(p => this.normalizePoint(p)))];
385
+ const divergence: string[] = [];
386
+
387
+ for (const point of uniquePoints) {
388
+ let matchCount = 0;
389
+
390
+ for (const pointSet of keyPointsArray) {
391
+ const hasMatch = pointSet.some(p =>
392
+ this.pointsAreSimilar(point, this.normalizePoint(p))
393
+ );
394
+ if (hasMatch) matchCount++;
395
+ }
396
+
397
+ // Point diverges if not in majority
398
+ if (matchCount <= keyPointsArray.length / 2) {
399
+ const original = allPoints.find(p => this.normalizePoint(p) === point);
400
+ if (original) divergence.push(original);
401
+ }
402
+ }
403
+
404
+ return divergence;
405
+ }
406
+
407
+ /**
408
+ * Normalize a point for comparison
409
+ * @param point - Point to normalize
410
+ * @returns Normalized point
411
+ */
412
+ private normalizePoint(point: string): string {
413
+ return point.toLowerCase().trim().replace(/\s+/g, ' ');
414
+ }
415
+
416
+ /**
417
+ * Check if two points are similar
418
+ * @param a - First point
419
+ * @param b - Second point
420
+ * @returns True if similar
421
+ */
422
+ private pointsAreSimilar(a: string, b: string): boolean {
423
+ // Simple similarity check
424
+ if (a === b) return true;
425
+
426
+ const wordsA = new Set(a.split(' '));
427
+ const wordsB = new Set(b.split(' '));
428
+ const intersection = [...wordsA].filter(w => wordsB.has(w));
429
+ const union = new Set([...wordsA, ...wordsB]);
430
+
431
+ return union.size > 0 && intersection.length / union.size > 0.6;
432
+ }
433
+
434
+ /**
435
+ * Apply confidence weights to points
436
+ * @param points - Points to weight
437
+ * @param outputs - Outputs with confidence
438
+ * @returns Weighted points
439
+ */
440
+ private applyConfidenceWeights(
441
+ points: string[],
442
+ outputs: Array<{ confidence: number }>
443
+ ): Array<{ point: string; weight: number }> {
444
+ const avgConfidence = outputs.reduce((sum, o) => sum + o.confidence, 0) / outputs.length;
445
+
446
+ return points.map(point => ({
447
+ point,
448
+ weight: avgConfidence
449
+ }));
450
+ }
451
+
452
+ /**
453
+ * Generate unified output
454
+ * @param weightedPoints - Weighted points
455
+ * @param divergencePoints - Divergence points
456
+ * @returns Unified output
457
+ */
458
+ private generateUnifiedOutput(
459
+ weightedPoints: Array<{ point: string; weight: number }>,
460
+ divergencePoints: string[]
461
+ ): Record<string, unknown> {
462
+ return {
463
+ consensus: weightedPoints.map(wp => wp.point),
464
+ consensusWeights: weightedPoints.map(wp => wp.weight),
465
+ pointsOfDivergence: divergencePoints,
466
+ summary: `Consensus reached on ${weightedPoints.length} points with ${divergencePoints.length} points of divergence`
467
+ };
468
+ }
469
+
470
+ /**
471
+ * Extract creative elements
472
+ * @param output - Output to extract from
473
+ * @returns Creative elements
474
+ */
475
+ private extractCreativeElements(output: unknown): string[] {
476
+ if (typeof output === 'string') {
477
+ // Extract novel phrases, metaphors, etc.
478
+ return output.split(/[.!?]+/).filter(s => s.trim().length > 5);
479
+ }
480
+
481
+ if (output && typeof output === 'object') {
482
+ const obj = output as Record<string, unknown>;
483
+
484
+ if ('creativeElements' in obj && Array.isArray(obj.creativeElements)) {
485
+ return obj.creativeElements as string[];
486
+ }
487
+
488
+ if ('ideas' in obj && Array.isArray(obj.ideas)) {
489
+ return obj.ideas as string[];
490
+ }
491
+ }
492
+
493
+ return [String(output)];
494
+ }
495
+
496
+ /**
497
+ * Find unexpected connections
498
+ * @param elementsArray - Array of element arrays
499
+ * @returns Connections
500
+ */
501
+ private findUnexpectedConnections(elementsArray: string[][]): Array<{
502
+ elements: [string, string];
503
+ connection: string;
504
+ }> {
505
+ const connections: Array<{ elements: [string, string]; connection: string }> = [];
506
+
507
+ // Compare elements from different sources
508
+ for (let i = 0; i < elementsArray.length; i++) {
509
+ for (let j = i + 1; j < elementsArray.length; j++) {
510
+ const setA = elementsArray[i];
511
+ const setB = elementsArray[j];
512
+
513
+ for (const elemA of setA) {
514
+ for (const elemB of setB) {
515
+ const connection = this.findConnection(elemA, elemB);
516
+ if (connection) {
517
+ connections.push({
518
+ elements: [elemA, elemB],
519
+ connection
520
+ });
521
+ }
522
+ }
523
+ }
524
+ }
525
+ }
526
+
527
+ return connections;
528
+ }
529
+
530
+ /**
531
+ * Find connection between two elements
532
+ * @param a - First element
533
+ * @param b - Second element
534
+ * @returns Connection description or null
535
+ */
536
+ private findConnection(a: string, b: string): string | null {
537
+ const wordsA = new Set(a.toLowerCase().split(/\s+/));
538
+ const wordsB = new Set(b.toLowerCase().split(/\s+/));
539
+ const common = [...wordsA].filter(w => wordsB.has(w) && w.length > 3);
540
+
541
+ if (common.length > 0) {
542
+ return `Connected through: ${common.join(', ')}`;
543
+ }
544
+
545
+ return null;
546
+ }
547
+
548
+ /**
549
+ * Generate novel combinations
550
+ * @param elementsArray - Array of element arrays
551
+ * @param connections - Connections
552
+ * @returns Combinations
553
+ */
554
+ private generateNovelCombinations(
555
+ elementsArray: string[][],
556
+ connections: Array<{ elements: [string, string]; connection: string }>
557
+ ): string[] {
558
+ const combinations: string[] = [];
559
+
560
+ for (const connection of connections) {
561
+ const [elemA, elemB] = connection.elements;
562
+ combinations.push(`Combining "${elemA.substring(0, 30)}..." with "${elemB.substring(0, 30)}..."`);
563
+ }
564
+
565
+ // Cross-pollinate ideas
566
+ for (let i = 0; i < elementsArray.length && i < 3; i++) {
567
+ for (let j = i + 1; j < elementsArray.length && j < 3; j++) {
568
+ const elemA = elementsArray[i][0];
569
+ const elemB = elementsArray[j][0];
570
+ if (elemA && elemB) {
571
+ combinations.push(`Cross: ${elemA.substring(0, 20)}... + ${elemB.substring(0, 20)}...`);
572
+ }
573
+ }
574
+ }
575
+
576
+ return combinations;
577
+ }
578
+
579
+ /**
580
+ * Generate novel insights
581
+ * @param combinations - Combinations
582
+ * @returns Insights
583
+ */
584
+ private generateNovelInsights(combinations: string[]): string[] {
585
+ return combinations.map((combo, i) =>
586
+ `Insight ${i + 1}: ${combo} suggests a new approach`
587
+ );
588
+ }
589
+
590
+ /**
591
+ * Calculate diversity score
592
+ * @param elementsArray - Array of element arrays
593
+ * @returns Diversity score (0-1)
594
+ */
595
+ private calculateDiversity(elementsArray: string[][]): number {
596
+ const allElements = elementsArray.flat();
597
+ const uniqueElements = new Set(allElements);
598
+
599
+ if (allElements.length === 0) return 0;
600
+
601
+ return uniqueElements.size / allElements.length;
602
+ }
603
+
604
+ /**
605
+ * Identify conflicts
606
+ * @param outputs - Outputs to analyze
607
+ * @returns Conflicts
608
+ */
609
+ private identifyConflicts(outputs: Array<{ agentId: string; output: unknown }>): Array<{
610
+ type: string;
611
+ description: string;
612
+ involvedAgents: string[];
613
+ }> {
614
+ const conflicts: Array<{
615
+ type: string;
616
+ description: string;
617
+ involvedAgents: string[];
618
+ }> = [];
619
+
620
+ // Check for contradictory conclusions
621
+ const conclusions: Array<{ agentId: string; conclusion: string }> = [];
622
+
623
+ for (const output of outputs) {
624
+ const conclusion = this.extractConclusion(output.output);
625
+ if (conclusion) {
626
+ conclusions.push({ agentId: output.agentId, conclusion });
627
+ }
628
+ }
629
+
630
+ // Find contradictions
631
+ for (let i = 0; i < conclusions.length; i++) {
632
+ for (let j = i + 1; j < conclusions.length; j++) {
633
+ const a = conclusions[i];
634
+ const b = conclusions[j];
635
+
636
+ if (this.areContradictory(a.conclusion, b.conclusion)) {
637
+ conflicts.push({
638
+ type: 'contradiction',
639
+ description: `Contradictory conclusions: "${a.conclusion.substring(0, 30)}..." vs "${b.conclusion.substring(0, 30)}..."`,
640
+ involvedAgents: [a.agentId, b.agentId]
641
+ });
642
+ }
643
+ }
644
+ }
645
+
646
+ return conflicts;
647
+ }
648
+
649
+ /**
650
+ * Extract conclusion from output
651
+ * @param output - Output to extract from
652
+ * @returns Conclusion string or null
653
+ */
654
+ private extractConclusion(output: unknown): string | null {
655
+ if (typeof output === 'string') return output;
656
+
657
+ if (output && typeof output === 'object') {
658
+ const obj = output as Record<string, unknown>;
659
+
660
+ if ('conclusion' in obj && typeof obj.conclusion === 'string') {
661
+ return obj.conclusion;
662
+ }
663
+ }
664
+
665
+ return null;
666
+ }
667
+
668
+ /**
669
+ * Check if two conclusions are contradictory
670
+ * @param a - First conclusion
671
+ * @param b - Second conclusion
672
+ * @returns True if contradictory
673
+ */
674
+ private areContradictory(a: string, b: string): boolean {
675
+ const lowerA = a.toLowerCase();
676
+ const lowerB = b.toLowerCase();
677
+
678
+ // Check for direct opposites
679
+ const oppositePatterns = [
680
+ { pos: /\b(is|are|was|were)\b/gi, neg: /\b(is not|are not|was not|were not)\b/gi },
681
+ { pos: /\bshould\b/gi, neg: /\bshould not\b/gi },
682
+ { pos: /\bcan\b/gi, neg: /\bcannot\b/gi }
683
+ ];
684
+
685
+ for (const { pos, neg } of oppositePatterns) {
686
+ const aHasPos = pos.test(lowerA);
687
+ const aHasNeg = neg.test(lowerA);
688
+ const bHasPos = pos.test(lowerB);
689
+ const bHasNeg = neg.test(lowerB);
690
+
691
+ if ((aHasPos && bHasNeg) || (aHasNeg && bHasPos)) {
692
+ return true;
693
+ }
694
+ }
695
+
696
+ return false;
697
+ }
698
+
699
+ /**
700
+ * Resolve a conflict
701
+ * @param conflict - Conflict to resolve
702
+ * @param outputs - All outputs
703
+ * @returns Resolution
704
+ */
705
+ private resolveConflict(
706
+ conflict: { type: string; involvedAgents: string[] },
707
+ outputs: Array<{ agentId: string; output: unknown; confidence: number }>
708
+ ): { resolution: unknown; confidence: number } {
709
+ // Get conflicting outputs
710
+ const conflictingOutputs = outputs.filter(o =>
711
+ conflict.involvedAgents.includes(o.agentId)
712
+ );
713
+
714
+ // Select based on confidence
715
+ const best = conflictingOutputs.reduce((max, o) =>
716
+ o.confidence > max.confidence ? o : max,
717
+ conflictingOutputs[0]
718
+ );
719
+
720
+ if (!best) {
721
+ return { resolution: null, confidence: 0 };
722
+ }
723
+
724
+ return {
725
+ resolution: best.output,
726
+ confidence: best.confidence
727
+ };
728
+ }
729
+
730
+ /**
731
+ * Merge resolutions with non-conflicting content
732
+ * @param outputs - All outputs
733
+ * @param resolutions - Resolutions
734
+ * @returns Merged output
735
+ */
736
+ private mergeResolutions(
737
+ outputs: Array<{ agentId: string; output: unknown }>,
738
+ resolutions: Array<{ conflict: { involvedAgents: string[] }; resolution: { resolution: unknown } }>
739
+ ): Record<string, unknown> {
740
+ const merged: Record<string, unknown> = {
741
+ resolvedConflicts: resolutions.length,
742
+ agentOutputs: {}
743
+ };
744
+
745
+ // Add all outputs
746
+ for (const output of outputs) {
747
+ (merged.agentOutputs as Record<string, unknown>)[output.agentId] = output.output;
748
+ }
749
+
750
+ // Add resolutions
751
+ merged.resolutions = resolutions.map(r => ({
752
+ conflict: r.conflict,
753
+ selectedResolution: r.resolution.resolution
754
+ }));
755
+
756
+ return merged;
757
+ }
758
+ }