@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,322 @@
1
+ /**
2
+ * Utils Test Suite
3
+ * Tests for utility functions including ID generation, similarity calculations,
4
+ * statistical functions, formatting, and validation
5
+ */
6
+ import { test, describe } from 'node:test';
7
+ import assert from 'node:assert';
8
+ import {
9
+ generateId,
10
+ clamp,
11
+ calculateSimilarity,
12
+ calculateMean,
13
+ formatDuration,
14
+ } from '../utils/index.js';
15
+
16
+ describe('generateId', () => {
17
+ test('should generate unique IDs', () => {
18
+ const id1 = generateId();
19
+ const id2 = generateId();
20
+ assert.notStrictEqual(id1, id2);
21
+ });
22
+
23
+ test('should generate string IDs', () => {
24
+ const id = generateId();
25
+ assert.strictEqual(typeof id, 'string');
26
+ });
27
+
28
+ test('should generate non-empty IDs', () => {
29
+ const id = generateId();
30
+ assert.ok(id.length > 0);
31
+ });
32
+
33
+ test('should generate IDs with consistent length', () => {
34
+ const ids = Array.from({ length: 100 }, generateId);
35
+ const lengths = new Set(ids.map(id => id.length));
36
+ assert.strictEqual(lengths.size, 1, 'All IDs should have the same length');
37
+ });
38
+
39
+ test('should generate IDs containing only valid characters', () => {
40
+ const id = generateId();
41
+ assert.ok(/^[a-zA-Z0-9_-]+$/.test(id), 'ID should contain only alphanumeric, underscore, and hyphen characters');
42
+ });
43
+
44
+ test('should generate many unique IDs without collision', () => {
45
+ const ids = new Set(Array.from({ length: 1000 }, generateId));
46
+ assert.strictEqual(ids.size, 1000, 'All 1000 IDs should be unique');
47
+ });
48
+ });
49
+
50
+ describe('clamp', () => {
51
+ test('should return value when within range', () => {
52
+ assert.strictEqual(clamp(5, 0, 10), 5);
53
+ assert.strictEqual(clamp(0, 0, 10), 0);
54
+ assert.strictEqual(clamp(10, 0, 10), 10);
55
+ });
56
+
57
+ test('should clamp to min when below range', () => {
58
+ assert.strictEqual(clamp(-5, 0, 10), 0);
59
+ assert.strictEqual(clamp(-100, 0, 10), 0);
60
+ assert.strictEqual(clamp(-0.1, 0, 10), 0);
61
+ });
62
+
63
+ test('should clamp to max when above range', () => {
64
+ assert.strictEqual(clamp(15, 0, 10), 10);
65
+ assert.strictEqual(clamp(100, 0, 10), 10);
66
+ assert.strictEqual(clamp(10.1, 0, 10), 10);
67
+ });
68
+
69
+ test('should handle negative ranges', () => {
70
+ assert.strictEqual(clamp(-5, -10, -1), -5);
71
+ assert.strictEqual(clamp(-15, -10, -1), -10);
72
+ assert.strictEqual(clamp(0, -10, -1), -1);
73
+ });
74
+
75
+ test('should handle decimal ranges', () => {
76
+ assert.strictEqual(clamp(0.5, 0, 1), 0.5);
77
+ assert.strictEqual(clamp(-0.5, 0, 1), 0);
78
+ assert.strictEqual(clamp(1.5, 0, 1), 1);
79
+ });
80
+
81
+ test('should handle zero range (min equals max)', () => {
82
+ assert.strictEqual(clamp(5, 5, 5), 5);
83
+ assert.strictEqual(clamp(0, 5, 5), 5);
84
+ assert.strictEqual(clamp(10, 5, 5), 5);
85
+ });
86
+
87
+ test('should handle very large numbers', () => {
88
+ assert.strictEqual(clamp(1e20, 0, 1e18), 1e18);
89
+ assert.strictEqual(clamp(-1e20, -1e18, 0), -1e18);
90
+ });
91
+
92
+ test('should handle very small numbers', () => {
93
+ assert.strictEqual(clamp(1e-20, 1e-18, 1), 1e-18);
94
+ assert.strictEqual(clamp(-1e-20, -1, -1e-18), -1e-18);
95
+ });
96
+ });
97
+
98
+ describe('calculateSimilarity', () => {
99
+ test('should return 1 for identical strings', () => {
100
+ assert.strictEqual(calculateSimilarity('hello', 'hello'), 1);
101
+ assert.strictEqual(calculateSimilarity('', ''), 1);
102
+ assert.strictEqual(calculateSimilarity('The quick brown fox', 'The quick brown fox'), 1);
103
+ });
104
+
105
+ test('should return 0 for completely different strings', () => {
106
+ assert.strictEqual(calculateSimilarity('abc', 'xyz'), 0);
107
+ assert.strictEqual(calculateSimilarity('abc', 'def'), 0);
108
+ });
109
+
110
+ test('should return value between 0 and 1 for similar strings', () => {
111
+ const similarity = calculateSimilarity('hello', 'hallo');
112
+ assert.ok(similarity > 0 && similarity < 1);
113
+ });
114
+
115
+ test('should be case sensitive', () => {
116
+ const similarity = calculateSimilarity('Hello', 'hello');
117
+ assert.ok(similarity < 1, 'Case-sensitive comparison should not return 1');
118
+ });
119
+
120
+ test('should handle empty strings', () => {
121
+ assert.strictEqual(calculateSimilarity('', ''), 1);
122
+ assert.strictEqual(calculateSimilarity('', 'hello'), 0);
123
+ assert.strictEqual(calculateSimilarity('hello', ''), 0);
124
+ });
125
+
126
+ test('should handle whitespace differences', () => {
127
+ const similarity1 = calculateSimilarity('hello world', 'hello world');
128
+ const similarity2 = calculateSimilarity('hello world', 'helloworld');
129
+ assert.ok(similarity1 > similarity2, 'Extra space should be more similar than no space');
130
+ });
131
+
132
+ test('should handle substring relationships', () => {
133
+ const similarity = calculateSimilarity('hello world', 'hello');
134
+ assert.ok(similarity > 0 && similarity < 1);
135
+ });
136
+
137
+ test('should be symmetric', () => {
138
+ const sim1 = calculateSimilarity('kitten', 'sitting');
139
+ const sim2 = calculateSimilarity('sitting', 'kitten');
140
+ assert.strictEqual(sim1, sim2);
141
+ });
142
+
143
+ test('should handle special characters', () => {
144
+ assert.ok(calculateSimilarity('hello!', 'hello') > 0);
145
+ assert.ok(calculateSimilarity('hello@#$', 'hello') > 0);
146
+ });
147
+
148
+ test('should handle unicode characters', () => {
149
+ assert.strictEqual(calculateSimilarity('héllo', 'héllo'), 1);
150
+ assert.ok(calculateSimilarity('héllo', 'hello') >= 0);
151
+ });
152
+
153
+ test('should handle very long strings', () => {
154
+ const long1 = 'a'.repeat(10000);
155
+ const long2 = 'a'.repeat(9999) + 'b';
156
+ const similarity = calculateSimilarity(long1, long2);
157
+ assert.ok(similarity > 0.99, 'Very similar long strings should have high similarity');
158
+ });
159
+
160
+ test('should handle common typos', () => {
161
+ const similarity = calculateSimilarity('accommodation', 'accomodation');
162
+ assert.ok(similarity > 0.9, 'Common typos should have high similarity');
163
+ });
164
+ });
165
+
166
+ describe('calculateMean', () => {
167
+ test('should calculate mean of positive numbers', () => {
168
+ assert.strictEqual(calculateMean([1, 2, 3, 4, 5]), 3);
169
+ assert.strictEqual(calculateMean([10, 20, 30]), 20);
170
+ });
171
+
172
+ test('should calculate mean of negative numbers', () => {
173
+ assert.strictEqual(calculateMean([-1, -2, -3, -4, -5]), -3);
174
+ assert.strictEqual(calculateMean([-10, -20, -30]), -20);
175
+ });
176
+
177
+ test('should calculate mean of mixed numbers', () => {
178
+ assert.strictEqual(calculateMean([-5, 0, 5]), 0);
179
+ assert.strictEqual(calculateMean([-10, 10]), 0);
180
+ });
181
+
182
+ test('should handle single element array', () => {
183
+ assert.strictEqual(calculateMean([42]), 42);
184
+ assert.strictEqual(calculateMean([0]), 0);
185
+ });
186
+
187
+ test('should handle decimal numbers', () => {
188
+ assert.strictEqual(calculateMean([1.5, 2.5, 3.5]), 2.5);
189
+ assert.ok(Math.abs(calculateMean([0.1, 0.2, 0.3]) - 0.2) < 0.0001);
190
+ });
191
+
192
+ test('should handle empty array', () => {
193
+ assert.ok(Number.isNaN(calculateMean([])));
194
+ });
195
+
196
+ test('should handle array with zeros', () => {
197
+ assert.strictEqual(calculateMean([0, 0, 0]), 0);
198
+ assert.strictEqual(calculateMean([0, 10, 0]), 10 / 3);
199
+ });
200
+
201
+ test('should handle very large numbers', () => {
202
+ const result = calculateMean([1e10, 2e10, 3e10]);
203
+ assert.strictEqual(result, 2e10);
204
+ });
205
+
206
+ test('should handle very small numbers', () => {
207
+ const result = calculateMean([1e-10, 2e-10, 3e-10]);
208
+ assert.strictEqual(result, 2e-10);
209
+ });
210
+
211
+ test('should handle large arrays', () => {
212
+ const largeArray = Array.from({ length: 10000 }, (_, i) => i + 1);
213
+ const result = calculateMean(largeArray);
214
+ assert.strictEqual(result, 5000.5);
215
+ });
216
+
217
+ test('should be precise with floating point', () => {
218
+ // Test for floating point precision issues
219
+ const result = calculateMean([0.1, 0.2]);
220
+ assert.ok(Math.abs(result - 0.15) < 0.0001);
221
+ });
222
+ });
223
+
224
+ describe('formatDuration', () => {
225
+ test('should format milliseconds', () => {
226
+ assert.strictEqual(formatDuration(500), '500ms');
227
+ assert.strictEqual(formatDuration(0), '0ms');
228
+ assert.strictEqual(formatDuration(999), '999ms');
229
+ });
230
+
231
+ test('should format seconds', () => {
232
+ assert.strictEqual(formatDuration(1000), '1s');
233
+ assert.strictEqual(formatDuration(5000), '5s');
234
+ assert.strictEqual(formatDuration(59000), '59s');
235
+ });
236
+
237
+ test('should format minutes', () => {
238
+ assert.strictEqual(formatDuration(60000), '1m');
239
+ assert.strictEqual(formatDuration(120000), '2m');
240
+ assert.strictEqual(formatDuration(3540000), '59m');
241
+ });
242
+
243
+ test('should format hours', () => {
244
+ assert.strictEqual(formatDuration(3600000), '1h');
245
+ assert.strictEqual(formatDuration(7200000), '2h');
246
+ assert.strictEqual(formatDuration(86400000), '24h');
247
+ });
248
+
249
+ test('should format days', () => {
250
+ assert.strictEqual(formatDuration(86400000), '24h');
251
+ assert.strictEqual(formatDuration(172800000), '48h');
252
+ });
253
+
254
+ test('should handle negative durations', () => {
255
+ assert.strictEqual(formatDuration(-500), '-500ms');
256
+ assert.strictEqual(formatDuration(-1000), '-1s');
257
+ });
258
+
259
+ test('should handle decimal milliseconds', () => {
260
+ assert.strictEqual(formatDuration(500.5), '500ms');
261
+ assert.strictEqual(formatDuration(1000.9), '1s');
262
+ });
263
+
264
+ test('should handle very large durations', () => {
265
+ assert.strictEqual(formatDuration(31536000000), '8760h'); // 1 year in hours
266
+ });
267
+
268
+ test('should handle boundary values', () => {
269
+ assert.strictEqual(formatDuration(59999), '59s');
270
+ assert.strictEqual(formatDuration(60000), '1m');
271
+ assert.strictEqual(formatDuration(59999.9), '59s');
272
+ });
273
+ });
274
+
275
+ describe('Utility Functions Integration', () => {
276
+ test('clamp and calculateMean work together', () => {
277
+ const values = [5, 15, 25, 35, 45];
278
+ const mean = calculateMean(values);
279
+ const clampedMean = clamp(mean, 10, 30);
280
+ assert.ok(clampedMean >= 10 && clampedMean <= 30);
281
+ });
282
+
283
+ test('generateId and calculateSimilarity work together', () => {
284
+ const id1 = generateId();
285
+ const id2 = generateId();
286
+ const similarity = calculateSimilarity(id1, id2);
287
+ assert.ok(similarity >= 0 && similarity <= 1);
288
+ });
289
+
290
+ test('formatDuration handles processing time from TaskResult', () => {
291
+ const processingTimes = [100, 500, 1000, 5000, 60000];
292
+ processingTimes.forEach(time => {
293
+ const formatted = formatDuration(time);
294
+ assert.ok(formatted.length > 0);
295
+ assert.ok(/\d+(ms|s|m|h)/.test(formatted));
296
+ });
297
+ });
298
+ });
299
+
300
+ describe('Edge Cases and Error Conditions', () => {
301
+ test('clamp with Infinity values', () => {
302
+ assert.strictEqual(clamp(5, -Infinity, Infinity), 5);
303
+ assert.strictEqual(clamp(Infinity, 0, 10), 10);
304
+ assert.strictEqual(clamp(-Infinity, 0, 10), 0);
305
+ });
306
+
307
+ test('calculateMean with Infinity values', () => {
308
+ assert.strictEqual(calculateMean([1, 2, Infinity]), Infinity);
309
+ assert.strictEqual(calculateMean([-Infinity, 0, 1]), -Infinity);
310
+ });
311
+
312
+ test('calculateSimilarity with null/undefined should handle gracefully', () => {
313
+ // These should not throw errors
314
+ assert.doesNotThrow(() => calculateSimilarity('', ''));
315
+ assert.doesNotThrow(() => calculateSimilarity('test', 'test'));
316
+ });
317
+
318
+ test('formatDuration with very small values', () => {
319
+ assert.strictEqual(formatDuration(0.1), '0ms');
320
+ assert.strictEqual(formatDuration(0.9), '0ms');
321
+ });
322
+ });
@@ -0,0 +1,285 @@
1
+ /**
2
+ * Base Agent Class
3
+ * @module agents/base-agent
4
+ * @version 1.0.0
5
+ */
6
+
7
+ import {
8
+ AgentType,
9
+ AgentStatus,
10
+ type AgentConfig,
11
+ type AgentCapability,
12
+ type Task,
13
+ type TaskResult,
14
+ type SwarmMessage
15
+ } from '../types/index.js';
16
+
17
+ /**
18
+ * Abstract base class for all agents
19
+ */
20
+ export abstract class BaseAgent {
21
+ /** Agent ID */
22
+ readonly id: string;
23
+
24
+ /** Agent configuration */
25
+ config: AgentConfig;
26
+
27
+ /** Current status */
28
+ protected status: AgentStatus = AgentStatus.IDLE;
29
+
30
+ /** Current task IDs */
31
+ protected currentTasks: Set<string> = new Set();
32
+
33
+ /** Performance history */
34
+ protected performanceHistory: Array<{
35
+ taskId: string;
36
+ quality: number;
37
+ timeMs: number;
38
+ timestamp: Date;
39
+ }> = [];
40
+
41
+ /** Message handlers */
42
+ protected messageHandlers: Array<(message: SwarmMessage) => void | Promise<void>> = [];
43
+
44
+ /**
45
+ * Create a new base agent
46
+ * @param config - Agent configuration
47
+ */
48
+ constructor(config: Partial<AgentConfig> & { name: string }) {
49
+ this.id = config.id || `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
50
+ this.config = {
51
+ id: this.id,
52
+ name: config.name,
53
+ type: config.type || AgentType.UTILITY,
54
+ subtype: config.subtype,
55
+ capabilities: config.capabilities || [],
56
+ maxConcurrentTasks: config.maxConcurrentTasks || 3,
57
+ confidenceThreshold: config.confidenceThreshold || 0.7,
58
+ metadata: {
59
+ createdAt: new Date(),
60
+ version: '1.0.0',
61
+ config: config.metadata?.config || {}
62
+ }
63
+ };
64
+ }
65
+
66
+ /**
67
+ * Execute a task
68
+ * @param task - Task to execute
69
+ * @returns Task result
70
+ */
71
+ async execute(task: Task): Promise<TaskResult> {
72
+ const startTime = Date.now();
73
+ this.status = AgentStatus.BUSY;
74
+ this.currentTasks.add(task.id);
75
+
76
+ try {
77
+ const result = await this.process(task);
78
+ const processingTime = Date.now() - startTime;
79
+
80
+ this.performanceHistory.push({
81
+ taskId: task.id,
82
+ quality: result.confidence,
83
+ timeMs: processingTime,
84
+ timestamp: new Date()
85
+ });
86
+
87
+ this.currentTasks.delete(task.id);
88
+ this.status = this.currentTasks.size === 0 ? AgentStatus.IDLE : AgentStatus.BUSY;
89
+
90
+ return result;
91
+ } catch (error) {
92
+ this.currentTasks.delete(task.id);
93
+ this.status = this.currentTasks.size === 0 ? AgentStatus.IDLE : AgentStatus.BUSY;
94
+
95
+ return {
96
+ taskId: task.id,
97
+ agentId: this.id,
98
+ success: false,
99
+ output: null,
100
+ confidence: 0,
101
+ processingTimeMs: Date.now() - startTime,
102
+ metadata: {
103
+ tokensUsed: 0,
104
+ reasoningSteps: 0,
105
+ intermediateResults: [],
106
+ error: error instanceof Error ? error.message : String(error)
107
+ }
108
+ };
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Process a task (implemented by subclasses)
114
+ * @param task - Task to process
115
+ * @returns Task result
116
+ */
117
+ abstract process(task: Task): Promise<TaskResult>;
118
+
119
+ /**
120
+ * Register a message handler
121
+ * @param handler - Message handler function
122
+ * @returns Unsubscribe function
123
+ */
124
+ onMessage(handler: (message: SwarmMessage) => void | Promise<void>): () => void {
125
+ this.messageHandlers.push(handler);
126
+
127
+ return () => {
128
+ const index = this.messageHandlers.indexOf(handler);
129
+ if (index > -1) {
130
+ this.messageHandlers.splice(index, 1);
131
+ }
132
+ };
133
+ }
134
+
135
+ /**
136
+ * Receive a message
137
+ * @param message - Message to receive
138
+ */
139
+ receiveMessage(message: SwarmMessage): void {
140
+ for (const handler of this.messageHandlers) {
141
+ try {
142
+ const result = handler(message);
143
+ if (result instanceof Promise) {
144
+ result.catch(error => {
145
+ console.error(`Error in message handler for agent ${this.id}:`, error);
146
+ });
147
+ }
148
+ } catch (error) {
149
+ console.error(`Error in message handler for agent ${this.id}:`, error);
150
+ }
151
+ }
152
+ }
153
+
154
+ /**
155
+ * Get agent status
156
+ * @returns Current status
157
+ */
158
+ getStatus(): AgentStatus {
159
+ return this.status;
160
+ }
161
+
162
+ /**
163
+ * Set agent status
164
+ * @param status - New status
165
+ */
166
+ setStatus(status: AgentStatus): void {
167
+ this.status = status;
168
+ }
169
+
170
+ /**
171
+ * Get current task IDs
172
+ * @returns Array of task IDs
173
+ */
174
+ getCurrentTasks(): string[] {
175
+ return Array.from(this.currentTasks);
176
+ }
177
+
178
+ /**
179
+ * Get performance metrics
180
+ * @returns Performance metrics
181
+ */
182
+ getPerformanceMetrics(): {
183
+ tasksCompleted: number;
184
+ averageQuality: number;
185
+ averageTimeMs: number;
186
+ successRate: number;
187
+ } {
188
+ if (this.performanceHistory.length === 0) {
189
+ return {
190
+ tasksCompleted: 0,
191
+ averageQuality: 0,
192
+ averageTimeMs: 0,
193
+ successRate: 0
194
+ };
195
+ }
196
+
197
+ const completed = this.performanceHistory.length;
198
+ const avgQuality = this.performanceHistory.reduce((sum, p) => sum + p.quality, 0) / completed;
199
+ const avgTime = this.performanceHistory.reduce((sum, p) => sum + p.timeMs, 0) / completed;
200
+ const successRate = this.performanceHistory.filter(p => p.quality > 0.5).length / completed;
201
+
202
+ return {
203
+ tasksCompleted: completed,
204
+ averageQuality: avgQuality,
205
+ averageTimeMs: avgTime,
206
+ successRate
207
+ };
208
+ }
209
+
210
+ /**
211
+ * Check if agent has a capability
212
+ * @param capabilityName - Capability name
213
+ * @returns True if agent has capability
214
+ */
215
+ hasCapability(capabilityName: string): boolean {
216
+ return this.getCapabilities().some(c => c.name === capabilityName);
217
+ }
218
+
219
+ /**
220
+ * Get capability confidence
221
+ * @param capabilityName - Capability name
222
+ * @returns Confidence level (0-1)
223
+ */
224
+ getCapabilityConfidence(capabilityName: string): number {
225
+ const cap = this.getCapabilities().find(c => c.name === capabilityName);
226
+ return cap?.confidence || 0;
227
+ }
228
+
229
+ /**
230
+ * Check if agent can handle a task
231
+ * @param task - Task to check
232
+ * @returns True if agent can handle task
233
+ */
234
+ canHandleTask(task: Task): boolean {
235
+ const requiredCaps = task.requirements.requiredCapabilities;
236
+ return requiredCaps.every(cap => this.hasCapability(cap));
237
+ }
238
+
239
+ /**
240
+ * Create a task result
241
+ * @param taskId - Task ID
242
+ * @param output - Output data
243
+ * @param confidence - Confidence level
244
+ * @param processingTimeMs - Processing time in ms
245
+ * @param metadata - Additional metadata
246
+ * @returns Task result
247
+ */
248
+ protected createTaskResult(
249
+ taskId: string,
250
+ output: unknown,
251
+ confidence: number,
252
+ processingTimeMs: number,
253
+ metadata: {
254
+ tokensUsed?: number;
255
+ reasoningSteps?: number;
256
+ intermediateResults?: unknown[];
257
+ } = {}
258
+ ): TaskResult {
259
+ return {
260
+ taskId,
261
+ agentId: this.id,
262
+ success: confidence > 0.5,
263
+ output,
264
+ confidence,
265
+ processingTimeMs,
266
+ metadata: {
267
+ tokensUsed: metadata.tokensUsed || 0,
268
+ reasoningSteps: metadata.reasoningSteps || 1,
269
+ intermediateResults: metadata.intermediateResults || []
270
+ }
271
+ };
272
+ }
273
+
274
+ /**
275
+ * Get agent type
276
+ * @returns Agent type
277
+ */
278
+ abstract getType(): string;
279
+
280
+ /**
281
+ * Get agent capabilities
282
+ * @returns Array of capabilities
283
+ */
284
+ abstract getCapabilities(): AgentCapability[];
285
+ }