@gotza02/seq-thinking 1.1.2 → 1.1.4

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 (75) hide show
  1. package/README.md +64 -95
  2. package/data/agents/1770106504306-dljh9ef.json +68 -0
  3. package/data/agents/1770106504310-4oarrst.json +58 -0
  4. package/data/agents/1770106540588-pvitt55.json +68 -0
  5. package/data/agents/1770106540595-z2ya871.json +58 -0
  6. package/data/agents/1770106710890-0e2naq1.json +68 -0
  7. package/data/agents/1770106710893-r076yxx.json +58 -0
  8. package/data/agents/1770109212161-4ybd0i7.json +68 -0
  9. package/data/agents/1770109212166-gkhya8h.json +58 -0
  10. package/data/agents/1770117726716-lrnm415.json +68 -0
  11. package/data/agents/1770117726719-w6hsf3v.json +58 -0
  12. package/data/sessions/1770100622009-5afiuyv.json +499 -0
  13. package/data/sessions/1770106504312-75zk750.json +107 -0
  14. package/data/sessions/1770106540597-z8e8soo.json +150 -0
  15. package/data/sessions/1770106710894-0kxgy5x.json +150 -0
  16. package/data/sessions/1770109212169-zpddeb9.json +150 -0
  17. package/data/sessions/1770117726720-frcwj99.json +150 -0
  18. package/dist/__tests__/sequential-thinking.test.js +21 -21
  19. package/dist/__tests__/sequential-thinking.test.js.map +1 -1
  20. package/dist/agents/base-agent.d.ts +1 -0
  21. package/dist/agents/base-agent.d.ts.map +1 -1
  22. package/dist/agents/base-agent.js +5 -3
  23. package/dist/agents/base-agent.js.map +1 -1
  24. package/dist/agents/meta-reasoning-agent.d.ts +4 -55
  25. package/dist/agents/meta-reasoning-agent.d.ts.map +1 -1
  26. package/dist/agents/meta-reasoning-agent.js +41 -333
  27. package/dist/agents/meta-reasoning-agent.js.map +1 -1
  28. package/dist/agents/synthesizer-agent.d.ts +3 -17
  29. package/dist/agents/synthesizer-agent.d.ts.map +1 -1
  30. package/dist/agents/synthesizer-agent.js +41 -139
  31. package/dist/agents/synthesizer-agent.js.map +1 -1
  32. package/dist/index.d.ts +1 -1
  33. package/dist/index.js +1 -1
  34. package/dist/mcp-server.d.ts.map +1 -1
  35. package/dist/mcp-server.js +10 -7
  36. package/dist/mcp-server.js.map +1 -1
  37. package/dist/real_world_test.d.ts +2 -0
  38. package/dist/real_world_test.d.ts.map +1 -0
  39. package/dist/real_world_test.js +78 -0
  40. package/dist/real_world_test.js.map +1 -0
  41. package/dist/sequential-thinking.d.ts +5 -5
  42. package/dist/sequential-thinking.d.ts.map +1 -1
  43. package/dist/sequential-thinking.js +68 -32
  44. package/dist/sequential-thinking.js.map +1 -1
  45. package/dist/swarm-coordinator.d.ts +1 -1
  46. package/dist/swarm-coordinator.d.ts.map +1 -1
  47. package/dist/swarm-coordinator.js +39 -13
  48. package/dist/swarm-coordinator.js.map +1 -1
  49. package/dist/utils/llm-adapter.d.ts +2 -2
  50. package/dist/utils/llm-adapter.d.ts.map +1 -1
  51. package/dist/utils/llm-adapter.js +57 -33
  52. package/dist/utils/llm-adapter.js.map +1 -1
  53. package/dist/utils/logger.d.ts +20 -0
  54. package/dist/utils/logger.d.ts.map +1 -0
  55. package/dist/utils/logger.js +49 -0
  56. package/dist/utils/logger.js.map +1 -0
  57. package/dist/utils/persistence.d.ts.map +1 -1
  58. package/dist/utils/persistence.js +4 -3
  59. package/dist/utils/persistence.js.map +1 -1
  60. package/package.json +1 -1
  61. package/real_world_test.log +200 -0
  62. package/real_world_test_dynamic.log +184 -0
  63. package/real_world_test_real.log +184 -0
  64. package/src/__tests__/sequential-thinking.test.ts +21 -21
  65. package/src/agents/base-agent.ts +6 -3
  66. package/src/agents/meta-reasoning-agent.ts +45 -403
  67. package/src/agents/synthesizer-agent.ts +48 -165
  68. package/src/index.ts +1 -1
  69. package/src/mcp-server.ts +10 -7
  70. package/src/real_world_test.ts +89 -0
  71. package/src/sequential-thinking.ts +87 -33
  72. package/src/swarm-coordinator.ts +41 -13
  73. package/src/utils/llm-adapter.ts +66 -32
  74. package/src/utils/logger.ts +56 -0
  75. package/src/utils/persistence.ts +4 -3
