confused-ai-core 0.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 (114) hide show
  1. package/FEATURES.md +169 -0
  2. package/package.json +119 -0
  3. package/src/agent.ts +187 -0
  4. package/src/agentic/index.ts +87 -0
  5. package/src/agentic/runner.ts +386 -0
  6. package/src/agentic/types.ts +91 -0
  7. package/src/artifacts/artifact.ts +417 -0
  8. package/src/artifacts/index.ts +42 -0
  9. package/src/artifacts/media.ts +304 -0
  10. package/src/cli/index.ts +122 -0
  11. package/src/core/base-agent.ts +151 -0
  12. package/src/core/context-builder.ts +106 -0
  13. package/src/core/index.ts +8 -0
  14. package/src/core/schemas.ts +17 -0
  15. package/src/core/types.ts +158 -0
  16. package/src/create-agent.ts +309 -0
  17. package/src/debug-logger.ts +188 -0
  18. package/src/dx/agent.ts +88 -0
  19. package/src/dx/define-agent.ts +183 -0
  20. package/src/dx/dev-logger.ts +57 -0
  21. package/src/dx/index.ts +11 -0
  22. package/src/errors.ts +175 -0
  23. package/src/execution/engine.ts +522 -0
  24. package/src/execution/graph-builder.ts +362 -0
  25. package/src/execution/index.ts +8 -0
  26. package/src/execution/types.ts +257 -0
  27. package/src/execution/worker-pool.ts +308 -0
  28. package/src/extensions/index.ts +123 -0
  29. package/src/guardrails/allowlist.ts +155 -0
  30. package/src/guardrails/index.ts +17 -0
  31. package/src/guardrails/types.ts +159 -0
  32. package/src/guardrails/validator.ts +265 -0
  33. package/src/index.ts +74 -0
  34. package/src/knowledge/index.ts +5 -0
  35. package/src/knowledge/types.ts +52 -0
  36. package/src/learning/in-memory-store.ts +72 -0
  37. package/src/learning/index.ts +6 -0
  38. package/src/learning/types.ts +42 -0
  39. package/src/llm/cache.ts +300 -0
  40. package/src/llm/index.ts +22 -0
  41. package/src/llm/model-resolver.ts +81 -0
  42. package/src/llm/openai-provider.ts +313 -0
  43. package/src/llm/openrouter-provider.ts +29 -0
  44. package/src/llm/types.ts +131 -0
  45. package/src/memory/in-memory-store.ts +255 -0
  46. package/src/memory/index.ts +7 -0
  47. package/src/memory/types.ts +193 -0
  48. package/src/memory/vector-store.ts +251 -0
  49. package/src/observability/console-logger.ts +123 -0
  50. package/src/observability/index.ts +12 -0
  51. package/src/observability/metrics.ts +85 -0
  52. package/src/observability/otlp-exporter.ts +417 -0
  53. package/src/observability/tracer.ts +105 -0
  54. package/src/observability/types.ts +341 -0
  55. package/src/orchestration/agent-adapter.ts +33 -0
  56. package/src/orchestration/index.ts +34 -0
  57. package/src/orchestration/load-balancer.ts +151 -0
  58. package/src/orchestration/mcp-types.ts +59 -0
  59. package/src/orchestration/message-bus.ts +192 -0
  60. package/src/orchestration/orchestrator.ts +349 -0
  61. package/src/orchestration/pipeline.ts +66 -0
  62. package/src/orchestration/supervisor.ts +107 -0
  63. package/src/orchestration/swarm.ts +1099 -0
  64. package/src/orchestration/toolkit.ts +47 -0
  65. package/src/orchestration/types.ts +339 -0
  66. package/src/planner/classical-planner.ts +383 -0
  67. package/src/planner/index.ts +8 -0
  68. package/src/planner/llm-planner.ts +353 -0
  69. package/src/planner/types.ts +227 -0
  70. package/src/planner/validator.ts +297 -0
  71. package/src/production/circuit-breaker.ts +290 -0
  72. package/src/production/graceful-shutdown.ts +251 -0
  73. package/src/production/health.ts +333 -0
  74. package/src/production/index.ts +57 -0
  75. package/src/production/latency-eval.ts +62 -0
  76. package/src/production/rate-limiter.ts +287 -0
  77. package/src/production/resumable-stream.ts +289 -0
  78. package/src/production/types.ts +81 -0
  79. package/src/sdk/index.ts +374 -0
  80. package/src/session/db-driver.ts +50 -0
  81. package/src/session/in-memory-store.ts +235 -0
  82. package/src/session/index.ts +12 -0
  83. package/src/session/sql-store.ts +315 -0
  84. package/src/session/sqlite-store.ts +61 -0
  85. package/src/session/types.ts +153 -0
  86. package/src/tools/base-tool.ts +223 -0
  87. package/src/tools/browser-tool.ts +123 -0
  88. package/src/tools/calculator-tool.ts +265 -0
  89. package/src/tools/file-tools.ts +394 -0
  90. package/src/tools/github-tool.ts +432 -0
  91. package/src/tools/hackernews-tool.ts +187 -0
  92. package/src/tools/http-tool.ts +118 -0
  93. package/src/tools/index.ts +99 -0
  94. package/src/tools/jira-tool.ts +373 -0
  95. package/src/tools/notion-tool.ts +322 -0
  96. package/src/tools/openai-tool.ts +236 -0
  97. package/src/tools/registry.ts +131 -0
  98. package/src/tools/serpapi-tool.ts +234 -0
  99. package/src/tools/shell-tool.ts +118 -0
  100. package/src/tools/slack-tool.ts +327 -0
  101. package/src/tools/telegram-tool.ts +127 -0
  102. package/src/tools/types.ts +229 -0
  103. package/src/tools/websearch-tool.ts +335 -0
  104. package/src/tools/wikipedia-tool.ts +177 -0
  105. package/src/tools/yfinance-tool.ts +33 -0
  106. package/src/voice/index.ts +17 -0
  107. package/src/voice/voice-provider.ts +228 -0
  108. package/tests/artifact.test.ts +241 -0
  109. package/tests/circuit-breaker.test.ts +171 -0
  110. package/tests/health.test.ts +192 -0
  111. package/tests/llm-cache.test.ts +186 -0
  112. package/tests/rate-limiter.test.ts +161 -0
  113. package/tsconfig.json +29 -0
  114. package/vitest.config.ts +47 -0
