@gotza02/seq-thinking 1.1.5 → 1.1.7
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 +4 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/mcp-server.js +1 -1
- package/package.json +9 -3
- package/agents_test.log +0 -15
- package/data/agents/1770106504306-dljh9ef.json +0 -68
- package/data/agents/1770106504310-4oarrst.json +0 -58
- package/data/agents/1770106540588-pvitt55.json +0 -68
- package/data/agents/1770106540595-z2ya871.json +0 -58
- package/data/agents/1770106710890-0e2naq1.json +0 -68
- package/data/agents/1770106710893-r076yxx.json +0 -58
- package/data/agents/1770109212161-4ybd0i7.json +0 -68
- package/data/agents/1770109212166-gkhya8h.json +0 -58
- package/data/agents/1770117726716-lrnm415.json +0 -68
- package/data/agents/1770117726719-w6hsf3v.json +0 -58
- package/data/sessions/1770100622009-5afiuyv.json +0 -499
- package/data/sessions/1770106504312-75zk750.json +0 -107
- package/data/sessions/1770106540597-z8e8soo.json +0 -150
- package/data/sessions/1770106710894-0kxgy5x.json +0 -150
- package/data/sessions/1770109212169-zpddeb9.json +0 -150
- package/data/sessions/1770117726720-frcwj99.json +0 -150
- package/real_world_test.log +0 -200
- package/real_world_test_dynamic.log +0 -184
- package/real_world_test_real.log +0 -184
- package/src/__tests__/agents.test.ts +0 -858
- package/src/__tests__/mcp-server.test.ts +0 -380
- package/src/__tests__/sequential-thinking.test.ts +0 -687
- package/src/__tests__/swarm-coordinator.test.ts +0 -903
- package/src/__tests__/types.test.ts +0 -839
- package/src/__tests__/utils.test.ts +0 -322
- package/src/agents/base-agent.ts +0 -288
- package/src/agents/critic-agent.ts +0 -582
- package/src/agents/index.ts +0 -11
- package/src/agents/meta-reasoning-agent.ts +0 -314
- package/src/agents/reasoner-agent.ts +0 -312
- package/src/agents/synthesizer-agent.ts +0 -641
- package/src/index.ts +0 -118
- package/src/mcp-server.ts +0 -391
- package/src/real_world_test.ts +0 -89
- package/src/sequential-thinking.ts +0 -614
- package/src/swarm-coordinator.ts +0 -772
- package/src/types/index.ts +0 -915
- package/src/utils/index.ts +0 -1004
- package/src/utils/llm-adapter.ts +0 -110
- package/src/utils/logger.ts +0 -56
- package/src/utils/persistence.ts +0 -109
- package/test_output.log +0 -0
- package/tsconfig.json +0 -21
|
@@ -1,641 +0,0 @@
|
|
|
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
|
-
import { LLMAdapter } from '../utils/llm-adapter.js';
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Synthesis input
|
|
19
|
-
*/
|
|
20
|
-
interface SynthesisInput {
|
|
21
|
-
outputs: Array<{
|
|
22
|
-
agentId: string;
|
|
23
|
-
output: unknown;
|
|
24
|
-
confidence: number;
|
|
25
|
-
}>;
|
|
26
|
-
context?: unknown;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Synthesis result
|
|
31
|
-
*/
|
|
32
|
-
interface Synthesis {
|
|
33
|
-
synthesizedOutput: unknown;
|
|
34
|
-
confidence: number;
|
|
35
|
-
contributingAgents: string[];
|
|
36
|
-
synthesisMethod: string;
|
|
37
|
-
consensusLevel?: number;
|
|
38
|
-
dissentPoints?: unknown[];
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Synthesizer agent that combines multiple agent outputs
|
|
43
|
-
*/
|
|
44
|
-
export class SynthesizerAgent extends BaseAgent {
|
|
45
|
-
/** Synthesizer type */
|
|
46
|
-
private synthesizerType: SynthesizerType;
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Create a new synthesizer agent
|
|
50
|
-
* @param config - Agent configuration
|
|
51
|
-
*/
|
|
52
|
-
constructor(config: {
|
|
53
|
-
name: string;
|
|
54
|
-
synthesizerType?: SynthesizerType;
|
|
55
|
-
capabilities?: AgentCapability[];
|
|
56
|
-
}) {
|
|
57
|
-
const defaultCapabilities: AgentCapability[] = [
|
|
58
|
-
{
|
|
59
|
-
name: 'consensus_building',
|
|
60
|
-
description: 'Build consensus from multiple outputs',
|
|
61
|
-
confidence: 0.9,
|
|
62
|
-
performanceMetrics: { tasksCompleted: 0, averageQuality: 0, averageTimeMs: 0 }
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
name: 'conflict_resolution',
|
|
66
|
-
description: 'Resolve conflicts between outputs',
|
|
67
|
-
confidence: 0.85,
|
|
68
|
-
performanceMetrics: { tasksCompleted: 0, averageQuality: 0, averageTimeMs: 0 }
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
name: 'creative_synthesis',
|
|
72
|
-
description: 'Create creative combinations',
|
|
73
|
-
confidence: 0.8,
|
|
74
|
-
performanceMetrics: { tasksCompleted: 0, averageQuality: 0, averageTimeMs: 0 }
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
name: 'integration',
|
|
78
|
-
description: 'Integrate multiple perspectives',
|
|
79
|
-
confidence: 0.9,
|
|
80
|
-
performanceMetrics: { tasksCompleted: 0, averageQuality: 0, averageTimeMs: 0 }
|
|
81
|
-
}
|
|
82
|
-
];
|
|
83
|
-
|
|
84
|
-
super({
|
|
85
|
-
name: config.name,
|
|
86
|
-
type: AgentType.SYNTHESIZER,
|
|
87
|
-
subtype: config.synthesizerType || SynthesizerType.CONSENSUS,
|
|
88
|
-
capabilities: config.capabilities || defaultCapabilities,
|
|
89
|
-
maxConcurrentTasks: 3,
|
|
90
|
-
confidenceThreshold: 0.7
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
this.synthesizerType = config.synthesizerType || SynthesizerType.CONSENSUS;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Get agent type
|
|
98
|
-
* @returns Agent type
|
|
99
|
-
*/
|
|
100
|
-
getType(): string {
|
|
101
|
-
return AgentType.SYNTHESIZER;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Get agent capabilities
|
|
106
|
-
* @returns Array of capabilities
|
|
107
|
-
*/
|
|
108
|
-
getCapabilities(): AgentCapability[] {
|
|
109
|
-
return this.config.capabilities;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Process a task - synthesize inputs using LLM
|
|
114
|
-
* @param task - Task to process
|
|
115
|
-
* @returns Task result
|
|
116
|
-
*/
|
|
117
|
-
async process(task: Task): Promise<TaskResult> {
|
|
118
|
-
const startTime = Date.now();
|
|
119
|
-
const input = task.input as SynthesisInput;
|
|
120
|
-
|
|
121
|
-
if (!input.outputs || input.outputs.length === 0) {
|
|
122
|
-
return this.createTaskResult(task.id, { error: 'No outputs to synthesize' }, 0, Date.now() - startTime);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const contextStr = input.context ? `Context: ${JSON.stringify(input.context)}\n` : '';
|
|
126
|
-
const outputsStr = input.outputs.map((o, i) => `Agent ${o.agentId} (Confidence: ${o.confidence}):\n${JSON.stringify(o.output)}`).join('\n\n');
|
|
127
|
-
|
|
128
|
-
const provider = (task.context as any)?.modelProvider;
|
|
129
|
-
|
|
130
|
-
let prompt = '';
|
|
131
|
-
let systemPrompt = 'You are an expert synthesizer agent in a swarm intelligence system. Your goal is to combine multiple agent outputs into a coherent, high-quality result.';
|
|
132
|
-
|
|
133
|
-
switch (this.synthesizerType) {
|
|
134
|
-
case SynthesizerType.CONSENSUS:
|
|
135
|
-
prompt = `Build a consensus from the following agent outputs. Identify common points, resolve minor discrepancies, and provide a unified conclusion.\n\n${contextStr}\n${outputsStr}`;
|
|
136
|
-
break;
|
|
137
|
-
case SynthesizerType.CREATIVE:
|
|
138
|
-
prompt = `Perform a creative synthesis of these agent outputs. Look for unexpected connections, combine ideas in novel ways, and provide a unique integrated insight.\n\n${contextStr}\n${outputsStr}`;
|
|
139
|
-
systemPrompt = 'You are a creative synthesizer agent. You excel at finding novel connections and unique perspectives by combining diverse ideas.';
|
|
140
|
-
break;
|
|
141
|
-
case SynthesizerType.CONFLICT_RESOLUTION:
|
|
142
|
-
prompt = `Resolve the conflicts between these agent outputs. Analyze the reasoning behind each conflicting point and determine the most logically sound resolution based on the evidence and confidence levels.\n\n${contextStr}\n${outputsStr}`;
|
|
143
|
-
systemPrompt = 'You are a conflict resolution specialist agent. You excel at analyzing differing perspectives and finding the most accurate resolution based on logic and evidence.';
|
|
144
|
-
break;
|
|
145
|
-
default:
|
|
146
|
-
prompt = `Integrate the following agent outputs into a comprehensive final result.\n\n${contextStr}\n${outputsStr}`;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const response = await LLMAdapter.call(prompt, systemPrompt, provider);
|
|
150
|
-
|
|
151
|
-
if (response.error) {
|
|
152
|
-
// Fallback to heuristic if LLM fails
|
|
153
|
-
const heuristicResult = await this.heuristicSynthesis(input);
|
|
154
|
-
return this.createTaskResult(task.id, heuristicResult, heuristicResult.confidence, Date.now() - startTime, { error: response.error });
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const synthesizedOutput = response.content;
|
|
158
|
-
const avgConfidence = input.outputs.reduce((sum, o) => sum + o.confidence, 0) / input.outputs.length;
|
|
159
|
-
|
|
160
|
-
const result: Synthesis = {
|
|
161
|
-
synthesizedOutput,
|
|
162
|
-
confidence: Math.min(0.95, avgConfidence + 0.1), // Boost confidence for successful synthesis
|
|
163
|
-
contributingAgents: input.outputs.map(o => o.agentId),
|
|
164
|
-
synthesisMethod: `llm_${this.synthesizerType.toLowerCase()}`
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
return this.createTaskResult(
|
|
168
|
-
task.id,
|
|
169
|
-
result,
|
|
170
|
-
result.confidence,
|
|
171
|
-
Date.now() - startTime,
|
|
172
|
-
{
|
|
173
|
-
reasoningSteps: input.outputs.length + 1,
|
|
174
|
-
intermediateResults: input.outputs.map(o => o.output)
|
|
175
|
-
}
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Fallback heuristic synthesis
|
|
181
|
-
*/
|
|
182
|
-
private async heuristicSynthesis(input: SynthesisInput): Promise<Synthesis> {
|
|
183
|
-
const { outputs } = input;
|
|
184
|
-
// Simplified version of the previous heuristic logic
|
|
185
|
-
return {
|
|
186
|
-
synthesizedOutput: outputs.map(o => JSON.stringify(o.output)).join('\n---\n'),
|
|
187
|
-
confidence: outputs.reduce((sum, o) => sum + o.confidence, 0) / outputs.length,
|
|
188
|
-
contributingAgents: outputs.map(o => o.agentId),
|
|
189
|
-
synthesisMethod: 'heuristic_fallback'
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
// ============================================================================
|
|
195
|
-
// Helper Methods
|
|
196
|
-
// ============================================================================
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Extract key points from output
|
|
200
|
-
* @param output - Output to extract from
|
|
201
|
-
* @returns Array of key points
|
|
202
|
-
*/
|
|
203
|
-
private extractKeyPoints(output: unknown): string[] {
|
|
204
|
-
if (typeof output === 'string') {
|
|
205
|
-
return output.split(/[.!?]+/).filter(s => s.trim().length > 10);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
if (output && typeof output === 'object') {
|
|
209
|
-
const obj = output as Record<string, unknown>;
|
|
210
|
-
|
|
211
|
-
if ('conclusion' in obj && typeof obj.conclusion === 'string') {
|
|
212
|
-
return [obj.conclusion];
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if ('keyPoints' in obj && Array.isArray(obj.keyPoints)) {
|
|
216
|
-
return obj.keyPoints as string[];
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
return [JSON.stringify(output)];
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
return [String(output)];
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Find consensus points
|
|
227
|
-
* @param keyPointsArray - Array of key points arrays
|
|
228
|
-
* @returns Consensus points
|
|
229
|
-
*/
|
|
230
|
-
private findConsensusPoints(keyPointsArray: string[][]): string[] {
|
|
231
|
-
if (keyPointsArray.length === 0) return [];
|
|
232
|
-
if (keyPointsArray.length === 1) return keyPointsArray[0];
|
|
233
|
-
|
|
234
|
-
const consensus: string[] = [];
|
|
235
|
-
const firstSet = keyPointsArray[0];
|
|
236
|
-
|
|
237
|
-
for (const point of firstSet) {
|
|
238
|
-
const normalizedPoint = this.normalizePoint(point);
|
|
239
|
-
let matchCount = 1;
|
|
240
|
-
|
|
241
|
-
for (let i = 1; i < keyPointsArray.length; i++) {
|
|
242
|
-
const otherSet = keyPointsArray[i];
|
|
243
|
-
const hasMatch = otherSet.some(otherPoint =>
|
|
244
|
-
this.pointsAreSimilar(normalizedPoint, this.normalizePoint(otherPoint))
|
|
245
|
-
);
|
|
246
|
-
if (hasMatch) matchCount++;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// Point is in consensus if it appears in majority
|
|
250
|
-
if (matchCount > keyPointsArray.length / 2) {
|
|
251
|
-
consensus.push(point);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
return consensus;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* Find divergence points
|
|
260
|
-
* @param keyPointsArray - Array of key points arrays
|
|
261
|
-
* @returns Divergence points
|
|
262
|
-
*/
|
|
263
|
-
private findDivergencePoints(keyPointsArray: string[][]): string[] {
|
|
264
|
-
if (keyPointsArray.length <= 1) return [];
|
|
265
|
-
|
|
266
|
-
const allPoints = keyPointsArray.flat();
|
|
267
|
-
const uniquePoints = [...new Set(allPoints.map(p => this.normalizePoint(p)))];
|
|
268
|
-
const divergence: string[] = [];
|
|
269
|
-
|
|
270
|
-
for (const point of uniquePoints) {
|
|
271
|
-
let matchCount = 0;
|
|
272
|
-
|
|
273
|
-
for (const pointSet of keyPointsArray) {
|
|
274
|
-
const hasMatch = pointSet.some(p =>
|
|
275
|
-
this.pointsAreSimilar(point, this.normalizePoint(p))
|
|
276
|
-
);
|
|
277
|
-
if (hasMatch) matchCount++;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
// Point diverges if not in majority
|
|
281
|
-
if (matchCount <= keyPointsArray.length / 2) {
|
|
282
|
-
const original = allPoints.find(p => this.normalizePoint(p) === point);
|
|
283
|
-
if (original) divergence.push(original);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
return divergence;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
/**
|
|
291
|
-
* Normalize a point for comparison
|
|
292
|
-
* @param point - Point to normalize
|
|
293
|
-
* @returns Normalized point
|
|
294
|
-
*/
|
|
295
|
-
private normalizePoint(point: string): string {
|
|
296
|
-
return point.toLowerCase().trim().replace(/\s+/g, ' ');
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Check if two points are similar
|
|
301
|
-
* @param a - First point
|
|
302
|
-
* @param b - Second point
|
|
303
|
-
* @returns True if similar
|
|
304
|
-
*/
|
|
305
|
-
private pointsAreSimilar(a: string, b: string): boolean {
|
|
306
|
-
// Simple similarity check
|
|
307
|
-
if (a === b) return true;
|
|
308
|
-
|
|
309
|
-
const wordsA = new Set(a.split(' '));
|
|
310
|
-
const wordsB = new Set(b.split(' '));
|
|
311
|
-
const intersection = [...wordsA].filter(w => wordsB.has(w));
|
|
312
|
-
const union = new Set([...wordsA, ...wordsB]);
|
|
313
|
-
|
|
314
|
-
return union.size > 0 && intersection.length / union.size > 0.6;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
/**
|
|
318
|
-
* Apply confidence weights to points
|
|
319
|
-
* @param points - Points to weight
|
|
320
|
-
* @param outputs - Outputs with confidence
|
|
321
|
-
* @returns Weighted points
|
|
322
|
-
*/
|
|
323
|
-
private applyConfidenceWeights(
|
|
324
|
-
points: string[],
|
|
325
|
-
outputs: Array<{ confidence: number }>
|
|
326
|
-
): Array<{ point: string; weight: number }> {
|
|
327
|
-
const avgConfidence = outputs.reduce((sum, o) => sum + o.confidence, 0) / outputs.length;
|
|
328
|
-
|
|
329
|
-
return points.map(point => ({
|
|
330
|
-
point,
|
|
331
|
-
weight: avgConfidence
|
|
332
|
-
}));
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/**
|
|
336
|
-
* Generate unified output
|
|
337
|
-
* @param weightedPoints - Weighted points
|
|
338
|
-
* @param divergencePoints - Divergence points
|
|
339
|
-
* @returns Unified output
|
|
340
|
-
*/
|
|
341
|
-
private generateUnifiedOutput(
|
|
342
|
-
weightedPoints: Array<{ point: string; weight: number }>,
|
|
343
|
-
divergencePoints: string[]
|
|
344
|
-
): Record<string, unknown> {
|
|
345
|
-
return {
|
|
346
|
-
consensus: weightedPoints.map(wp => wp.point),
|
|
347
|
-
consensusWeights: weightedPoints.map(wp => wp.weight),
|
|
348
|
-
pointsOfDivergence: divergencePoints,
|
|
349
|
-
summary: `Consensus reached on ${weightedPoints.length} points with ${divergencePoints.length} points of divergence`
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* Extract creative elements
|
|
355
|
-
* @param output - Output to extract from
|
|
356
|
-
* @returns Creative elements
|
|
357
|
-
*/
|
|
358
|
-
private extractCreativeElements(output: unknown): string[] {
|
|
359
|
-
if (typeof output === 'string') {
|
|
360
|
-
// Extract novel phrases, metaphors, etc.
|
|
361
|
-
return output.split(/[.!?]+/).filter(s => s.trim().length > 5);
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
if (output && typeof output === 'object') {
|
|
365
|
-
const obj = output as Record<string, unknown>;
|
|
366
|
-
|
|
367
|
-
if ('creativeElements' in obj && Array.isArray(obj.creativeElements)) {
|
|
368
|
-
return obj.creativeElements as string[];
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
if ('ideas' in obj && Array.isArray(obj.ideas)) {
|
|
372
|
-
return obj.ideas as string[];
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
return [String(output)];
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
/**
|
|
380
|
-
* Find unexpected connections
|
|
381
|
-
* @param elementsArray - Array of element arrays
|
|
382
|
-
* @returns Connections
|
|
383
|
-
*/
|
|
384
|
-
private findUnexpectedConnections(elementsArray: string[][]): Array<{
|
|
385
|
-
elements: [string, string];
|
|
386
|
-
connection: string;
|
|
387
|
-
}> {
|
|
388
|
-
const connections: Array<{ elements: [string, string]; connection: string }> = [];
|
|
389
|
-
|
|
390
|
-
// Compare elements from different sources
|
|
391
|
-
for (let i = 0; i < elementsArray.length; i++) {
|
|
392
|
-
for (let j = i + 1; j < elementsArray.length; j++) {
|
|
393
|
-
const setA = elementsArray[i];
|
|
394
|
-
const setB = elementsArray[j];
|
|
395
|
-
|
|
396
|
-
for (const elemA of setA) {
|
|
397
|
-
for (const elemB of setB) {
|
|
398
|
-
const connection = this.findConnection(elemA, elemB);
|
|
399
|
-
if (connection) {
|
|
400
|
-
connections.push({
|
|
401
|
-
elements: [elemA, elemB],
|
|
402
|
-
connection
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
return connections;
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
/**
|
|
414
|
-
* Find connection between two elements
|
|
415
|
-
* @param a - First element
|
|
416
|
-
* @param b - Second element
|
|
417
|
-
* @returns Connection description or null
|
|
418
|
-
*/
|
|
419
|
-
private findConnection(a: string, b: string): string | null {
|
|
420
|
-
const wordsA = new Set(a.toLowerCase().split(/\s+/));
|
|
421
|
-
const wordsB = new Set(b.toLowerCase().split(/\s+/));
|
|
422
|
-
const common = [...wordsA].filter(w => wordsB.has(w) && w.length > 3);
|
|
423
|
-
|
|
424
|
-
if (common.length > 0) {
|
|
425
|
-
return `Connected through: ${common.join(', ')}`;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
return null;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
/**
|
|
432
|
-
* Generate novel combinations
|
|
433
|
-
* @param elementsArray - Array of element arrays
|
|
434
|
-
* @param connections - Connections
|
|
435
|
-
* @returns Combinations
|
|
436
|
-
*/
|
|
437
|
-
private generateNovelCombinations(
|
|
438
|
-
elementsArray: string[][],
|
|
439
|
-
connections: Array<{ elements: [string, string]; connection: string }>
|
|
440
|
-
): string[] {
|
|
441
|
-
const combinations: string[] = [];
|
|
442
|
-
|
|
443
|
-
for (const connection of connections) {
|
|
444
|
-
const [elemA, elemB] = connection.elements;
|
|
445
|
-
combinations.push(`Combining "${elemA.substring(0, 30)}..." with "${elemB.substring(0, 30)}..."`);
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
// Cross-pollinate ideas
|
|
449
|
-
for (let i = 0; i < elementsArray.length && i < 3; i++) {
|
|
450
|
-
for (let j = i + 1; j < elementsArray.length && j < 3; j++) {
|
|
451
|
-
const elemA = elementsArray[i][0];
|
|
452
|
-
const elemB = elementsArray[j][0];
|
|
453
|
-
if (elemA && elemB) {
|
|
454
|
-
combinations.push(`Cross: ${elemA.substring(0, 20)}... + ${elemB.substring(0, 20)}...`);
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
return combinations;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
/**
|
|
463
|
-
* Generate novel insights
|
|
464
|
-
* @param combinations - Combinations
|
|
465
|
-
* @returns Insights
|
|
466
|
-
*/
|
|
467
|
-
private generateNovelInsights(combinations: string[]): string[] {
|
|
468
|
-
return combinations.map((combo, i) =>
|
|
469
|
-
`Insight ${i + 1}: ${combo} suggests a new approach`
|
|
470
|
-
);
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
/**
|
|
474
|
-
* Calculate diversity score
|
|
475
|
-
* @param elementsArray - Array of element arrays
|
|
476
|
-
* @returns Diversity score (0-1)
|
|
477
|
-
*/
|
|
478
|
-
private calculateDiversity(elementsArray: string[][]): number {
|
|
479
|
-
const allElements = elementsArray.flat();
|
|
480
|
-
const uniqueElements = new Set(allElements);
|
|
481
|
-
|
|
482
|
-
if (allElements.length === 0) return 0;
|
|
483
|
-
|
|
484
|
-
return uniqueElements.size / allElements.length;
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
/**
|
|
488
|
-
* Identify conflicts
|
|
489
|
-
* @param outputs - Outputs to analyze
|
|
490
|
-
* @returns Conflicts
|
|
491
|
-
*/
|
|
492
|
-
private identifyConflicts(outputs: Array<{ agentId: string; output: unknown }>): Array<{
|
|
493
|
-
type: string;
|
|
494
|
-
description: string;
|
|
495
|
-
involvedAgents: string[];
|
|
496
|
-
}> {
|
|
497
|
-
const conflicts: Array<{
|
|
498
|
-
type: string;
|
|
499
|
-
description: string;
|
|
500
|
-
involvedAgents: string[];
|
|
501
|
-
}> = [];
|
|
502
|
-
|
|
503
|
-
// Check for contradictory conclusions
|
|
504
|
-
const conclusions: Array<{ agentId: string; conclusion: string }> = [];
|
|
505
|
-
|
|
506
|
-
for (const output of outputs) {
|
|
507
|
-
const conclusion = this.extractConclusion(output.output);
|
|
508
|
-
if (conclusion) {
|
|
509
|
-
conclusions.push({ agentId: output.agentId, conclusion });
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
// Find contradictions
|
|
514
|
-
for (let i = 0; i < conclusions.length; i++) {
|
|
515
|
-
for (let j = i + 1; j < conclusions.length; j++) {
|
|
516
|
-
const a = conclusions[i];
|
|
517
|
-
const b = conclusions[j];
|
|
518
|
-
|
|
519
|
-
if (this.areContradictory(a.conclusion, b.conclusion)) {
|
|
520
|
-
conflicts.push({
|
|
521
|
-
type: 'contradiction',
|
|
522
|
-
description: `Contradictory conclusions: "${a.conclusion.substring(0, 30)}..." vs "${b.conclusion.substring(0, 30)}..."`,
|
|
523
|
-
involvedAgents: [a.agentId, b.agentId]
|
|
524
|
-
});
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
return conflicts;
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
/**
|
|
533
|
-
* Extract conclusion from output
|
|
534
|
-
* @param output - Output to extract from
|
|
535
|
-
* @returns Conclusion string or null
|
|
536
|
-
*/
|
|
537
|
-
private extractConclusion(output: unknown): string | null {
|
|
538
|
-
if (typeof output === 'string') return output;
|
|
539
|
-
|
|
540
|
-
if (output && typeof output === 'object') {
|
|
541
|
-
const obj = output as Record<string, unknown>;
|
|
542
|
-
|
|
543
|
-
if ('conclusion' in obj && typeof obj.conclusion === 'string') {
|
|
544
|
-
return obj.conclusion;
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
return null;
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
/**
|
|
552
|
-
* Check if two conclusions are contradictory
|
|
553
|
-
* @param a - First conclusion
|
|
554
|
-
* @param b - Second conclusion
|
|
555
|
-
* @returns True if contradictory
|
|
556
|
-
*/
|
|
557
|
-
private areContradictory(a: string, b: string): boolean {
|
|
558
|
-
const lowerA = a.toLowerCase();
|
|
559
|
-
const lowerB = b.toLowerCase();
|
|
560
|
-
|
|
561
|
-
// Check for direct opposites
|
|
562
|
-
const oppositePatterns = [
|
|
563
|
-
{ pos: /\b(is|are|was|were)\b/gi, neg: /\b(is not|are not|was not|were not)\b/gi },
|
|
564
|
-
{ pos: /\bshould\b/gi, neg: /\bshould not\b/gi },
|
|
565
|
-
{ pos: /\bcan\b/gi, neg: /\bcannot\b/gi }
|
|
566
|
-
];
|
|
567
|
-
|
|
568
|
-
for (const { pos, neg } of oppositePatterns) {
|
|
569
|
-
const aHasPos = pos.test(lowerA);
|
|
570
|
-
const aHasNeg = neg.test(lowerA);
|
|
571
|
-
const bHasPos = pos.test(lowerB);
|
|
572
|
-
const bHasNeg = neg.test(lowerB);
|
|
573
|
-
|
|
574
|
-
if ((aHasPos && bHasNeg) || (aHasNeg && bHasPos)) {
|
|
575
|
-
return true;
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
return false;
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
/**
|
|
583
|
-
* Resolve a conflict
|
|
584
|
-
* @param conflict - Conflict to resolve
|
|
585
|
-
* @param outputs - All outputs
|
|
586
|
-
* @returns Resolution
|
|
587
|
-
*/
|
|
588
|
-
private resolveConflict(
|
|
589
|
-
conflict: { type: string; involvedAgents: string[] },
|
|
590
|
-
outputs: Array<{ agentId: string; output: unknown; confidence: number }>
|
|
591
|
-
): { resolution: unknown; confidence: number } {
|
|
592
|
-
// Get conflicting outputs
|
|
593
|
-
const conflictingOutputs = outputs.filter(o =>
|
|
594
|
-
conflict.involvedAgents.includes(o.agentId)
|
|
595
|
-
);
|
|
596
|
-
|
|
597
|
-
// Select based on confidence
|
|
598
|
-
const best = conflictingOutputs.reduce((max, o) =>
|
|
599
|
-
o.confidence > max.confidence ? o : max,
|
|
600
|
-
conflictingOutputs[0]
|
|
601
|
-
);
|
|
602
|
-
|
|
603
|
-
if (!best) {
|
|
604
|
-
return { resolution: null, confidence: 0 };
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
return {
|
|
608
|
-
resolution: best.output,
|
|
609
|
-
confidence: best.confidence
|
|
610
|
-
};
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
/**
|
|
614
|
-
* Merge resolutions with non-conflicting content
|
|
615
|
-
* @param outputs - All outputs
|
|
616
|
-
* @param resolutions - Resolutions
|
|
617
|
-
* @returns Merged output
|
|
618
|
-
*/
|
|
619
|
-
private mergeResolutions(
|
|
620
|
-
outputs: Array<{ agentId: string; output: unknown }>,
|
|
621
|
-
resolutions: Array<{ conflict: { involvedAgents: string[] }; resolution: { resolution: unknown } }>
|
|
622
|
-
): Record<string, unknown> {
|
|
623
|
-
const merged: Record<string, unknown> = {
|
|
624
|
-
resolvedConflicts: resolutions.length,
|
|
625
|
-
agentOutputs: {}
|
|
626
|
-
};
|
|
627
|
-
|
|
628
|
-
// Add all outputs
|
|
629
|
-
for (const output of outputs) {
|
|
630
|
-
(merged.agentOutputs as Record<string, unknown>)[output.agentId] = output.output;
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
// Add resolutions
|
|
634
|
-
merged.resolutions = resolutions.map(r => ({
|
|
635
|
-
conflict: r.conflict,
|
|
636
|
-
selectedResolution: r.resolution.resolution
|
|
637
|
-
}));
|
|
638
|
-
|
|
639
|
-
return merged;
|
|
640
|
-
}
|
|
641
|
-
}
|