@@ -23,6 +23,7 @@ import {
23
23
  import { BaseAgent } from './agents/base-agent.js';
24
24
 
25
25
  import { PersistenceManager } from './utils/persistence.js';
26
+ import { Logger } from './utils/logger.js';
26
27
 
27
28
  /**
28
29
  * Registry to track all agents in the swarm
@@ -327,8 +328,9 @@ export class TaskAssigner {
327
328
 
328
329
  constructor(private registry: AgentRegistry) {}
329
330
 
330
- assignTask(task: Task, strategy: string = 'adaptive') {
331
+ assignTask(task: Task, strategy: string = 'adaptive', excludeAgentIds: string[] = []) {
331
332
  const availableAgents = this.registry.getAvailableAgents()
333
+ .filter(a => !excludeAgentIds.includes(a.config.id))
332
334
  .filter(a => this.hasRequiredCapabilities(a, task.requirements?.requiredCapabilities || task.requiredCapabilities || []));
333
335
 
334
336
  if (availableAgents.length === 0) return null;
@@ -568,24 +570,44 @@ export class SwarmCoordinator {
568
570
  }
569
571
 
570
572
  async executeTask(taskId: string, maxRetries: number = 3) {
571
- let retries = 0;
573
+ let globalRetries = 0;
572
574
  let lastError: any = null;
575
+ const maxGlobalRetries = maxRetries * 2; // Allow attempts across multiple agents
576
+ const failedAgents = new Set<string>();
573
577
 
574
- while (retries < maxRetries) {
578
+ while (globalRetries < maxGlobalRetries) {
575
579
  const task = this.taskQueue.getTask(taskId);
576
580
  if (!task) throw new Error(`Task not found: ${taskId}`);
577
581
 
582
+ // Auto-reassignment logic if not assigned
578
583
  if (!task.assignedAgentId) {
579
- throw new Error(`Task ${taskId} is not assigned to any agent`);
584
+ const agent = this.taskAssigner.assignTask(task, 'adaptive', Array.from(failedAgents));
585
+ if (agent) {
586
+ this.taskQueue.assignTask(task.id, agent.config.id);
587
+ this.registry.updateAgentStatus(agent.config.id, AgentStatus.BUSY);
588
+ Logger.info(`Reassigned task ${taskId} to agent ${agent.config.id}`);
589
+ } else {
590
+ // No more agents available
591
+ Logger.warn(`No suitable agent found for task ${taskId} (Agents tried: ${Array.from(failedAgents).join(', ')})`);
592
+ break;
593
+ }
594
+ }
595
+
596
+ // Check assignment validity
597
+ if (!task.assignedAgentId) {
598
+ break; // Should be handled above, but safety check
580
599
  }
581
600
 
582
601
  const agentState = this.registry.getAgent(task.assignedAgentId);
583
602
  if (!agentState || !agentState.instance) {
584
- throw new Error(`Agent execution instance not found for agent: ${task.assignedAgentId}`);
603
+ // Agent gone? Treat as failure
604
+ failedAgents.add(task.assignedAgentId);
605
+ task.assignedAgentId = null;
606
+ globalRetries++;
607
+ continue;
585
608
  }
586
609
 
587
610
  this.taskQueue.startTask(taskId);
588
- const startTime = Date.now();
589
611
 
590
612
  try {
591
613
  const result = await agentState.instance.execute(task);
@@ -595,20 +617,26 @@ export class SwarmCoordinator {
595
617
  return result;
596
618
  } catch (error) {
597
619
  lastError = error;
598
- retries++;
599
- console.warn(`Task ${taskId} failed (attempt ${retries}/${maxRetries}):`, error);
620
+ globalRetries++;
621
+ Logger.warn(`Task ${taskId} failed with agent ${task.assignedAgentId} (attempt ${globalRetries}/${maxGlobalRetries})`, { error });
600
622
 
601
- if (retries < maxRetries) {
602
- // Wait before retry
603
- await new Promise(resolve => setTimeout(resolve, 1000 * retries));
604
- // Reset status to ASSIGNED for retry
605
- task.status = TaskStatus.ASSIGNED;
623
+ // Mark agent as failed for this task and unassign
624
+ if (task.assignedAgentId) {
625
+ failedAgents.add(task.assignedAgentId);
626
+ this.registry.updateAgentStatus(task.assignedAgentId, AgentStatus.IDLE);
627
+ task.assignedAgentId = null; // Unassign to trigger reassignment
606
628
  }
629
+
630
+ task.status = TaskStatus.PENDING; // Reset status for next attempt
631
+
632
+ // Wait a bit before next loop
633
+ await new Promise(resolve => setTimeout(resolve, 500 * globalRetries));
607
634
  }
608
635
  }
609
636
 
610
637
  const processingTime = 0;
611
638
  this.taskQueue.failTask(taskId, String(lastError));
639
+ // Final cleanup if task is still assigned
612
640
  const task = this.taskQueue.getTask(taskId);
613
641
  if (task?.assignedAgentId) {
614
642
  this.registry.updateAgentStatus(task.assignedAgentId, AgentStatus.IDLE);
@@ -3,7 +3,11 @@
3
3
  * @module utils/llm-adapter
4
4
  */
5
5
 
6
- import { execSync } from 'child_process';
6
+ import { exec } from 'child_process';
7
+ import { promisify } from 'util';
8
+ import { Logger } from './logger.js';
9
+
10
+ const execAsync = promisify(exec);
7
11
 
8
12
  export interface LLMResponse {
9
13
  content: string;
@@ -12,56 +16,86 @@ export interface LLMResponse {
12
16
 
13
17
  export class LLMAdapter {
14
18
  /**
15
- * Main entry point to call an LLM based on provider
19
+ * Main entry point to call an LLM based on provider pool
16
20
  */
17
- static async call(prompt: string, systemPrompt?: string): Promise<LLMResponse> {
18
- const provider = process.env.provider || 'gemini';
19
- const combinedPrompt = systemPrompt ? `${systemPrompt}\n\nUser: ${prompt}` : prompt;
21
+ static async call(prompt: string, systemPrompt?: string, providerOverride?: string): Promise<LLMResponse> {
22
+ const providerEnv = process.env.provider || 'gemini';
23
+ const providers = providerOverride ? [providerOverride] : providerEnv.split(',').map(p => p.trim());
24
+
25
+ let lastError = '';
20
26
 
21
- // For testing/development: If MOCK_LLM is set, return mock data
22
- if (process.env.MOCK_LLM === 'true') {
23
- return { content: `[MOCK RESPONSE from ${provider}] I have analyzed your request: ${prompt.substring(0, 50)}...` };
24
- }
27
+ for (const provider of providers) {
28
+ const combinedPrompt = systemPrompt ? `${systemPrompt}\n\nUser: ${prompt}` : prompt;
25
29
 
26
- try {
27
- switch (provider.toLowerCase()) {
28
- case 'gemini':
29
- return this.safeExec(`gemini ask ${this.escapeShell(combinedPrompt)}`);
30
- case 'claude':
31
- return this.safeExec(`claude ${this.escapeShell(combinedPrompt)} --non-interactive`);
32
- case 'kimi':
33
- return this.safeExec(`kimi chat ${this.escapeShell(combinedPrompt)}`);
34
- case 'opencode':
35
- return this.safeExec(`opencode ask ${this.escapeShell(combinedPrompt)}`);
36
- default:
37
- return { content: '', error: `Unsupported provider: ${provider}` };
30
+ // For testing/development: If MOCK_LLM is set, return mock data
31
+ if (process.env.MOCK_LLM === 'true') {
32
+ Logger.debug('LLM Mock Call', { provider, promptLength: prompt.length });
33
+ return { content: `[MOCK RESPONSE from ${provider}] I have analyzed your request: ${prompt.substring(0, 50)}...` };
34
+ }
35
+
36
+ Logger.info('LLM Call initiated', { provider });
37
+
38
+ try {
39
+ let response: LLMResponse;
40
+ switch (provider.toLowerCase()) {
41
+ case 'gemini':
42
+ response = await this.safeExec(`gemini ask ${this.escapeShell(combinedPrompt)}`);
43
+ break;
44
+ case 'claude':
45
+ response = await this.safeExec(`claude ${this.escapeShell(combinedPrompt)} --non-interactive`);
46
+ break;
47
+ case 'kimi':
48
+ response = await this.safeExec(`kimi chat ${this.escapeShell(combinedPrompt)}`);
49
+ break;
50
+ case 'opencode':
51
+ response = await this.safeExec(`opencode ask ${this.escapeShell(combinedPrompt)}`);
52
+ break;
53
+ default:
54
+ response = { content: '', error: `Unsupported provider: ${provider}` };
55
+ }
56
+
57
+ if (response.content && !response.error) {
58
+ return response; // Success!
59
+ }
60
+
61
+ lastError = response.error || 'Unknown error';
62
+ Logger.warn(`Provider ${provider} failed, trying next...`, { error: lastError });
63
+
64
+ } catch (error: any) {
65
+ lastError = error.message;
66
+ Logger.error(`LLM Adapter Error with ${provider}`, { error: lastError });
38
67
  }
39
- } catch (error: any) {
40
- console.error(`LLM Call Error (${provider}):`, error.message);
41
- return { content: '', error: error.message };
42
68
  }
69
+
70
+ return { content: '', error: `All providers failed. Last error: ${lastError}` };
43
71
  }
44
72
 
45
73
  /**
46
74
  * Safely execute CLI command with timeout and existence check
47
75
  */
48
- private static safeExec(cmd: string): LLMResponse {
76
+ private static async safeExec(cmd: string): Promise<LLMResponse> {
49
77
  try {
50
78
  // Check if command base exists (first word)
51
79
  const baseCmd = cmd.split(' ')[0];
52
80
  try {
53
- execSync(`command -v ${baseCmd}`, { stdio: 'ignore' });
81
+ await execAsync(`command -v ${baseCmd}`);
54
82
  } catch {
55
- return { content: '', error: `CLI tool '${baseCmd}' not found or not in PATH. Please install and login.` };
83
+ const error = `CLI tool '${baseCmd}' not found or not in PATH. Please install and login.`;
84
+ Logger.warn('CLI tool missing', { baseCmd });
85
+ return { content: '', error };
56
86
  }
57
87
 
58
- const output = execSync(cmd, {
59
- encoding: 'utf8',
60
- stdio: ['ignore', 'pipe', 'pipe'],
61
- timeout: 30000 // 30 second timeout
88
+ const { stdout, stderr } = await execAsync(cmd, {
89
+ timeout: 60000 // 60 second timeout
62
90
  });
63
- return { content: output.trim() };
91
+
92
+ if (stderr && stderr.trim()) {
93
+ Logger.debug('CLI Stderr output', { baseCmd, stderr: stderr.substring(0, 100) });
94
+ }
95
+
96
+ return { content: stdout.trim() };
64
97
  } catch (error: any) {
98
+ Logger.error('Execution failed', { command: cmd.substring(0, 50), error: error.message });
65
99
  return { content: '', error: error.message };
66
100
  }
67
101
  }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Simple Structured Logging Utility
3
+ * @module utils/logger
4
+ */
5
+
6
+ export enum LogLevel {
7
+ DEBUG = 0,
8
+ INFO = 1,
9
+ WARN = 2,
10
+ ERROR = 3
11
+ }
12
+
13
+ export class Logger {
14
+ private static level: LogLevel = LogLevel.INFO;
15
+
16
+ static setLevel(level: LogLevel) {
17
+ this.level = level;
18
+ }
19
+
20
+ static debug(message: string, context: any = {}) {
21
+ if (this.level <= LogLevel.DEBUG) {
22
+ this.log('DEBUG', message, context);
23
+ }
24
+ }
25
+
26
+ static info(message: string, context: any = {}) {
27
+ if (this.level <= LogLevel.INFO) {
28
+ this.log('INFO', message, context);
29
+ }
30
+ }
31
+
32
+ static warn(message: string, context: any = {}) {
33
+ if (this.level <= LogLevel.WARN) {
34
+ this.log('WARN', message, context);
35
+ }
36
+ }
37
+
38
+ static error(message: string, context: any = {}) {
39
+ if (this.level <= LogLevel.ERROR) {
40
+ this.log('ERROR', message, context);
41
+ }
42
+ }
43
+
44
+ private static log(level: string, message: string, context: any) {
45
+ const timestamp = new Date().toISOString();
46
+ const logEntry = {
47
+ timestamp,
48
+ level,
49
+ message,
50
+ ...context
51
+ };
52
+
53
+ // Write to stderr to avoid interfering with MCP stdio protocol
54
+ process.stderr.write(JSON.stringify(logEntry) + '\n');
55
+ }
56
+ }
@@ -5,6 +5,7 @@
5
5
 
6
6
  import * as fs from 'fs/promises';
7
7
  import * as path from 'path';
8
+ import { Logger } from './logger.js';
8
9
 
9
10
  export class PersistenceManager {
10
11
  private baseDir: string;
@@ -23,7 +24,7 @@ export class PersistenceManager {
23
24
  await fs.mkdir(path.join(this.baseDir, dir), { recursive: true });
24
25
  }
25
26
  } catch (error) {
26
- console.error('Failed to initialize persistence directory:', error);
27
+ Logger.error('Failed to initialize persistence directory', { error });
27
28
  throw error;
28
29
  }
29
30
  }
@@ -38,7 +39,7 @@ export class PersistenceManager {
38
39
  const serializedData = this.serialize(data);
39
40
  await fs.writeFile(filePath, JSON.stringify(serializedData, null, 2), 'utf8');
40
41
  } catch (error) {
41
- console.error(`Failed to save ${collection}/${id}:`, error);
42
+ Logger.error(`Failed to save ${collection}/${id}`, { error });
42
43
  throw error;
43
44
  }
44
45
  }
@@ -53,7 +54,7 @@ export class PersistenceManager {
53
54
  return JSON.parse(content) as T;
54
55
  } catch (error: any) {
55
56
  if (error.code === 'ENOENT') return null;
56
- console.error(`Failed to load ${collection}/${id}:`, error);
57
+ Logger.error(`Failed to load ${collection}/${id}`, { error });
57
58
  throw error;
58
59
  }
59
60
  }