@@ -0,0 +1,1099 @@
1
+ /**
2
+ * Agent Swarm Implementation
3
+ *
4
+ * Inspired by Kimi K2.5's Agent Swarm architecture with PARL (Parallel-Agent Reinforcement Learning)
5
+ *
6
+ * Key concepts:
7
+ * - Orchestrator decomposes tasks into parallelizable subtasks
8
+ * - Dynamic subagent instantiation (up to 100 sub-agents)
9
+ * - Parallel execution across coordinated steps
10
+ * - Critical path optimization for latency reduction
11
+ * - No predefined roles or hand-crafted workflows
12
+ */
13
+
14
+ import type { Agent, AgentInput, AgentOutput, AgentContext, EntityId } from '../core/types.js';
15
+ import { AgentState } from '../core/types.js';
16
+ import type { AgentRole, MessageBus } from './types.js';
17
+ import { MessageBusImpl } from './message-bus.js';
18
+ import { createRunnableAgent, type RunnableAgentConfig } from './agent-adapter.js';
19
+ import { AgentContextBuilder } from '../core/context-builder.js';
20
+ import { InMemoryStore } from '../memory/in-memory-store.js';
21
+ import { ToolRegistryImpl } from '../tools/registry.js';
22
+ import { ClassicalPlanner } from '../planner/classical-planner.js';
23
+ import { PlanningAlgorithm } from '../planner/types.js';
24
+ import type { LLMProvider, Message, GenerateOptions } from '../llm/types.js';
25
+ import { OpenAIProvider } from '../llm/openai-provider.js';
26
+ import { createOpenRouterProvider } from '../llm/openrouter-provider.js';
27
+ import { resolveModelString, isModelString, LLAMABARN_BASE_URL } from '../llm/model-resolver.js';
28
+ import { DebugLogger, createDebugLogger } from '../debug-logger.js';
29
+
30
+ /**
31
+ * Subagent template for dynamic instantiation
32
+ */
33
+ export interface SubagentTemplate {
34
+ readonly id: string;
35
+ readonly name: string;
36
+ readonly description: string;
37
+ readonly capabilities: string[];
38
+ readonly specialization: string;
39
+ readonly maxConcurrentTasks?: number;
40
+ }
41
+
42
+ /**
43
+ * A decomposed subtask ready for parallel execution
44
+ */
45
+ export interface Subtask {
46
+ readonly id: EntityId;
47
+ readonly description: string;
48
+ readonly specialization: string;
49
+ readonly dependencies: EntityId[];
50
+ readonly estimatedComplexity: number; // 1-10 scale
51
+ readonly input: AgentInput;
52
+ }
53
+
54
+ /**
55
+ * Execution stage for critical path optimization
56
+ */
57
+ export interface ExecutionStage {
58
+ readonly id: EntityId;
59
+ readonly subtasks: Subtask[];
60
+ readonly stageNumber: number;
61
+ readonly canParallelize: boolean;
62
+ }
63
+
64
+ /**
65
+ * Subagent instance created dynamically
66
+ */
67
+ export interface SubagentInstance {
68
+ readonly id: EntityId;
69
+ readonly templateId: string;
70
+ readonly agent: Agent;
71
+ readonly role: AgentRole;
72
+ assignedSubtasks: EntityId[];
73
+ readonly createdAt: Date;
74
+ active: boolean;
75
+ }
76
+
77
+ /**
78
+ * Result from a subtask execution
79
+ */
80
+ export interface SubtaskResult {
81
+ readonly subtaskId: EntityId;
82
+ readonly subagentId: EntityId;
83
+ readonly output: AgentOutput;
84
+ readonly executionTimeMs: number;
85
+ readonly completedAt: Date;
86
+ }
87
+
88
+ /**
89
+ * Critical path metrics for optimization
90
+ */
91
+ export interface CriticalPathMetrics {
92
+ readonly totalStages: number;
93
+ readonly criticalSteps: number;
94
+ readonly parallelEfficiency: number; // 0-1 scale
95
+ readonly orchestrationOverheadMs: number;
96
+ readonly slowestSubagentTimeMs: number;
97
+ }
98
+
99
+ /**
100
+ * Swarm execution result
101
+ */
102
+ export interface SwarmResult {
103
+ readonly taskId: EntityId;
104
+ readonly status: 'success' | 'partial' | 'failed';
105
+ readonly results: Map<EntityId, SubtaskResult>;
106
+ readonly aggregatedOutput: unknown;
107
+ readonly executionTimeMs: number;
108
+ readonly metrics: CriticalPathMetrics;
109
+ readonly subagentCount: number;
110
+ }
111
+
112
+ /**
113
+ * LLM configuration for swarm subagents
114
+ */
115
+ export interface SwarmLLMConfig {
116
+ /**
117
+ * LLM provider to use for subagents.
118
+ * Can be a provider instance, a model string (e.g., "openrouter:meta-llama/llama-3.3-70b-instruct"),
119
+ * or "default" to use placeholder logic.
120
+ */
121
+ readonly provider?: LLMProvider | string;
122
+ /**
123
+ * Model identifier for OpenRouter or other providers.
124
+ * Examples: "meta-llama/llama-3.3-70b-instruct", "openai/gpt-oss-20b"
125
+ */
126
+ readonly model?: string;
127
+ /** Temperature for LLM generation (default: 0.7) */
128
+ readonly temperature?: number;
129
+ /** Maximum tokens for LLM generation */
130
+ readonly maxTokens?: number;
131
+ /** OpenRouter API key (if using OpenRouter) */
132
+ readonly openRouterApiKey?: string;
133
+ /** OpenAI API key (if using OpenAI) */
134
+ readonly openAIApiKey?: string;
135
+ /** Base URL for custom endpoints */
136
+ readonly baseURL?: string;
137
+ /** LlamaBarn API key (if using LlamaBarn) */
138
+ readonly llamaBarnApiKey?: string;
139
+ }
140
+
141
+ /**
142
+ * Configuration for the swarm orchestrator
143
+ */
144
+ export interface SwarmConfig {
145
+ /** Maximum number of subagents that can be instantiated (default: 100) */
146
+ readonly maxSubagents?: number;
147
+ /** Maximum number of parallel execution stages (default: 1500) */
148
+ readonly maxStages?: number;
149
+ /** Timeout for individual subtask execution (default: 30000ms) */
150
+ readonly subtaskTimeoutMs?: number;
151
+ /** Enable critical path optimization (default: true) */
152
+ readonly enableCriticalPathOptimization?: boolean;
153
+ /** Minimum parallelism threshold to avoid serial collapse (default: 2) */
154
+ readonly minParallelism?: number;
155
+ /** Templates for dynamic subagent creation */
156
+ readonly subagentTemplates?: SubagentTemplate[];
157
+ /** LLM configuration for subagents */
158
+ readonly llm?: SwarmLLMConfig;
159
+ /** Enable debug logging (default: false) */
160
+ readonly debug?: boolean;
161
+ }
162
+
163
+ /**
164
+ * Task decomposition result
165
+ */
166
+ interface TaskDecomposition {
167
+ readonly subtasks: Subtask[];
168
+ readonly stages: ExecutionStage[];
169
+ readonly estimatedTotalComplexity: number;
170
+ }
171
+
172
+ /**
173
+ * Swarm Orchestrator - Inspired by Kimi K2.5's PARL architecture
174
+ *
175
+ * The orchestrator:
176
+ * 1. Decomposes complex tasks into parallelizable subtasks
177
+ * 2. Dynamically instantiates specialized subagents
178
+ * 3. Executes subtasks across stages optimizing for critical path
179
+ * 4. Aggregates results and manages subagent lifecycle
180
+ */
181
+ export class SwarmOrchestrator {
182
+ private config: Required<SwarmConfig>;
183
+ /** @internal Message bus for inter-agent communication */
184
+ messageBus: MessageBus;
185
+ private subagents: Map<EntityId, SubagentInstance> = new Map();
186
+ private templates: Map<string, SubagentTemplate> = new Map();
187
+ private _isRunning = false;
188
+ private taskCounter = 0;
189
+ private logger: DebugLogger;
190
+
191
+ private llmProvider: LLMProvider | undefined;
192
+
193
+ constructor(config: SwarmConfig = {}, messageBus?: MessageBus) {
194
+ this.config = {
195
+ maxSubagents: config.maxSubagents ?? 100,
196
+ maxStages: config.maxStages ?? 1500,
197
+ subtaskTimeoutMs: config.subtaskTimeoutMs ?? 30000,
198
+ enableCriticalPathOptimization: config.enableCriticalPathOptimization ?? true,
199
+ minParallelism: config.minParallelism ?? 2,
200
+ subagentTemplates: config.subagentTemplates ?? defaultTemplates,
201
+ llm: config.llm ?? {},
202
+ debug: config.debug ?? false,
203
+ };
204
+ this.messageBus = messageBus ?? new MessageBusImpl();
205
+ this.llmProvider = this.initializeLLMProvider(config.llm);
206
+ this.logger = createDebugLogger('Swarm', this.config.debug);
207
+
208
+ // Register templates
209
+ for (const template of this.config.subagentTemplates) {
210
+ this.templates.set(template.id, template);
211
+ }
212
+
213
+ this.logger.logStart('SwarmOrchestrator initialization', {
214
+ maxSubagents: this.config.maxSubagents,
215
+ maxStages: this.config.maxStages,
216
+ debug: this.config.debug,
217
+ });
218
+ }
219
+
220
+ /**
221
+ * Initialize LLM provider from configuration
222
+ */
223
+ private initializeLLMProvider(llmConfig?: SwarmLLMConfig): LLMProvider | undefined {
224
+ if (!llmConfig) {
225
+ return undefined;
226
+ }
227
+
228
+ // If a provider instance is passed directly, use it
229
+ if (llmConfig.provider && typeof llmConfig.provider === 'object') {
230
+ return llmConfig.provider;
231
+ }
232
+
233
+ // If a model string is passed (e.g., "openrouter:meta-llama/llama-3.3-70b-instruct")
234
+ if (typeof llmConfig.provider === 'string' && isModelString(llmConfig.provider)) {
235
+ const resolved = resolveModelString(llmConfig.provider);
236
+ if (resolved) {
237
+ return new OpenAIProvider({
238
+ apiKey: resolved.apiKey,
239
+ baseURL: resolved.baseURL,
240
+ model: resolved.model,
241
+ });
242
+ }
243
+ }
244
+
245
+ // If model is specified but no provider, try to infer from model string
246
+ if (llmConfig.model) {
247
+ // Check if model string is a provider:model format
248
+ if (isModelString(llmConfig.model)) {
249
+ const resolved = resolveModelString(llmConfig.model);
250
+ if (resolved) {
251
+ return new OpenAIProvider({
252
+ apiKey: resolved.apiKey ?? llmConfig.openRouterApiKey ?? llmConfig.openAIApiKey ?? llmConfig.llamaBarnApiKey,
253
+ baseURL: resolved.baseURL ?? llmConfig.baseURL,
254
+ model: resolved.model,
255
+ });
256
+ }
257
+ }
258
+
259
+ // If it looks like an OpenRouter model (contains "/")
260
+ if (llmConfig.model.includes('/')) {
261
+ return createOpenRouterProvider({
262
+ apiKey: llmConfig.openRouterApiKey ?? process.env.OPENROUTER_API_KEY ?? '',
263
+ model: llmConfig.model,
264
+ });
265
+ }
266
+
267
+ // Check for LlamaBarn GPT-OSS models
268
+ if (llmConfig.model.toLowerCase().includes('gpt-oss')) {
269
+ return new OpenAIProvider({
270
+ apiKey: llmConfig.llamaBarnApiKey ?? process.env.LLAMABARN_API_KEY ?? 'not-needed',
271
+ baseURL: llmConfig.baseURL ?? LLAMABARN_BASE_URL,
272
+ model: llmConfig.model,
273
+ });
274
+ }
275
+
276
+ // Default to OpenAI provider with the specified model
277
+ return new OpenAIProvider({
278
+ apiKey: llmConfig.openAIApiKey ?? process.env.OPENAI_API_KEY,
279
+ baseURL: llmConfig.baseURL,
280
+ model: llmConfig.model,
281
+ });
282
+ }
283
+
284
+ return undefined;
285
+ }
286
+
287
+ /**
288
+ * Execute a complex task using the swarm pattern
289
+ *
290
+ * This is the main entry point that:
291
+ * 1. Decomposes the task into subtasks
292
+ * 2. Creates execution stages based on dependencies
293
+ * 3. Dynamically instantiates subagents
294
+ * 4. Executes stages in parallel where possible
295
+ * 5. Aggregates results
296
+ */
297
+ async execute(task: AgentInput, parentContext?: AgentContext): Promise<SwarmResult> {
298
+ const startTime = Date.now();
299
+ const taskId = this.generateTaskId();
300
+
301
+ this.logger.logStart(`Task execution: ${taskId}`, {
302
+ prompt: task.prompt.slice(0, 80),
303
+ hasLLM: !!this.llmProvider,
304
+ });
305
+
306
+ if (!this._isRunning) {
307
+ await this.start();
308
+ }
309
+
310
+ try {
311
+ // Step 1: Decompose task into parallelizable subtasks
312
+ this.logger.logStep('Task decomposition', 1, 4, { taskId });
313
+ const decomposition = await this.decomposeTask(task, parentContext);
314
+ this.logger.logComplete('Task decomposition', undefined, {
315
+ subtaskCount: decomposition.subtasks.length,
316
+ stageCount: decomposition.stages.length,
317
+ });
318
+
319
+ // Step 2: Validate parallelism (avoid serial collapse)
320
+ if (this.config.enableCriticalPathOptimization) {
321
+ this.logger.logStep('Parallelism validation', 2, 4);
322
+ this.validateParallelism(decomposition);
323
+ }
324
+
325
+ // Step 3: Execute stages
326
+ this.logger.logStep('Stage execution', 3, 4, { totalStages: decomposition.stages.length });
327
+ const results = new Map<EntityId, SubtaskResult>();
328
+ let orchestrationOverheadMs = 0;
329
+ let slowestSubagentTimeMs = 0;
330
+
331
+ for (const stage of decomposition.stages) {
332
+ const stageStart = Date.now();
333
+ this.logger.logStart(`Stage ${stage.stageNumber}/${decomposition.stages.length}`, {
334
+ subtaskCount: stage.subtasks.length,
335
+ canParallelize: stage.canParallelize,
336
+ });
337
+
338
+ // Dynamically instantiate subagents for this stage
339
+ const stageSubagents = await this.instantiateSubagentsForStage(stage);
340
+ this.logger.debug(`Instantiated ${stageSubagents.length} subagents for stage ${stage.stageNumber}`);
341
+
342
+ // Execute subtasks in parallel
343
+ const stageResults = await this.executeStage(stage, stageSubagents);
344
+ const stageTime = Date.now() - stageStart;
345
+ this.logger.logComplete(`Stage ${stage.stageNumber}`, stageTime, {
346
+ resultsCount: stageResults.length,
347
+ });
348
+
349
+ // Track metrics
350
+ orchestrationOverheadMs += stageTime;
351
+ slowestSubagentTimeMs = Math.max(
352
+ slowestSubagentTimeMs,
353
+ ...stageResults.map(r => r.executionTimeMs)
354
+ );
355
+
356
+ // Store results
357
+ for (const result of stageResults) {
358
+ results.set(result.subtaskId, result);
359
+ }
360
+
361
+ // Clean up subagents that are no longer needed
362
+ await this.cleanupSubagents(stage, decomposition.stages);
363
+ }
364
+
365
+ // Step 4: Aggregate results
366
+ this.logger.logStep('Result aggregation', 4, 4);
367
+ const aggregatedOutput = await this.aggregateResults(results, task);
368
+
369
+ const executionTimeMs = Date.now() - startTime;
370
+
371
+ // Calculate critical path metrics
372
+ const metrics: CriticalPathMetrics = {
373
+ totalStages: decomposition.stages.length,
374
+ criticalSteps: this.calculateCriticalSteps(decomposition.stages),
375
+ parallelEfficiency: this.calculateParallelEfficiency(decomposition, results),
376
+ orchestrationOverheadMs,
377
+ slowestSubagentTimeMs,
378
+ };
379
+
380
+ const finalStatus = this.determineStatus(results, decomposition.subtasks.length);
381
+ this.logger.logComplete(`Task ${taskId}`, executionTimeMs, {
382
+ status: finalStatus,
383
+ stages: metrics.totalStages,
384
+ parallelEfficiency: `${(metrics.parallelEfficiency * 100).toFixed(1)}%`,
385
+ });
386
+
387
+ return {
388
+ taskId,
389
+ status: finalStatus,
390
+ results,
391
+ aggregatedOutput,
392
+ executionTimeMs,
393
+ metrics,
394
+ subagentCount: this.subagents.size,
395
+ };
396
+ } catch (error) {
397
+ this.logger.error(`Task ${taskId} failed`, undefined, {
398
+ error: error instanceof Error ? error.message : String(error),
399
+ });
400
+ throw error;
401
+ } finally {
402
+ // Cleanup all subagents
403
+ this.logger.debug('Cleaning up subagents...');
404
+ await this.cleanupAllSubagents();
405
+ this.logger.debug('Cleanup complete');
406
+ }
407
+ }
408
+
409
+ /**
410
+ * Decompose a complex task into parallelizable subtasks
411
+ *
412
+ * This mimics the PARL orchestrator's task decomposition capability
413
+ */
414
+ private async decomposeTask(
415
+ task: AgentInput,
416
+ _parentContext?: AgentContext
417
+ ): Promise<TaskDecomposition> {
418
+ // For now, use a simple rule-based decomposition
419
+ // In production, this would use an LLM to intelligently decompose
420
+ const subtasks = this.ruleBasedDecomposition(task);
421
+
422
+ // Build execution stages based on dependencies
423
+ const stages = this.buildExecutionStages(subtasks);
424
+
425
+ const estimatedTotalComplexity = subtasks.reduce(
426
+ (sum, s) => sum + s.estimatedComplexity,
427
+ 0
428
+ );
429
+
430
+ return { subtasks, stages, estimatedTotalComplexity };
431
+ }
432
+
433
+ /**
434
+ * Simple rule-based decomposition for demonstration
435
+ * In production, this would use LLM-based decomposition
436
+ */
437
+ private ruleBasedDecomposition(task: AgentInput): Subtask[] {
438
+ const subtasks: Subtask[] = [];
439
+
440
+ // Detect task type and decompose accordingly
441
+ const prompt = task.prompt.toLowerCase();
442
+
443
+ if (prompt.includes('research') || prompt.includes('analyze')) {
444
+ // Research task - parallelize by aspect
445
+ const aspects = ['background', 'current_state', 'future_trends', 'key_players'];
446
+ for (let i = 0; i < aspects.length; i++) {
447
+ subtasks.push({
448
+ id: `subtask-${i + 1}`,
449
+ description: `Research ${aspects[i]}`,
450
+ specialization: 'researcher',
451
+ dependencies: [],
452
+ estimatedComplexity: 5,
453
+ input: {
454
+ prompt: `Research the ${aspects[i]} of: ${task.prompt}`,
455
+ context: task.context,
456
+ },
457
+ });
458
+ }
459
+ } else if (prompt.includes('code') || prompt.includes('develop')) {
460
+ // Development task - parallelize by component
461
+ const components = ['architecture', 'implementation', 'testing', 'documentation'];
462
+ for (let i = 0; i < components.length; i++) {
463
+ const deps = i > 0 ? [`subtask-${i}`] : [];
464
+ subtasks.push({
465
+ id: `subtask-${i + 1}`,
466
+ description: `${components[i]} phase`,
467
+ specialization: 'developer',
468
+ dependencies: deps,
469
+ estimatedComplexity: 6,
470
+ input: {
471
+ prompt: `Handle the ${components[i]} for: ${task.prompt}`,
472
+ context: task.context,
473
+ },
474
+ });
475
+ }
476
+ } else {
477
+ // Generic task - create parallel subtasks
478
+ const subtaskCount = Math.min(3, this.config.maxSubagents);
479
+ for (let i = 0; i < subtaskCount; i++) {
480
+ subtasks.push({
481
+ id: `subtask-${i + 1}`,
482
+ description: `Subtask ${i + 1}`,
483
+ specialization: 'generalist',
484
+ dependencies: [],
485
+ estimatedComplexity: 4,
486
+ input: {
487
+ prompt: `Part ${i + 1} of: ${task.prompt}`,
488
+ context: task.context,
489
+ },
490
+ });
491
+ }
492
+ }
493
+
494
+ return subtasks;
495
+ }
496
+
497
+ /**
498
+ * Build execution stages from subtasks based on dependencies
499
+ */
500
+ private buildExecutionStages(subtasks: Subtask[]): ExecutionStage[] {
501
+ const stages: ExecutionStage[] = [];
502
+ const completed = new Set<EntityId>();
503
+ const remaining = new Set(subtasks.map(s => s.id));
504
+
505
+ let stageNumber = 1;
506
+
507
+ while (remaining.size > 0) {
508
+ // Find subtasks with all dependencies satisfied
509
+ const readySubtasks = subtasks.filter(
510
+ s => remaining.has(s.id) && s.dependencies.every(dep => completed.has(dep))
511
+ );
512
+
513
+ if (readySubtasks.length === 0) {
514
+ // Circular dependency or invalid dependency
515
+ throw new Error('Circular or invalid dependency detected in subtasks');
516
+ }
517
+
518
+ stages.push({
519
+ id: `stage-${stageNumber}`,
520
+ subtasks: readySubtasks,
521
+ stageNumber,
522
+ canParallelize: readySubtasks.length > 1,
523
+ });
524
+
525
+ for (const subtask of readySubtasks) {
526
+ completed.add(subtask.id);
527
+ remaining.delete(subtask.id);
528
+ }
529
+
530
+ stageNumber++;
531
+
532
+ // Safety check
533
+ if (stageNumber > this.config.maxStages) {
534
+ throw new Error(`Exceeded maximum stages (${this.config.maxStages})`);
535
+ }
536
+ }
537
+
538
+ return stages;
539
+ }
540
+
541
+ /**
542
+ * Validate that we have sufficient parallelism to avoid serial collapse
543
+ */
544
+ private validateParallelism(decomposition: TaskDecomposition): void {
545
+ const parallelStages = decomposition.stages.filter(s => s.canParallelize);
546
+ const avgParallelism =
547
+ parallelStages.reduce((sum, s) => sum + s.subtasks.length, 0) /
548
+ (parallelStages.length || 1);
549
+
550
+ if (avgParallelism < this.config.minParallelism && decomposition.stages.length > 1) {
551
+ console.warn(
552
+ `Warning: Low parallelism detected (${avgParallelism.toFixed(1)}). ` +
553
+ `Consider restructuring tasks for better parallelization.`
554
+ );
555
+ }
556
+ }
557
+
558
+ /**
559
+ * Dynamically instantiate subagents for a stage
560
+ */
561
+ private async instantiateSubagentsForStage(
562
+ stage: ExecutionStage
563
+ ): Promise<SubagentInstance[]> {
564
+ const instances: SubagentInstance[] = [];
565
+
566
+ for (const subtask of stage.subtasks) {
567
+ const template = this.templates.get(subtask.specialization);
568
+ if (!template) {
569
+ throw new Error(`Unknown specialization: ${subtask.specialization}`);
570
+ }
571
+
572
+ // Check if we can reuse an existing subagent
573
+ const existing = this.findReusableSubagent(template, subtask);
574
+
575
+ if (existing) {
576
+ this.logger.debug(`Reusing subagent ${existing.id} (${template.name}) for ${subtask.id}`);
577
+ existing.assignedSubtasks.push(subtask.id);
578
+ instances.push(existing);
579
+ } else {
580
+ // Create new subagent instance
581
+ this.logger.debug(`Creating new subagent (${template.name}) for ${subtask.id}`);
582
+ const instance = await this.createSubagent(template, subtask);
583
+ instances.push(instance);
584
+ this.subagents.set(instance.id, instance);
585
+ this.logger.debug(`Created subagent ${instance.id}`);
586
+ }
587
+ }
588
+
589
+ return instances;
590
+ }
591
+
592
+ /**
593
+ * Find a reusable subagent that can handle additional tasks
594
+ */
595
+ private findReusableSubagent(
596
+ template: SubagentTemplate,
597
+ _subtask: Subtask
598
+ ): SubagentInstance | undefined {
599
+ for (const instance of this.subagents.values()) {
600
+ if (
601
+ instance.templateId === template.id &&
602
+ instance.active &&
603
+ instance.assignedSubtasks.length < (template.maxConcurrentTasks ?? 5)
604
+ ) {
605
+ return instance;
606
+ }
607
+ }
608
+ return undefined;
609
+ }
610
+
611
+ /**
612
+ * Create a new subagent instance from a template
613
+ */
614
+ private async createSubagent(
615
+ template: SubagentTemplate,
616
+ subtask: Subtask
617
+ ): Promise<SubagentInstance> {
618
+ const id = `subagent-${template.id}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
619
+
620
+ // Create the agent using the adapter
621
+ const agentConfig: RunnableAgentConfig = {
622
+ name: `${template.name} (${id})`,
623
+ description: template.description,
624
+ run: async (input: AgentInput, ctx: AgentContext): Promise<AgentOutput> => {
625
+ // Subagent execution logic
626
+ const startTime = Date.now();
627
+ try {
628
+ // In a real implementation, this would use an LLM
629
+ // For now, return a placeholder result
630
+ const result = await this.executeSubagentLogic(template, input, ctx);
631
+
632
+ return {
633
+ result,
634
+ state: AgentState.COMPLETED,
635
+ metadata: {
636
+ startTime: new Date(startTime),
637
+ iterations: 1,
638
+ durationMs: Date.now() - startTime,
639
+ },
640
+ };
641
+ } catch (error) {
642
+ return {
643
+ result: error instanceof Error ? error.message : String(error),
644
+ state: AgentState.FAILED,
645
+ metadata: {
646
+ startTime: new Date(startTime),
647
+ iterations: 1,
648
+ durationMs: Date.now() - startTime,
649
+ },
650
+ };
651
+ }
652
+ },
653
+ };
654
+
655
+ const agent = createRunnableAgent(agentConfig);
656
+
657
+ const role: AgentRole = {
658
+ id: `role-${template.id}`,
659
+ name: template.name,
660
+ description: template.description,
661
+ responsibilities: template.capabilities,
662
+ permissions: {
663
+ canExecuteTools: true,
664
+ canAccessMemory: true,
665
+ canCreateSubAgents: false,
666
+ canModifyPlan: false,
667
+ },
668
+ canDelegate: false,
669
+ canCommunicateWith: [],
670
+ };
671
+
672
+ return {
673
+ id,
674
+ templateId: template.id,
675
+ agent,
676
+ role,
677
+ assignedSubtasks: [subtask.id],
678
+ createdAt: new Date(),
679
+ active: true,
680
+ };
681
+ }
682
+
683
+ /**
684
+ * System prompts for different subagent specializations
685
+ */
686
+ private getSystemPrompt(template: SubagentTemplate): string {
687
+ const basePrompt = `You are a specialized AI agent: ${template.name}.
688
+ ${template.description}
689
+
690
+ Your capabilities include: ${template.capabilities.join(', ')}.
691
+ Your specialization: ${template.specialization}
692
+
693
+ Provide a detailed, helpful response to the user's request.`;
694
+
695
+ // Add specialization-specific instructions
696
+ switch (template.specialization) {
697
+ case 'research':
698
+ return `${basePrompt}\n\nWhen researching:\n- Gather comprehensive information\n- Cite sources when possible\n- Synthesize findings clearly\n- Identify key trends and insights`;
699
+ case 'development':
700
+ return `${basePrompt}\n\nWhen developing:\n- Write clean, well-documented code\n- Follow best practices\n- Consider edge cases\n- Provide explanations for complex logic`;
701
+ case 'analysis':
702
+ return `${basePrompt}\n\nWhen analyzing:\n- Be thorough and data-driven\n- Identify patterns and correlations\n- Provide actionable insights\n- Support conclusions with evidence`;
703
+ case 'writing':
704
+ return `${basePrompt}\n\nWhen writing:\n- Create engaging, clear content\n- Adapt tone to the audience\n- Structure information logically\n- Edit for clarity and impact`;
705
+ case 'verification':
706
+ return `${basePrompt}\n\nWhen fact-checking:\n- Verify claims against reliable sources\n- Cross-reference information\n- Identify potential biases\n- Report confidence levels`;
707
+ default:
708
+ return basePrompt;
709
+ }
710
+ }
711
+
712
+ /**
713
+ * Execute subagent logic using LLM if configured, otherwise use placeholder
714
+ */
715
+ private async executeSubagentLogic(
716
+ template: SubagentTemplate,
717
+ input: AgentInput,
718
+ _ctx: AgentContext
719
+ ): Promise<unknown> {
720
+ // If no LLM provider is configured, use placeholder logic
721
+ if (!this.llmProvider) {
722
+ this.logger.debug(`Using placeholder logic for ${template.name} (no LLM configured)`);
723
+ return {
724
+ specialization: template.specialization,
725
+ capabilities: template.capabilities,
726
+ result: `Executed by ${template.name} (placeholder - no LLM configured)`,
727
+ input: input.prompt,
728
+ };
729
+ }
730
+
731
+ this.logger.debug(`Calling LLM for ${template.name}`, undefined, {
732
+ promptPreview: input.prompt.slice(0, 60),
733
+ model: this.config.llm?.model ?? 'unknown',
734
+ });
735
+
736
+ // Build messages for LLM
737
+ const messages: Message[] = [
738
+ { role: 'system', content: this.getSystemPrompt(template) },
739
+ { role: 'user', content: input.prompt },
740
+ ];
741
+
742
+ // Add context if available
743
+ if (input.context && Object.keys(input.context).length > 0) {
744
+ messages.push({
745
+ role: 'user',
746
+ content: `Context: ${JSON.stringify(input.context, null, 2)}`,
747
+ });
748
+ }
749
+
750
+ // Call LLM
751
+ const options: GenerateOptions = {
752
+ temperature: this.config.llm?.temperature ?? 0.7,
753
+ maxTokens: this.config.llm?.maxTokens,
754
+ };
755
+
756
+ this.logger.debug(`Sending ${messages.length} messages to LLM`, undefined, {
757
+ model: this.config.llm?.model ?? 'unknown',
758
+ });
759
+ const llmStartTime = Date.now();
760
+ const result = await this.llmProvider.generateText(messages, options);
761
+ this.logger.logComplete(`LLM call for ${template.name}`, Date.now() - llmStartTime, {
762
+ tokens: result.usage?.totalTokens,
763
+ });
764
+
765
+ return {
766
+ specialization: template.specialization,
767
+ capabilities: template.capabilities,
768
+ result: result.text,
769
+ model: this.config.llm?.model ?? 'unknown',
770
+ usage: result.usage,
771
+ };
772
+ }
773
+
774
+ /**
775
+ * Execute all subtasks in a stage in parallel
776
+ */
777
+ private async executeStage(
778
+ stage: ExecutionStage,
779
+ subagents: SubagentInstance[]
780
+ ): Promise<SubtaskResult[]> {
781
+ const promises = stage.subtasks.map(async subtask => {
782
+ const subagent = subagents.find(s => s.assignedSubtasks.includes(subtask.id));
783
+ if (!subagent) {
784
+ throw new Error(`No subagent found for subtask ${subtask.id}`);
785
+ }
786
+
787
+ const startTime = Date.now();
788
+ this.logger.logStart(`Subtask ${subtask.id}`, {
789
+ subagentId: subagent.id,
790
+ templateId: subagent.templateId,
791
+ });
792
+
793
+ // Create minimal context for subagent
794
+ const ctx = this.createMinimalContext(subagent.agent);
795
+
796
+ // Execute with timeout
797
+ const timeoutPromise = new Promise<AgentOutput>((_, reject) => {
798
+ setTimeout(
799
+ () => reject(new Error(`Subtask ${subtask.id} timed out after ${this.config.subtaskTimeoutMs}ms`)),
800
+ this.config.subtaskTimeoutMs
801
+ );
802
+ });
803
+
804
+ try {
805
+ const output = await Promise.race([
806
+ subagent.agent.run(subtask.input, ctx),
807
+ timeoutPromise,
808
+ ]);
809
+ this.logger.logComplete(`Subtask ${subtask.id}`, Date.now() - startTime, {
810
+ state: output.state,
811
+ });
812
+ return {
813
+ subtaskId: subtask.id,
814
+ subagentId: subagent.id,
815
+ output,
816
+ executionTimeMs: Date.now() - startTime,
817
+ completedAt: new Date(),
818
+ };
819
+ } catch (error) {
820
+ this.logger.error(`Subtask ${subtask.id} failed`, undefined, {
821
+ error: error instanceof Error ? error.message : String(error),
822
+ });
823
+ throw error;
824
+ }
825
+ });
826
+
827
+ return Promise.all(promises);
828
+ }
829
+
830
+ /**
831
+ * Cleanup subagents that are no longer needed
832
+ */
833
+ private async cleanupSubagents(
834
+ currentStage: ExecutionStage,
835
+ allStages: ExecutionStage[]
836
+ ): Promise<void> {
837
+ const currentSubtaskIds = new Set(currentStage.subtasks.map(s => s.id));
838
+ const futureSubtaskIds = new Set<EntityId>();
839
+
840
+ // Collect all future subtask IDs
841
+ let foundCurrent = false;
842
+ for (const stage of allStages) {
843
+ if (foundCurrent) {
844
+ for (const subtask of stage.subtasks) {
845
+ futureSubtaskIds.add(subtask.id);
846
+ }
847
+ }
848
+ if (stage.id === currentStage.id) {
849
+ foundCurrent = true;
850
+ }
851
+ }
852
+
853
+ // Find subagents that can be cleaned up
854
+ for (const instance of this.subagents.values()) {
855
+ const hasCurrentTasks = instance.assignedSubtasks.some(id => currentSubtaskIds.has(id));
856
+ const hasFutureTasks = instance.assignedSubtasks.some(id => futureSubtaskIds.has(id));
857
+
858
+ if (!hasCurrentTasks && !hasFutureTasks) {
859
+ instance.active = false;
860
+ this.subagents.delete(instance.id);
861
+ }
862
+ }
863
+ }
864
+
865
+ /**
866
+ * Cleanup all subagents
867
+ */
868
+ private async cleanupAllSubagents(): Promise<void> {
869
+ this.subagents.clear();
870
+ }
871
+
872
+ /**
873
+ * Aggregate results from all subtasks
874
+ */
875
+ private async aggregateResults(
876
+ results: Map<EntityId, SubtaskResult>,
877
+ originalTask: AgentInput
878
+ ): Promise<unknown> {
879
+ // In production, this would use an LLM to synthesize results
880
+ const outputs: Record<string, unknown> = {};
881
+
882
+ results.forEach((result, subtaskId) => {
883
+ outputs[subtaskId] = {
884
+ result: result.output.result,
885
+ executionTimeMs: result.executionTimeMs,
886
+ };
887
+ });
888
+
889
+ return {
890
+ originalTask: originalTask.prompt,
891
+ subtaskResults: outputs,
892
+ summary: `Completed ${results.size} subtasks`,
893
+ };
894
+ }
895
+
896
+ /**
897
+ * Calculate critical steps metric (inspired by Kimi's Critical Steps formula)
898
+ */
899
+ private calculateCriticalSteps(stages: ExecutionStage[]): number {
900
+ return stages.reduce((sum, stage) => {
901
+ // S_main: orchestration overhead per stage (constant)
902
+ const orchestrationOverhead = 1;
903
+
904
+ // max_i S_sub,i: slowest subagent in this stage
905
+ const maxSubagentSteps = stage.canParallelize ? Math.max(1, stage.subtasks.length * 0.5) : 1;
906
+
907
+ return sum + orchestrationOverhead + maxSubagentSteps;
908
+ }, 0);
909
+ }
910
+
911
+ /**
912
+ * Calculate parallel efficiency metric
913
+ */
914
+ private calculateParallelEfficiency(
915
+ decomposition: TaskDecomposition,
916
+ _results: Map<EntityId, SubtaskResult>
917
+ ): number {
918
+ if (decomposition.subtasks.length <= 1) return 1;
919
+
920
+ const totalSubtasks = decomposition.subtasks.length;
921
+ const parallelSubtasks = decomposition.stages
922
+ .filter(s => s.canParallelize)
923
+ .reduce((sum, s) => sum + s.subtasks.length, 0);
924
+
925
+ return parallelSubtasks / totalSubtasks;
926
+ }
927
+
928
+ /**
929
+ * Determine overall execution status
930
+ */
931
+ private determineStatus(
932
+ results: Map<EntityId, SubtaskResult>,
933
+ totalSubtasks: number
934
+ ): 'success' | 'partial' | 'failed' {
935
+ const completed = Array.from(results.values()).filter(
936
+ r => r.output.state === AgentState.COMPLETED
937
+ ).length;
938
+
939
+ if (completed === totalSubtasks) return 'success';
940
+ if (completed === 0) return 'failed';
941
+ return 'partial';
942
+ }
943
+
944
+ /**
945
+ * Generate unique task ID
946
+ */
947
+ private generateTaskId(): EntityId {
948
+ return `swarm-task-${Date.now()}-${++this.taskCounter}`;
949
+ }
950
+
951
+ /**
952
+ * Create minimal context for subagent execution
953
+ */
954
+ private createMinimalContext(agent: Agent): AgentContext {
955
+ return new AgentContextBuilder()
956
+ .withAgentId(agent.id)
957
+ .withMemory(new InMemoryStore())
958
+ .withTools(new ToolRegistryImpl())
959
+ .withPlanner(new ClassicalPlanner({ algorithm: PlanningAlgorithm.HIERARCHICAL }))
960
+ .build();
961
+ }
962
+
963
+ /**
964
+ * Start the orchestrator
965
+ */
966
+ async start(): Promise<void> {
967
+ this._isRunning = true;
968
+ }
969
+
970
+ /**
971
+ * Stop the orchestrator
972
+ */
973
+ async stop(): Promise<void> {
974
+ this._isRunning = false;
975
+ await this.cleanupAllSubagents();
976
+ }
977
+
978
+ /**
979
+ * Check if orchestrator is running
980
+ */
981
+ isRunning(): boolean {
982
+ return this._isRunning;
983
+ }
984
+
985
+ /**
986
+ * Get current subagent count
987
+ */
988
+ getSubagentCount(): number {
989
+ return this.subagents.size;
990
+ }
991
+
992
+ /**
993
+ * Register a custom subagent template
994
+ */
995
+ registerTemplate(template: SubagentTemplate): void {
996
+ this.templates.set(template.id, template);
997
+ }
998
+
999
+ /**
1000
+ * Get registered templates
1001
+ */
1002
+ getTemplates(): SubagentTemplate[] {
1003
+ return Array.from(this.templates.values());
1004
+ }
1005
+ }
1006
+
1007
+ /**
1008
+ * Default subagent templates
1009
+ */
1010
+ const defaultTemplates: SubagentTemplate[] = [
1011
+ {
1012
+ id: 'researcher',
1013
+ name: 'Research Agent',
1014
+ description: 'Specialized in research and information gathering',
1015
+ capabilities: ['web_search', 'data_analysis', 'synthesis'],
1016
+ specialization: 'research',
1017
+ maxConcurrentTasks: 5,
1018
+ },
1019
+ {
1020
+ id: 'developer',
1021
+ name: 'Developer Agent',
1022
+ description: 'Specialized in code development and technical tasks',
1023
+ capabilities: ['code_generation', 'debugging', 'testing'],
1024
+ specialization: 'development',
1025
+ maxConcurrentTasks: 3,
1026
+ },
1027
+ {
1028
+ id: 'analyst',
1029
+ name: 'Analyst Agent',
1030
+ description: 'Specialized in data analysis and insights',
1031
+ capabilities: ['data_processing', 'statistical_analysis', 'visualization'],
1032
+ specialization: 'analysis',
1033
+ maxConcurrentTasks: 4,
1034
+ },
1035
+ {
1036
+ id: 'writer',
1037
+ name: 'Writer Agent',
1038
+ description: 'Specialized in content creation and writing',
1039
+ capabilities: ['content_generation', 'editing', 'formatting'],
1040
+ specialization: 'writing',
1041
+ maxConcurrentTasks: 5,
1042
+ },
1043
+ {
1044
+ id: 'fact-checker',
1045
+ name: 'Fact Checker Agent',
1046
+ description: 'Specialized in verifying facts and accuracy',
1047
+ capabilities: ['verification', 'cross_reference', 'validation'],
1048
+ specialization: 'verification',
1049
+ maxConcurrentTasks: 10,
1050
+ },
1051
+ {
1052
+ id: 'generalist',
1053
+ name: 'Generalist Agent',
1054
+ description: 'General-purpose agent for various tasks',
1055
+ capabilities: ['general_task_execution', 'coordination'],
1056
+ specialization: 'general',
1057
+ maxConcurrentTasks: 5,
1058
+ },
1059
+ ];
1060
+
1061
+ /**
1062
+ * Create a swarm orchestrator with the given configuration
1063
+ */
1064
+ export function createSwarm(config?: SwarmConfig): SwarmOrchestrator {
1065
+ return new SwarmOrchestrator(config);
1066
+ }
1067
+
1068
+ /**
1069
+ * Create a swarm-based agent that can be used in the framework
1070
+ */
1071
+ export function createSwarmAgent(
1072
+ name: string,
1073
+ config?: SwarmConfig
1074
+ ): Agent {
1075
+ const swarm = new SwarmOrchestrator(config);
1076
+
1077
+ const run = async (input: AgentInput, _ctx: AgentContext): Promise<AgentOutput> => {
1078
+ const result = await swarm.execute(input);
1079
+
1080
+ return {
1081
+ result: {
1082
+ swarmResult: result,
1083
+ aggregated: result.aggregatedOutput,
1084
+ },
1085
+ state: result.status === 'success' ? AgentState.COMPLETED : AgentState.FAILED,
1086
+ metadata: {
1087
+ startTime: new Date(Date.now() - result.executionTimeMs),
1088
+ durationMs: result.executionTimeMs,
1089
+ iterations: result.metrics.totalStages,
1090
+ },
1091
+ };
1092
+ };
1093
+
1094
+ return createRunnableAgent({
1095
+ name,
1096
+ description: `Swarm-based agent using ${config?.maxSubagents ?? 100} max subagents`,
1097
+ run,
1098
+ });
1099
+ }