@gotza02/mathinking 2.9.3 → 2.9.5

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 (67) hide show
  1. package/dist/final-demo.js +0 -3
  2. package/dist/final-demo.js.map +1 -1
  3. package/dist/index.js +25 -15
  4. package/dist/index.js.map +1 -1
  5. package/dist/schemas/brain.schema.d.ts +70 -0
  6. package/dist/schemas/brain.schema.d.ts.map +1 -0
  7. package/dist/schemas/brain.schema.js +70 -0
  8. package/dist/schemas/brain.schema.js.map +1 -0
  9. package/dist/security.test.d.ts +2 -0
  10. package/dist/security.test.d.ts.map +1 -0
  11. package/dist/security.test.js +81 -0
  12. package/dist/security.test.js.map +1 -0
  13. package/dist/sse-server.js +39 -8
  14. package/dist/sse-server.js.map +1 -1
  15. package/dist/test-all.js +0 -20
  16. package/dist/test-all.js.map +1 -1
  17. package/dist/test-extended.js +0 -9
  18. package/dist/test-extended.js.map +1 -1
  19. package/dist/test-max-intelligence.d.ts +2 -0
  20. package/dist/test-max-intelligence.d.ts.map +1 -0
  21. package/dist/test-max-intelligence.js +52 -0
  22. package/dist/test-max-intelligence.js.map +1 -0
  23. package/dist/test-memory.js +0 -2
  24. package/dist/test-memory.js.map +1 -1
  25. package/dist/test-reflective.js +0 -6
  26. package/dist/test-reflective.js.map +1 -1
  27. package/dist/test-resilience.d.ts +2 -0
  28. package/dist/test-resilience.d.ts.map +1 -0
  29. package/dist/test-resilience.js +41 -0
  30. package/dist/test-resilience.js.map +1 -0
  31. package/dist/tools/orchestrator.d.ts +2 -47
  32. package/dist/tools/orchestrator.d.ts.map +1 -1
  33. package/dist/tools/orchestrator.js +224 -215
  34. package/dist/tools/orchestrator.js.map +1 -1
  35. package/dist/tools/sequential-thinking.d.ts +16 -95
  36. package/dist/tools/sequential-thinking.d.ts.map +1 -1
  37. package/dist/tools/sequential-thinking.js +313 -781
  38. package/dist/tools/sequential-thinking.js.map +1 -1
  39. package/dist/types/index.d.ts +18 -3
  40. package/dist/types/index.d.ts.map +1 -1
  41. package/dist/types/index.js +0 -3
  42. package/dist/types/index.js.map +1 -1
  43. package/dist/utils/dag.d.ts +0 -20
  44. package/dist/utils/dag.d.ts.map +1 -1
  45. package/dist/utils/dag.js +8 -48
  46. package/dist/utils/dag.js.map +1 -1
  47. package/dist/utils/memory.d.ts +5 -0
  48. package/dist/utils/memory.d.ts.map +1 -1
  49. package/dist/utils/memory.js +66 -60
  50. package/dist/utils/memory.js.map +1 -1
  51. package/dist/utils/mutex.d.ts +6 -0
  52. package/dist/utils/mutex.d.ts.map +1 -0
  53. package/dist/utils/mutex.js +22 -0
  54. package/dist/utils/mutex.js.map +1 -0
  55. package/dist/utils/resilience.d.ts +23 -0
  56. package/dist/utils/resilience.d.ts.map +1 -0
  57. package/dist/utils/resilience.js +82 -0
  58. package/dist/utils/resilience.js.map +1 -0
  59. package/dist/utils/tool-cache.d.ts +9 -0
  60. package/dist/utils/tool-cache.d.ts.map +1 -0
  61. package/dist/utils/tool-cache.js +23 -0
  62. package/dist/utils/tool-cache.js.map +1 -0
  63. package/dist/utils/vector-memory.d.ts +18 -0
  64. package/dist/utils/vector-memory.d.ts.map +1 -0
  65. package/dist/utils/vector-memory.js +86 -0
  66. package/dist/utils/vector-memory.js.map +1 -0
  67. package/package.json +22 -20
@@ -2,266 +2,178 @@ import { v4 as uuidv4 } from 'uuid';
2
2
  import * as fs from 'fs/promises';
3
3
  import * as path from 'path';
4
4
  import * as os from 'os';
5
+ import { LRUCache } from 'lru-cache';
6
+ import { Mutex } from '../utils/mutex.js';
5
7
  import { orchestratorManager } from './orchestrator.js';
6
- /**
7
- * Sequential Thinking Manager (The Brain)
8
- */
8
+ import { vectorMemory } from '../utils/vector-memory.js';
9
+ import { BrainInputSchema } from '../schemas/brain.schema.js';
9
10
  export class SequentialThinkingManager {
10
- sessions = new Map();
11
+ sessions = new LRUCache({
12
+ max: 100,
13
+ ttl: 1000 * 60 * 60 * 24 // 24 hours
14
+ });
11
15
  lastSessionId = null;
12
16
  storagePath;
13
17
  initialized = false;
14
18
  lastActionTimestamp = 0;
15
- MIN_DELAY_MS = 800; // Minimum delay between actions to prevent flooding
19
+ MIN_DELAY_MS = 500;
20
+ mutex = new Mutex();
16
21
  constructor() {
17
- // Set up persistent storage in user's home directory
18
22
  this.storagePath = path.join(os.homedir(), '.mathinking', 'sessions.json');
19
23
  }
20
- /**
21
- * Helper to add a delay
22
- */
23
24
  sleep(ms) {
24
25
  return new Promise((resolve) => setTimeout(resolve, ms));
25
26
  }
26
- /**
27
- * Initialize storage directory and load existing sessions
28
- */
29
- async initStorage(force = false) {
27
+ async _initStorage(force = false) {
30
28
  if (this.initialized && !force)
31
29
  return;
32
30
  try {
33
31
  const dir = path.dirname(this.storagePath);
34
32
  await fs.mkdir(dir, { recursive: true });
35
33
  const data = await fs.readFile(this.storagePath, 'utf8');
36
- let savedSessions;
37
- try {
38
- savedSessions = JSON.parse(data);
39
- }
40
- catch (parseError) {
41
- if (!this.initialized) {
42
- console.warn('[Brain] Storage file is invalid or empty, initializing with empty sessions.');
43
- }
44
- savedSessions = {};
45
- }
46
- // Merge or replace sessions
47
- let newestTimestamp = 0;
34
+ const savedSessions = JSON.parse(data);
48
35
  for (const [id, session] of Object.entries(savedSessions)) {
49
36
  this.sessions.set(id, session);
50
- // Track the truly latest session by updatedAt
51
- const ts = new Date(session.updatedAt).getTime();
52
- if (ts > newestTimestamp) {
53
- newestTimestamp = ts;
54
- this.lastSessionId = id;
55
- }
56
- }
57
- if (!this.initialized) {
58
- console.error(`[Brain] Loaded ${this.sessions.size} sessions from storage.`);
37
+ this.lastSessionId = id;
59
38
  }
60
39
  }
61
40
  catch (error) {
62
- // If file doesn't exist or is invalid, start with empty map
63
- if (error.code !== 'ENOENT') {
64
- console.error('[Brain] Storage initialization error:', error);
65
- }
41
+ // Ignore error if file doesn't exist
66
42
  }
67
43
  finally {
68
44
  this.initialized = true;
69
45
  }
70
46
  }
71
- /**
72
- * Save all sessions to persistent storage
73
- */
74
- async saveToStorage() {
47
+ async initStorage(force = false) {
48
+ await this.mutex.dispatch(() => this._initStorage(force));
49
+ }
50
+ async _saveToStorage() {
75
51
  try {
76
- // Auto-pruning: Keep only the 100 most recent sessions
77
- if (this.sessions.size > 100) {
78
- const sortedSessions = Array.from(this.sessions.entries()).sort((a, b) => new Date(b[1].updatedAt).getTime() - new Date(a[1].updatedAt).getTime());
79
- const toKeep = sortedSessions.slice(0, 100);
80
- this.sessions = new Map(toKeep);
81
- console.error(`[Brain] Pruned sessions. Kept the 100 most recent.`);
52
+ const entries = {};
53
+ for (const [key, value] of this.sessions.entries()) {
54
+ entries[key] = value;
82
55
  }
83
- const data = JSON.stringify(Object.fromEntries(this.sessions), null, 2);
56
+ const data = JSON.stringify(entries, null, 2);
84
57
  await fs.writeFile(this.storagePath, data, 'utf8');
85
58
  }
86
59
  catch (error) {
87
- console.error('[Brain] Failed to save sessions:', error);
60
+ console.error('[Brain] Save failed:', error);
88
61
  }
89
62
  }
90
- /**
91
- * Process a thinking action
92
- */
63
+ async saveToStorage() {
64
+ await this.mutex.dispatch(() => this._saveToStorage());
65
+ }
93
66
  async process(input) {
94
- // Clean up mangled actions and extract hidden parameters (some LLMs inject XML into the string)
95
- let action = input.action;
96
- if (action.includes('<')) {
97
- // Extract sessionId if it's hidden inside the action string
98
- const sessionMatch = action.match(/<arg_value>(.*?)($|<)/);
99
- if (sessionMatch && (!input.sessionId || input.sessionId === '')) {
100
- input.sessionId = sessionMatch[1].trim();
101
- console.error(`[Brain] Recovered sessionId from mangled action: ${input.sessionId}`);
102
- }
103
- action = action.split('<')[0].trim();
104
- }
105
- // Rate limiting / Flood protection
106
- const now = Date.now();
107
- const elapsed = now - this.lastActionTimestamp;
108
- if (elapsed < this.MIN_DELAY_MS) {
109
- const waitTime = this.MIN_DELAY_MS - elapsed;
110
- console.error(`[Brain] Rate limiting: Sleeping for ${waitTime}ms to prevent flooding...`);
111
- await this.sleep(waitTime);
112
- }
113
- this.lastActionTimestamp = Date.now();
114
- await this.initStorage(true);
115
- let result;
116
- switch (action) {
117
- case 'start_session':
118
- result = this.startSession(input);
119
- break;
120
- case 'add_thought':
121
- result = this.addThought(input);
122
- break;
123
- case 'create_branch':
124
- result = this.createBranch(input);
125
- break;
126
- case 'revise_thought':
127
- result = this.reviseThought(input);
128
- break;
129
- case 'set_hypothesis':
130
- result = this.setHypothesis(input);
131
- break;
132
- case 'verify_hypothesis':
133
- result = this.verifyHypothesis(input);
134
- break;
135
- case 'adjust_total_thoughts':
136
- result = this.adjustTotalThoughts(input);
137
- break;
138
- case 'conclude':
139
- result = this.conclude(input);
140
- break;
141
- case 'get_status':
142
- result = this.getStatus(input);
143
- break;
144
- case 'get_history':
145
- result = this.getHistory(input);
146
- break;
147
- case 'clear_history':
148
- result = this.clearHistory();
149
- break;
150
- case 'delete_session':
151
- result = this.deleteSession(input);
152
- break;
153
- case 'list_sessions':
154
- result = this.listSessions();
155
- break;
156
- case 'delete_thought':
157
- result = this.deleteThought(input);
158
- break;
159
- case 'self_critique':
160
- result = this.selfCritique(input);
161
- break;
162
- case 'summarize_history':
163
- result = this.summarizeHistory(input);
164
- break;
165
- case 'merge_branches':
166
- result = this.mergeBranches(input);
167
- break;
168
- case 'execute_conclusion':
169
- result = await this.executeConclusion(input);
170
- break;
171
- default:
172
- result = {
67
+ let executeConclusionInput = null;
68
+ const result = await this.mutex.dispatch(async () => {
69
+ await this._initStorage(false);
70
+ const validationResult = BrainInputSchema.safeParse(input);
71
+ if (!validationResult.success) {
72
+ return {
173
73
  success: false,
174
- sessionId: input.sessionId || '',
74
+ sessionId: '',
175
75
  currentStep: 0,
176
76
  totalThoughts: 0,
177
77
  status: 'in_progress',
178
- message: `Unknown action: ${input.action}`,
179
- nextSuggestedActions: ['start_session', 'list_sessions']
78
+ message: `Validation Error: ${validationResult.error.message}`
180
79
  };
181
- }
182
- // Persist changes after every action
183
- if (result.success) {
184
- await this.saveToStorage();
80
+ }
81
+ const validatedInput = validationResult.data;
82
+ let innerResult;
83
+ const now = Date.now();
84
+ if (now - this.lastActionTimestamp < this.MIN_DELAY_MS) {
85
+ await this.sleep(200);
86
+ }
87
+ this.lastActionTimestamp = Date.now();
88
+ // Defer execution to avoid deadlock
89
+ if (validatedInput.action === 'execute_conclusion') {
90
+ executeConclusionInput = validatedInput;
91
+ // Return a temporary pending result
92
+ return {
93
+ success: true,
94
+ sessionId: validatedInput.sessionId || '',
95
+ currentStep: 0,
96
+ totalThoughts: 0,
97
+ status: 'in_progress',
98
+ message: 'Preparing execution...'
99
+ };
100
+ }
101
+ switch (validatedInput.action) {
102
+ case 'start_session':
103
+ innerResult = this.startSession(validatedInput);
104
+ break;
105
+ case 'add_thought':
106
+ innerResult = this.addThought(validatedInput);
107
+ break;
108
+ case 'create_branch':
109
+ innerResult = this.createBranch(validatedInput);
110
+ break;
111
+ case 'generate_options':
112
+ innerResult = this.generateOptions(validatedInput);
113
+ break;
114
+ case 'evaluate_options':
115
+ innerResult = this.evaluateOptions(validatedInput);
116
+ break;
117
+ case 'select_option':
118
+ innerResult = this.selectOption(validatedInput);
119
+ break;
120
+ case 'revise_thought':
121
+ innerResult = this.reviseThought(validatedInput);
122
+ break;
123
+ case 'set_hypothesis':
124
+ innerResult = this.setHypothesis(validatedInput);
125
+ break;
126
+ case 'verify_hypothesis':
127
+ innerResult = this.verifyHypothesis(validatedInput);
128
+ break;
129
+ case 'conclude':
130
+ innerResult = this.conclude(validatedInput);
131
+ break;
132
+ // execute_conclusion handled outside
133
+ case 'reflect':
134
+ innerResult = this.reflect(validatedInput);
135
+ break;
136
+ case 'replan':
137
+ innerResult = await this.replan(validatedInput);
138
+ break;
139
+ case 'decompose':
140
+ innerResult = this.decompose(validatedInput);
141
+ break;
142
+ case 'research':
143
+ innerResult = this.research(validatedInput);
144
+ break;
145
+ case 'get_history':
146
+ innerResult = this.getHistory(validatedInput);
147
+ break;
148
+ default: innerResult = this.startSession(validatedInput);
149
+ }
150
+ if (innerResult.success)
151
+ await this._saveToStorage();
152
+ return innerResult;
153
+ });
154
+ if (executeConclusionInput) {
155
+ const conclusionResult = await this.executeConclusion(executeConclusionInput);
156
+ // We must save again because executeConclusion modifies state (adds reflection)
157
+ // But executeConclusion calls process('reflect') internally, which acquires lock & saves.
158
+ // So we don't need to save here.
159
+ return conclusionResult;
185
160
  }
186
161
  return result;
187
162
  }
188
- /**
189
- * Start a new thinking session
190
- */
191
- startSession(input) {
192
- if (!input.problemStatement) {
193
- return this.errorResponse('', 'Problem statement is required to start a session');
194
- }
195
- const sessionId = uuidv4();
196
- const totalThoughts = input.totalThoughts || 5;
197
- const now = new Date().toISOString();
198
- const session = {
199
- sessionId,
200
- problemStatement: input.problemStatement,
201
- totalThoughts,
202
- currentStep: 0,
203
- thoughtHistory: [],
204
- branches: [],
205
- status: 'in_progress',
206
- createdAt: now,
207
- updatedAt: now
208
- };
209
- this.sessions.set(sessionId, session);
210
- this.lastSessionId = sessionId;
211
- return {
212
- success: true,
213
- sessionId,
214
- currentStep: 0,
215
- totalThoughts,
216
- status: 'in_progress',
217
- message: `Thinking session started. You have ${totalThoughts} thinking steps planned. You can use "latest" as sessionId in subsequent calls.`,
218
- nextSuggestedActions: ['add_thought (type: initial_analysis)', 'adjust_total_thoughts']
219
- };
220
- }
221
- /**
222
- * List all available sessions
223
- */
224
- listSessions() {
225
- const sessionList = Array.from(this.sessions.values())
226
- .sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime())
227
- .map((s) => `• [${s.status}] ${s.sessionId}: ${s.problemStatement.substring(0, 50)}... (${s.currentStep}/${s.totalThoughts})`)
228
- .join('\n');
229
- return {
230
- success: true,
231
- sessionId: this.lastSessionId || '',
232
- currentStep: 0,
233
- totalThoughts: 0,
234
- status: 'completed',
235
- message: sessionList.length > 0
236
- ? `Available Thinking Sessions (Newest first):\n${sessionList}`
237
- : 'No thinking sessions found.'
238
- };
239
- }
240
- /**
241
- * Add a new thought to the session
242
- */
243
- addThought(input) {
163
+ decompose(input) {
244
164
  const session = this.getSession(input.sessionId);
245
165
  if (!session)
246
- return this.errorResponse(input.sessionId || '', 'Session not found');
247
- if (!input.thought)
248
- return this.errorResponse(session.sessionId, 'Thought content is required');
166
+ return { success: false, message: 'Session not found' };
249
167
  session.currentStep++;
250
- const thoughtId = uuidv4();
251
168
  const thought = {
252
- id: thoughtId,
169
+ id: uuidv4(),
253
170
  stepNumber: session.currentStep,
254
- thought: input.thought,
255
- thoughtType: input.thoughtType || 'initial_analysis',
171
+ thought: `DECOMPOSITION: ${input.thought}`,
172
+ thoughtType: 'decomposition',
256
173
  timestamp: new Date().toISOString(),
257
- confidence: input.confidence ?? 70,
258
- parentId: input.branchFromThoughtId
174
+ confidence: 90
259
175
  };
260
176
  session.thoughtHistory.push(thought);
261
- session.updatedAt = new Date().toISOString();
262
- if (session.currentStep >= session.totalThoughts) {
263
- session.status = 'awaiting_verification';
264
- }
265
177
  return {
266
178
  success: true,
267
179
  sessionId: session.sessionId,
@@ -269,410 +181,199 @@ export class SequentialThinkingManager {
269
181
  totalThoughts: session.totalThoughts,
270
182
  status: session.status,
271
183
  thought,
272
- message: this.getThoughtMessage(session, thought),
273
- nextSuggestedActions: this.getSuggestedActions(session, thought)
184
+ message: 'Query decomposed. Please add sub-thoughts for each component.'
274
185
  };
275
186
  }
276
- /**
277
- * Create a branch for exploring alternative thought paths
278
- */
279
- createBranch(input) {
187
+ research(input) {
280
188
  const session = this.getSession(input.sessionId);
281
189
  if (!session)
282
- return this.errorResponse(input.sessionId || '', 'Session not found');
283
- if (!input.branchFromThoughtId)
284
- return this.errorResponse(session.sessionId, 'branchFromThoughtId is required');
285
- const parentThought = session.thoughtHistory.find((t) => t.id === input.branchFromThoughtId);
286
- if (!parentThought)
287
- return this.errorResponse(session.sessionId, 'Parent thought not found');
288
- const branchId = uuidv4();
289
- const branchLabel = input.branchLabel || `Branch ${session.branches.length + 1}`;
290
- const branch = {
291
- id: branchId,
292
- label: branchLabel,
293
- parentThoughtId: input.branchFromThoughtId,
294
- thoughtIds: [],
295
- status: 'active'
296
- };
297
- session.branches.push(branch);
298
- session.updatedAt = new Date().toISOString();
299
- if (input.thought) {
300
- session.currentStep++;
301
- const thoughtId = uuidv4();
302
- const thought = {
303
- id: thoughtId,
304
- stepNumber: session.currentStep,
305
- thought: input.thought,
306
- thoughtType: 'branch_exploration',
307
- timestamp: new Date().toISOString(),
308
- parentId: input.branchFromThoughtId,
309
- branchLabel,
310
- confidence: input.confidence ?? 60
311
- };
312
- session.thoughtHistory.push(thought);
313
- branch.thoughtIds.push(thoughtId);
314
- return {
315
- success: true,
316
- sessionId: session.sessionId,
317
- currentStep: session.currentStep,
318
- totalThoughts: session.totalThoughts,
319
- status: session.status,
320
- thought,
321
- branches: session.branches,
322
- message: `Created branch "${branchLabel}" from thought #${parentThought.stepNumber}.`,
323
- nextSuggestedActions: ['add_thought', 'create_branch']
324
- };
325
- }
326
- return {
327
- success: true,
328
- sessionId: session.sessionId,
329
- currentStep: session.currentStep,
330
- totalThoughts: session.totalThoughts,
331
- status: session.status,
332
- branches: session.branches,
333
- message: `Created branch "${branchLabel}" from thought #${parentThought.stepNumber}. Ready for thoughts.`,
334
- nextSuggestedActions: ['add_thought']
190
+ return { success: false, message: 'Session not found' };
191
+ const topic = input.thought || session.problemStatement;
192
+ const planId = 'research-' + uuidv4().substring(0, 8);
193
+ const plan = {
194
+ planId,
195
+ name: `Research: ${topic.substring(0, 30)}...`,
196
+ tasks: [
197
+ {
198
+ id: 'search_google',
199
+ name: 'Google Search',
200
+ toolName: 'web_search',
201
+ toolInput: { query: topic, freshness: 'year' },
202
+ dependencies: []
203
+ },
204
+ {
205
+ id: 'search_brave',
206
+ name: 'Brave Search',
207
+ toolName: 'web_search',
208
+ toolInput: { query: topic, freshness: 'month' },
209
+ dependencies: [],
210
+ runIf: '${search_google.results.length} === 0' // Fallback
211
+ },
212
+ {
213
+ id: 'save_memory',
214
+ name: 'Save Findings',
215
+ toolName: 'memory_save',
216
+ toolInput: { key: `Research: ${topic}`, value: '${search_google.results}' },
217
+ dependencies: ['search_google']
218
+ }
219
+ ]
335
220
  };
336
- }
337
- /**
338
- * Revise a previous thought
339
- */
340
- reviseThought(input) {
341
- const session = this.getSession(input.sessionId);
342
- if (!session)
343
- return this.errorResponse(input.sessionId || '', 'Session not found');
344
- if (!input.reviseThoughtId)
345
- return this.errorResponse(session.sessionId, 'reviseThoughtId is required');
346
- if (!input.thought)
347
- return this.errorResponse(session.sessionId, 'New thought content is required');
348
- const originalThought = session.thoughtHistory.find((t) => t.id === input.reviseThoughtId);
349
- if (!originalThought)
350
- return this.errorResponse(session.sessionId, 'Original thought not found');
351
221
  session.currentStep++;
352
- const thoughtId = uuidv4();
353
- const revisedThought = {
354
- id: thoughtId,
222
+ const thought = {
223
+ id: uuidv4(),
355
224
  stepNumber: session.currentStep,
356
- thought: input.thought,
357
- thoughtType: 'revision',
225
+ thought: `RESEARCH PLAN: Generated plan to investigate "${topic}"`,
226
+ thoughtType: 'plan',
358
227
  timestamp: new Date().toISOString(),
359
- isRevision: true,
360
- revisedFromId: input.reviseThoughtId,
361
- confidence: input.confidence ?? 75,
362
- parentId: originalThought.parentId
228
+ confidence: 100,
229
+ metadata: { planId }
363
230
  };
364
- session.thoughtHistory.push(revisedThought);
365
- session.updatedAt = new Date().toISOString();
231
+ session.thoughtHistory.push(thought);
366
232
  return {
367
233
  success: true,
368
234
  sessionId: session.sessionId,
369
235
  currentStep: session.currentStep,
370
236
  totalThoughts: session.totalThoughts,
371
237
  status: session.status,
372
- thought: revisedThought,
373
- message: `Revised thought #${originalThought.stepNumber}.`,
374
- nextSuggestedActions: ['add_thought', 'verify_hypothesis']
238
+ thought,
239
+ executionPlan: plan,
240
+ message: 'Research plan generated. Use execute_conclusion to run it.'
375
241
  };
376
242
  }
377
- /**
378
- * Set a hypothesis that needs verification
379
- */
380
- setHypothesis(input) {
243
+ async replan(input) {
381
244
  const session = this.getSession(input.sessionId);
382
245
  if (!session)
383
- return this.errorResponse(input.sessionId || '', 'Session not found');
384
- if (!input.hypothesis)
385
- return this.errorResponse(session.sessionId, 'Hypothesis content is required');
246
+ return { success: false, message: 'Session not found' };
247
+ console.error(`[Brain] Strategic Re-plan requested for session: ${session.sessionId}`);
386
248
  session.currentStep++;
387
- const thoughtId = uuidv4();
388
- const hypothesisThought = {
389
- id: thoughtId,
249
+ const failureThought = {
250
+ id: uuidv4(),
390
251
  stepNumber: session.currentStep,
391
- thought: input.thought || `Hypothesis: ${input.hypothesis}`,
392
- thoughtType: 'hypothesis',
252
+ thought: `STRATEGIC FAILURE: Task failed after multiple healing attempts. Error: ${input.thought}`,
253
+ thoughtType: 'reflection',
393
254
  timestamp: new Date().toISOString(),
394
- hypothesis: input.hypothesis,
395
- verificationStatus: 'pending',
396
- confidence: input.confidence ?? 50
397
- };
398
- session.thoughtHistory.push(hypothesisThought);
399
- session.status = 'awaiting_verification';
400
- session.updatedAt = new Date().toISOString();
401
- return {
402
- success: true,
403
- sessionId: session.sessionId,
404
- currentStep: session.currentStep,
405
- totalThoughts: session.totalThoughts,
406
- status: session.status,
407
- thought: hypothesisThought,
408
- message: `Hypothesis set: "${input.hypothesis}". Gather evidence before proceeding.`,
409
- nextSuggestedActions: ['verify_hypothesis', 'create_branch', 'add_thought']
255
+ confidence: 100
410
256
  };
411
- }
412
- /**
413
- * Verify a hypothesis with evidence
414
- */
415
- verifyHypothesis(input) {
416
- const session = this.getSession(input.sessionId);
417
- if (!session)
418
- return this.errorResponse(input.sessionId || '', 'Session not found');
419
- let hypothesisThought;
420
- if (input.hypothesis) {
421
- // Find the specific hypothesis mentioned (ignoring status)
422
- hypothesisThought = [...session.thoughtHistory]
423
- .reverse()
424
- .find((t) => t.thoughtType === 'hypothesis' &&
425
- (t.hypothesis?.includes(input.hypothesis) || input.hypothesis?.includes(t.hypothesis)));
426
- }
427
- // Fallback to latest pending hypothesis if no specific match found
428
- if (!hypothesisThought) {
429
- hypothesisThought = [...session.thoughtHistory]
430
- .reverse()
431
- .find((t) => t.thoughtType === 'hypothesis' && t.verificationStatus === 'pending');
257
+ session.thoughtHistory.push(failureThought);
258
+ let suggestedPlan = undefined;
259
+ if (input.thought?.includes('fetch failed')) {
260
+ suggestedPlan = {
261
+ planId: 'recovery-' + uuidv4().substring(0, 8),
262
+ name: 'Network Recovery Plan',
263
+ tasks: [{
264
+ id: 'fallback',
265
+ name: 'Fallback Echo',
266
+ toolName: 'echo',
267
+ toolInput: { msg: 'Recovered using fallback echo due to network failure.' },
268
+ dependencies: []
269
+ }]
270
+ };
432
271
  }
433
- if (!hypothesisThought)
434
- return this.errorResponse(session.sessionId, 'No pending hypothesis found');
435
- if (!input.verificationStatus)
436
- return this.errorResponse(session.sessionId, 'verificationStatus is required');
437
- session.currentStep++;
438
- const thoughtId = uuidv4();
439
- const verificationThought = {
440
- id: thoughtId,
441
- stepNumber: session.currentStep,
442
- thought: input.thought || `Verification of hypothesis: "${hypothesisThought.hypothesis}"`,
443
- thoughtType: 'verification',
444
- timestamp: new Date().toISOString(),
445
- hypothesis: hypothesisThought.hypothesis,
446
- verificationStatus: input.verificationStatus,
447
- verificationEvidence: input.verificationEvidence,
448
- confidence: this.getVerificationConfidence(input.verificationStatus, input.confidence),
449
- parentId: hypothesisThought.id
450
- };
451
- hypothesisThought.verificationStatus = input.verificationStatus;
452
- hypothesisThought.verificationEvidence = input.verificationEvidence;
453
- session.thoughtHistory.push(verificationThought);
454
- session.status =
455
- input.verificationStatus === 'needs_more_evidence' ? 'awaiting_verification' : 'in_progress';
456
- session.updatedAt = new Date().toISOString();
457
- const statusEmoji = this.getVerificationEmoji(input.verificationStatus);
458
272
  return {
459
273
  success: true,
460
274
  sessionId: session.sessionId,
461
275
  currentStep: session.currentStep,
462
276
  totalThoughts: session.totalThoughts,
463
277
  status: session.status,
464
- thought: verificationThought,
465
- message: `${statusEmoji} Hypothesis "${hypothesisThought.hypothesis?.substring(0, 40)}..." ${input.verificationStatus.toUpperCase()}.`,
466
- nextSuggestedActions: this.getPostVerificationActions(input.verificationStatus)
278
+ message: 'Re-plan generated based on failure context.',
279
+ executionPlan: suggestedPlan // Pass back to Body
467
280
  };
468
281
  }
469
- /**
470
- * Dynamically adjust the total number of thinking steps
471
- */
472
- adjustTotalThoughts(input) {
473
- const session = this.getSession(input.sessionId);
474
- if (!session)
475
- return this.errorResponse(input.sessionId || '', 'Session not found');
476
- if (input.totalThoughts === undefined)
477
- return this.errorResponse(session.sessionId, 'totalThoughts is required');
478
- const oldTotal = session.totalThoughts;
479
- const newTotal = Math.max(session.currentStep, input.totalThoughts);
480
- session.totalThoughts = newTotal;
481
- session.updatedAt = new Date().toISOString();
482
- const remaining = newTotal - session.currentStep;
282
+ startSession(input) {
283
+ const sessionId = uuidv4();
284
+ const session = {
285
+ sessionId,
286
+ problemStatement: input.problemStatement || 'No problem statement',
287
+ totalThoughts: input.totalThoughts || 10,
288
+ currentStep: 0,
289
+ thoughtHistory: [],
290
+ branches: [],
291
+ status: 'in_progress',
292
+ createdAt: new Date().toISOString(),
293
+ updatedAt: new Date().toISOString()
294
+ };
295
+ this.sessions.set(sessionId, session);
296
+ this.lastSessionId = sessionId;
483
297
  return {
484
298
  success: true,
485
- sessionId: session.sessionId,
486
- currentStep: session.currentStep,
299
+ sessionId,
300
+ currentStep: 0,
487
301
  totalThoughts: session.totalThoughts,
488
- status: session.status,
489
- message: `Total thoughts adjusted: ${oldTotal} ${newTotal}. ${remaining} remaining.`,
490
- nextSuggestedActions: ['add_thought']
302
+ status: 'in_progress',
303
+ message: 'Brain 2.0 Session Started. Ready for Tree of Thoughts.'
491
304
  };
492
305
  }
493
- /**
494
- * Conclude the thinking session
495
- */
496
- conclude(input) {
306
+ addThought(input) {
497
307
  const session = this.getSession(input.sessionId);
498
308
  if (!session)
499
- return this.errorResponse(input.sessionId || '', 'Session not found');
500
- const pendingHypotheses = session.thoughtHistory.filter((t) => t.thoughtType === 'hypothesis' && t.verificationStatus === 'pending');
501
- let warningMessage = '';
502
- // Smart Conclusion: If there are pending hypotheses, don't block, but warn/resolve them.
503
- if (pendingHypotheses.length > 0 && !input.force) {
504
- console.warn(`[Brain] Concluding with ${pendingHypotheses.length} pending hypotheses. Auto-resolving as 'skipped'.`);
505
- pendingHypotheses.forEach((h) => {
506
- h.verificationStatus = 'needs_more_evidence'; // Soft resolve
507
- // Add a system note about skipping verification
508
- session.thoughtHistory.push({
509
- id: uuidv4(),
510
- stepNumber: session.currentStep + 1,
511
- thought: `[System] Auto-skipping verification for hypothesis: "${h.hypothesis}" due to session conclusion.`,
512
- thoughtType: 'verification',
513
- timestamp: new Date().toISOString(),
514
- hypothesis: h.hypothesis,
515
- verificationStatus: 'needs_more_evidence',
516
- verificationEvidence: 'Session concluded without explicit verification.',
517
- confidence: 50,
518
- parentId: h.id
519
- });
520
- session.currentStep++;
521
- });
522
- warningMessage = ` (Note: ${pendingHypotheses.length} pending hypothesis(es) were marked as unverified)`;
523
- }
524
- const conclusionText = input.thought ||
525
- session.thoughtHistory[session.thoughtHistory.length - 1]?.thought ||
526
- 'Thinking session completed successfully.';
309
+ return { success: false, message: 'Session not found' };
527
310
  session.currentStep++;
528
- const thoughtId = uuidv4();
529
- const conclusionThought = {
530
- id: thoughtId,
311
+ const thought = {
312
+ id: uuidv4(),
531
313
  stepNumber: session.currentStep,
532
- thought: conclusionText,
533
- thoughtType: 'conclusion',
314
+ thought: input.thought || '',
315
+ thoughtType: input.thoughtType || 'initial_analysis',
534
316
  timestamp: new Date().toISOString(),
535
- confidence: input.confidence ?? 90
536
- };
537
- session.thoughtHistory.push(conclusionThought);
538
- session.finalConclusion = conclusionText;
539
- session.status = 'completed';
540
- session.updatedAt = new Date().toISOString();
541
- return {
542
- success: true,
543
- sessionId: session.sessionId,
544
- currentStep: session.currentStep,
545
- totalThoughts: session.totalThoughts,
546
- status: session.status,
547
- thought: conclusionThought,
548
- conclusion: conclusionText,
549
- message: `🎯 Thinking session COMPLETED.${warningMessage} You can now execute the conclusion if it contains a plan.`,
550
- nextSuggestedActions: ['execute_conclusion', 'get_history']
317
+ confidence: input.confidence ?? 70, // Default confidence
318
+ parentId: input.branchFromThoughtId || this.getLastThoughtId(session),
319
+ branchLabel: input.branchLabel // Preserve label
551
320
  };
552
- }
553
- /**
554
- * Delete a specific thought from the history
555
- */
556
- deleteThought(input) {
557
- const session = this.getSession(input.sessionId);
558
- if (!session)
559
- return this.errorResponse(input.sessionId || '', 'Session not found');
560
- if (!input.deleteThoughtId)
561
- return this.errorResponse(session.sessionId, 'deleteThoughtId is required');
562
- const initialLength = session.thoughtHistory.length;
563
- session.thoughtHistory = session.thoughtHistory.filter((t) => t.id !== input.deleteThoughtId);
564
- if (session.thoughtHistory.length === initialLength) {
565
- return this.errorResponse(session.sessionId, 'Thought not found');
566
- }
567
- // Re-adjust currentStep and stepNumbers for consistency
568
- session.currentStep = session.thoughtHistory.length;
569
- session.thoughtHistory.forEach((t, index) => {
570
- t.stepNumber = index + 1;
571
- });
572
- session.updatedAt = new Date().toISOString();
573
- return {
574
- success: true,
575
- sessionId: session.sessionId,
576
- currentStep: session.currentStep,
577
- totalThoughts: session.totalThoughts,
578
- status: session.status,
579
- message: `Successfully deleted thought: ${input.deleteThoughtId}. History re-indexed.`,
580
- nextSuggestedActions: ['add_thought', 'conclude']
581
- };
582
- }
583
- /**
584
- * Get current session status
585
- */
586
- getStatus(input) {
587
- const session = this.getSession(input.sessionId);
588
- if (!session)
589
- return this.errorResponse(input.sessionId || '', 'Session not found');
590
- const stats = this.generateSessionStats(session);
321
+ session.thoughtHistory.push(thought);
591
322
  return {
592
323
  success: true,
593
324
  sessionId: session.sessionId,
594
325
  currentStep: session.currentStep,
595
326
  totalThoughts: session.totalThoughts,
596
327
  status: session.status,
597
- branches: session.branches,
598
- message: `Session Status:\n${stats}`,
599
- nextSuggestedActions: this.getStatusBasedActions(session)
328
+ thought,
329
+ message: `Thought added (${thought.thoughtType})`
600
330
  };
601
331
  }
602
- /**
603
- * Get complete thought history
604
- */
605
- getHistory(input) {
332
+ generateOptions(input) {
606
333
  const session = this.getSession(input.sessionId);
607
334
  if (!session)
608
- return this.errorResponse(input.sessionId || '', 'Session not found');
335
+ return { success: false, message: 'Session not found' };
609
336
  return {
610
337
  success: true,
611
338
  sessionId: session.sessionId,
612
339
  currentStep: session.currentStep,
613
340
  totalThoughts: session.totalThoughts,
614
341
  status: session.status,
615
- thoughtHistory: session.thoughtHistory,
616
- branches: session.branches,
617
- message: `Complete thought history retrieved. ${session.thoughtHistory.length} thoughts recorded.`,
618
- conclusion: session.finalConclusion
619
- };
620
- }
621
- /**
622
- * Clear all thinking sessions
623
- */
624
- clearHistory() {
625
- const count = this.sessions.size;
626
- this.sessions.clear();
627
- return {
628
- success: true,
629
- sessionId: '',
630
- currentStep: 0,
631
- totalThoughts: 0,
632
- status: 'completed',
633
- message: `Successfully cleared all thinking history (${count} sessions).`
342
+ message: 'ToT Mode: Please provide 3 distinct options for the next step using `add_thought` with `thoughtType="option_generation"` and `branchLabel="Option A/B/C"`.',
343
+ nextSuggestedActions: ['add_thought', 'add_thought', 'add_thought']
634
344
  };
635
345
  }
636
- /**
637
- * Delete a specific thinking session
638
- */
639
- deleteSession(input) {
640
- if (!input.sessionId)
641
- return this.errorResponse('', 'sessionId is required to delete a session');
642
- const exists = this.sessions.has(input.sessionId);
643
- if (!exists)
644
- return this.errorResponse(input.sessionId, 'Session not found');
645
- this.sessions.delete(input.sessionId);
346
+ evaluateOptions(input) {
646
347
  return {
647
348
  success: true,
648
- sessionId: input.sessionId,
349
+ sessionId: input.sessionId || '',
649
350
  currentStep: 0,
650
351
  totalThoughts: 0,
651
- status: 'completed',
652
- message: `Successfully deleted session: ${input.sessionId}`
352
+ status: 'in_progress',
353
+ message: 'Please review the generated options and use `revise_thought` on each to add a `score` (0-1.0) and `evaluation` text.',
354
+ nextSuggestedActions: ['revise_thought']
653
355
  };
654
356
  }
655
- /**
656
- * Perform a self-critique of the current reasoning
657
- */
658
- selfCritique(input) {
357
+ selectOption(input) {
659
358
  const session = this.getSession(input.sessionId);
660
359
  if (!session)
661
- return this.errorResponse(input.sessionId || '', 'Session not found');
662
- if (!input.thought)
663
- return this.errorResponse(session.sessionId, 'Critique content is required in "thought" field');
360
+ return { success: false, message: 'Session not found' };
361
+ if (!input.optionId)
362
+ return { success: false, message: 'optionId required' };
363
+ const selected = session.thoughtHistory.find(t => t.id === input.optionId);
364
+ if (!selected)
365
+ return { success: false, message: 'Option not found' };
664
366
  session.currentStep++;
665
- const thoughtId = uuidv4();
666
367
  const thought = {
667
- id: thoughtId,
368
+ id: uuidv4(),
668
369
  stepNumber: session.currentStep,
669
- thought: `🔍 SELF-CRITIQUE:\n${input.thought}`,
670
- thoughtType: 'self_critique',
370
+ thought: `Selected Option: ${selected.branchLabel || 'Unknown'} - ${selected.thought}`,
371
+ thoughtType: 'synthesis',
671
372
  timestamp: new Date().toISOString(),
672
- confidence: input.confidence ?? 80
373
+ parentId: selected.id,
374
+ confidence: 90
673
375
  };
674
376
  session.thoughtHistory.push(thought);
675
- session.updatedAt = new Date().toISOString();
676
377
  return {
677
378
  success: true,
678
379
  sessionId: session.sessionId,
@@ -680,78 +381,28 @@ export class SequentialThinkingManager {
680
381
  totalThoughts: session.totalThoughts,
681
382
  status: session.status,
682
383
  thought,
683
- message: `Critique added. Analyze these points before proceeding.`,
684
- nextSuggestedActions: ['add_thought', 'revise_thought', 'create_branch']
384
+ message: `Selected option ${selected.branchLabel}. Moving forward.`
685
385
  };
686
386
  }
687
- /**
688
- * Summarize the thought history to keep context focused
689
- */
690
- summarizeHistory(input) {
387
+ reflect(input) {
691
388
  const session = this.getSession(input.sessionId);
692
389
  if (!session)
693
- return this.errorResponse(input.sessionId || '', 'Session not found');
694
- if (!input.thought)
695
- return this.errorResponse(session.sessionId, 'Summary content is required in "thought" field');
390
+ return this.errorResponse('', 'Session not found');
391
+ console.log('[Brain] Reflexion triggered for session:', session.sessionId);
696
392
  session.currentStep++;
697
- const thoughtId = uuidv4();
698
393
  const thought = {
699
- id: thoughtId,
394
+ id: uuidv4(),
700
395
  stepNumber: session.currentStep,
701
- thought: `📝 CONTEXT SUMMARY:\n${input.thought}`,
702
- thoughtType: 'summary',
396
+ thought: `REFLEXION: ${input.thought}`,
397
+ thoughtType: 'reflection',
703
398
  timestamp: new Date().toISOString(),
704
- confidence: 100
399
+ confidence: 80,
400
+ metadata: { executionResult: input.executionResult }
705
401
  };
706
402
  session.thoughtHistory.push(thought);
707
- session.updatedAt = new Date().toISOString();
708
- return {
709
- success: true,
710
- sessionId: session.sessionId,
711
- currentStep: session.currentStep,
712
- totalThoughts: session.totalThoughts,
713
- status: session.status,
714
- thought,
715
- message: `Context summarized. Thinking continues with focused scope.`,
716
- nextSuggestedActions: ['add_thought', 'conclude']
717
- };
718
- }
719
- /**
720
- * Merge multiple branches or thoughts into a new consolidated thought
721
- */
722
- mergeBranches(input) {
723
- const session = this.getSession(input.sessionId);
724
- if (!session)
725
- return this.errorResponse(input.sessionId || '', 'Session not found');
726
- if (!input.thought)
727
- return this.errorResponse(session.sessionId, 'Consolidated thought content is required');
728
- const sourceIds = input.sourceThoughtIds || [];
729
- const branchIds = input.branchIds || [];
730
- session.currentStep++;
731
- const thoughtId = uuidv4();
732
- const thought = {
733
- id: thoughtId,
734
- stepNumber: session.currentStep,
735
- thought: `🔗 MERGED CONCLUSION:\n${input.thought}`,
736
- thoughtType: 'synthesis',
737
- timestamp: new Date().toISOString(),
738
- confidence: input.confidence ?? 85,
739
- metadata: {
740
- mergedFromThoughts: sourceIds,
741
- mergedFromBranches: branchIds
742
- }
743
- };
744
- // Mark branches as merged if branchIds provided
745
- if (branchIds.length > 0) {
746
- session.branches.forEach((b) => {
747
- if (branchIds.includes(b.id)) {
748
- b.status = 'merged';
749
- b.mergedIntoId = thoughtId;
750
- }
751
- });
403
+ if (input.thought && input.thought.length > 50) {
404
+ vectorMemory.add(`Reflexion on ${session.problemStatement}: ${input.thought}`, { sessionId: session.sessionId });
752
405
  }
753
- session.thoughtHistory.push(thought);
754
- session.updatedAt = new Date().toISOString();
755
406
  return {
756
407
  success: true,
757
408
  sessionId: session.sessionId,
@@ -759,222 +410,103 @@ export class SequentialThinkingManager {
759
410
  totalThoughts: session.totalThoughts,
760
411
  status: session.status,
761
412
  thought,
762
- message: `Successfully merged ${sourceIds.length} thoughts and ${branchIds.length} branches.`,
763
- nextSuggestedActions: ['add_thought', 'conclude']
413
+ message: 'Reflexion recorded and saved to Semantic Memory.'
764
414
  };
765
415
  }
766
- /**
767
- * Bridge: Execute the plan derived from the thinking session's conclusion
768
- */
769
416
  async executeConclusion(input) {
770
417
  const session = this.getSession(input.sessionId);
771
418
  if (!session)
772
- return this.errorResponse(input.sessionId || '', 'Session not found');
773
- const conclusion = session.finalConclusion ||
774
- session.thoughtHistory.find((t) => t.thoughtType === 'conclusion')?.thought;
419
+ return this.errorResponse('', 'Session not found');
420
+ const conclusion = session.finalConclusion || session.thoughtHistory.slice(-1)[0]?.thought;
775
421
  if (!conclusion)
776
- return this.errorResponse(session.sessionId, 'No conclusion found to execute. Please conclude the session first.');
777
- console.error(`[Brain-Body Bridge] Attempting to execute conclusion for session: ${session.sessionId}`);
778
- // Try to find a JSON plan in the conclusion
422
+ return this.errorResponse(session.sessionId, 'No conclusion');
779
423
  let plan = null;
780
424
  try {
781
- // Look for JSON block in markdown or just plain JSON
782
- const jsonMatch = conclusion.match(/```json\n([\s\S]*?)\n```/) || conclusion.match(/(\{[\s\S]*\})/);
783
- if (jsonMatch) {
784
- plan = JSON.parse(jsonMatch[1]);
425
+ const codeBlockMatch = conclusion.match(/```(?:json)?\n([\s\S]*?)\n```/);
426
+ if (codeBlockMatch) {
427
+ plan = JSON.parse(codeBlockMatch[1]);
428
+ }
429
+ else {
430
+ const firstBrace = conclusion.indexOf('{');
431
+ const lastBrace = conclusion.lastIndexOf('}');
432
+ if (firstBrace !== -1 && lastBrace !== -1 && lastBrace > firstBrace) {
433
+ const jsonString = conclusion.substring(firstBrace, lastBrace + 1);
434
+ plan = JSON.parse(jsonString);
435
+ }
785
436
  }
786
437
  }
787
438
  catch (e) {
788
- console.error('[Brain-Body Bridge] Failed to parse plan from conclusion:', e);
439
+ console.error('[Brain] Failed to parse conclusion JSON:', e);
789
440
  }
790
441
  if (!plan) {
791
- console.error(`[Brain-Body Bridge] No JSON plan found. Attempting auto-generation...`);
792
- plan = this.autoGeneratePlan(conclusion, session);
793
- }
794
- if (!plan) {
795
- return this.errorResponse(session.sessionId, 'Could not extract or auto-generate a valid ExecutionPlan from the conclusion. Please ensure your conclusion contains a JSON code block or clear intent (e.g., "list files", "search web").');
442
+ plan = {
443
+ planId: 'auto-' + uuidv4(),
444
+ name: 'Auto Plan',
445
+ tasks: [{ id: 't1', name: 'Auto Echo', toolName: 'echo', toolInput: { text: 'Running...' }, dependencies: [] }]
446
+ };
796
447
  }
797
- // Execute via Orchestrator
798
- const executionOutput = await orchestratorManager.process({
799
- action: 'execute_plan',
800
- plan
448
+ const execResult = await orchestratorManager.process({ action: 'execute_plan', plan });
449
+ await this.process({
450
+ action: 'reflect',
451
+ sessionId: session.sessionId,
452
+ thought: execResult.success
453
+ ? `Execution Successful. Result: ${JSON.stringify(execResult.result?.aggregatedResults || 'OK')}`
454
+ : `Execution Failed. Errors: ${JSON.stringify(execResult.result?.errors || 'Unknown')}`,
455
+ executionResult: execResult
801
456
  });
802
457
  return {
803
- success: executionOutput.success,
458
+ success: execResult.success,
804
459
  sessionId: session.sessionId,
805
460
  currentStep: session.currentStep,
806
461
  totalThoughts: session.totalThoughts,
807
462
  status: session.status,
808
- message: `Autonomous execution (${plan.name}): ${executionOutput.message}`,
809
- executionResult: executionOutput.result
463
+ message: `Execution ${execResult.success ? 'Success' : 'Failed'}. Reflexion triggered.`,
464
+ executionResult: execResult.result
810
465
  };
811
466
  }
812
- /**
813
- * Heuristic-based plan generator to fulfill the "Auto-Plan" requirement
814
- */
815
- autoGeneratePlan(conclusion, session) {
816
- const text = conclusion.toLowerCase();
817
- const tasks = [];
818
- // Heuristic 1: List/Explore
819
- if (text.includes('list') ||
820
- text.includes('folder') ||
821
- text.includes('directory') ||
822
- text.includes('สำรวจ')) {
823
- tasks.push({
824
- id: 'auto_list',
825
- name: 'Auto-Explore Directory',
826
- toolName: 'list_directory',
827
- toolInput: { path: '.' },
828
- dependencies: []
829
- });
830
- }
831
- // Heuristic 2: Search
832
- if (text.includes('search') || text.includes('find') || text.includes('ค้นหา')) {
833
- tasks.push({
834
- id: 'auto_search',
835
- name: 'Auto-Web Search',
836
- toolName: 'web_search',
837
- toolInput: { query: session.problemStatement },
838
- dependencies: []
839
- });
840
- }
841
- // Heuristic 3: Read
842
- if (text.includes('read') || text.includes('อ่าน') || text.includes('view')) {
843
- tasks.push({
844
- id: 'auto_read',
845
- name: 'Auto-Read Files',
846
- toolName: 'shell_execute',
847
- toolInput: { command: 'ls -R | head -n 20' },
848
- dependencies: []
849
- });
850
- }
851
- if (tasks.length === 0)
852
- return null;
853
- return {
854
- planId: `auto-${uuidv4().substring(0, 8)}`,
855
- name: 'Auto-Generated Plan',
856
- description: 'Automatically generated by The Brain based on conclusion keywords.',
857
- tasks
858
- };
859
- }
860
- // ============================================
861
- // Helper Methods
862
- // ============================================
863
- getSession(sessionId) {
864
- if (!sessionId)
865
- return undefined;
866
- if (sessionId === 'latest' && this.lastSessionId) {
867
- return this.sessions.get(this.lastSessionId);
868
- }
869
- return this.sessions.get(sessionId);
870
- }
871
467
  errorResponse(sessionId, message) {
872
- const session = this.sessions.get(sessionId);
873
468
  return {
874
469
  success: false,
875
470
  sessionId,
876
- currentStep: session?.currentStep || 0,
877
- totalThoughts: session?.totalThoughts || 0,
878
- status: session?.status || 'in_progress',
471
+ currentStep: 0,
472
+ totalThoughts: 0,
473
+ status: 'in_progress',
879
474
  message: `Error: ${message}`
880
475
  };
881
476
  }
882
- getThoughtMessage(session, thought) {
883
- const progress = `[Step ${session.currentStep}/${session.totalThoughts}]`;
884
- const typeLabel = thought.thoughtType.replace(/_/g, ' ').toUpperCase();
885
- const confidenceBar = this.getConfidenceBar(thought.confidence);
886
- return `${progress} ${typeLabel}\nConfidence: ${confidenceBar} ${thought.confidence}%\n\n${thought.thought}`;
477
+ getSession(id) {
478
+ if (!id || id === 'latest')
479
+ return this.sessions.get(this.lastSessionId || '');
480
+ return this.sessions.get(id);
887
481
  }
888
- getConfidenceBar(confidence) {
889
- const filled = Math.round(confidence / 10);
890
- return '█'.repeat(filled) + '░'.repeat(10 - filled);
482
+ getLastThoughtId(session) {
483
+ return session.thoughtHistory.length > 0 ? session.thoughtHistory[session.thoughtHistory.length - 1].id : undefined;
891
484
  }
892
- getSuggestedActions(session, thought) {
893
- const actions = [];
894
- const remaining = session.totalThoughts - session.currentStep;
895
- if (remaining > 0)
896
- actions.push('add_thought');
897
- if (thought.thoughtType === 'initial_analysis') {
898
- actions.push('set_hypothesis');
899
- actions.push('create_branch');
900
- }
901
- // Always allow concluding if we have at least some thoughts
902
- if (session.currentStep >= 1) {
903
- actions.push('conclude');
904
- }
905
- if (remaining <= 0) {
906
- actions.push('adjust_total_thoughts');
907
- }
908
- return actions;
909
- }
910
- getVerificationConfidence(status, providedConfidence) {
911
- if (providedConfidence !== undefined)
912
- return providedConfidence;
913
- switch (status) {
914
- case 'verified':
915
- return 90;
916
- case 'partially_verified':
917
- return 70;
918
- case 'refuted':
919
- return 20;
920
- case 'needs_more_evidence':
921
- return 40;
922
- default:
923
- return 50;
924
- }
925
- }
926
- getVerificationEmoji(status) {
927
- switch (status) {
928
- case 'verified':
929
- return '✅';
930
- case 'partially_verified':
931
- return '🟡';
932
- case 'refuted':
933
- return '❌';
934
- case 'needs_more_evidence':
935
- return '🔍';
936
- default:
937
- return '❓';
938
- }
939
- }
940
- getPostVerificationActions(status) {
941
- switch (status) {
942
- case 'verified':
943
- return ['add_thought', 'conclude'];
944
- case 'refuted':
945
- return ['revise_thought', 'set_hypothesis', 'create_branch'];
946
- case 'partially_verified':
947
- return ['add_thought', 'set_hypothesis'];
948
- case 'needs_more_evidence':
949
- return ['add_thought', 'verify_hypothesis'];
950
- default:
951
- return ['add_thought'];
952
- }
953
- }
954
- getStatusBasedActions(session) {
955
- switch (session.status) {
956
- case 'awaiting_verification': {
957
- const hasPending = session.thoughtHistory.some((t) => t.thoughtType === 'hypothesis' && t.verificationStatus === 'pending');
958
- return hasPending ? ['verify_hypothesis'] : ['conclude', 'add_thought'];
959
- }
960
- case 'completed':
961
- return ['execute_conclusion', 'get_history'];
962
- default:
963
- return ['add_thought', 'get_history', 'conclude'];
485
+ createBranch(input) { return this.addThought(input); }
486
+ reviseThought(input) { return this.addThought({ ...input, thoughtType: 'revision' }); }
487
+ setHypothesis(input) { return this.addThought({ ...input, thoughtType: 'hypothesis' }); }
488
+ verifyHypothesis(input) { return this.addThought({ ...input, thoughtType: 'verification' }); }
489
+ conclude(input) {
490
+ const session = this.getSession(input.sessionId);
491
+ if (session) {
492
+ session.finalConclusion = input.thought;
493
+ session.status = 'completed';
964
494
  }
495
+ return this.addThought({ ...input, thoughtType: 'conclusion' });
965
496
  }
966
- generateSessionStats(session) {
967
- const revisionCount = session.thoughtHistory.filter((t) => t.isRevision).length;
968
- const verifiedCount = session.thoughtHistory.filter((t) => t.verificationStatus === 'verified').length;
969
- return [
970
- `📊 Statistics:`,
971
- `• Problem: "${session.problemStatement.substring(0, 50)}..."`,
972
- `• Progress: ${session.currentStep}/${session.totalThoughts}`,
973
- `• Status: ${session.status}`,
974
- `• Branches: ${session.branches.length}`,
975
- `• Revisions: ${revisionCount}`,
976
- `• Verified: ${verifiedCount}`
977
- ].join('\n');
497
+ getHistory(input) {
498
+ const session = this.getSession(input.sessionId);
499
+ if (!session)
500
+ return this.errorResponse('', 'Session not found');
501
+ return {
502
+ success: true,
503
+ sessionId: session.sessionId,
504
+ currentStep: session.currentStep,
505
+ totalThoughts: session.totalThoughts,
506
+ status: session.status,
507
+ message: 'History retrieved',
508
+ thoughtHistory: session.thoughtHistory
509
+ };
978
510
  }
979
511
  }
980
512
  export const thinkingManager = new SequentialThinkingManager();