@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.
- package/dist/final-demo.js +0 -3
- package/dist/final-demo.js.map +1 -1
- package/dist/index.js +25 -15
- package/dist/index.js.map +1 -1
- package/dist/schemas/brain.schema.d.ts +70 -0
- package/dist/schemas/brain.schema.d.ts.map +1 -0
- package/dist/schemas/brain.schema.js +70 -0
- package/dist/schemas/brain.schema.js.map +1 -0
- package/dist/security.test.d.ts +2 -0
- package/dist/security.test.d.ts.map +1 -0
- package/dist/security.test.js +81 -0
- package/dist/security.test.js.map +1 -0
- package/dist/sse-server.js +39 -8
- package/dist/sse-server.js.map +1 -1
- package/dist/test-all.js +0 -20
- package/dist/test-all.js.map +1 -1
- package/dist/test-extended.js +0 -9
- package/dist/test-extended.js.map +1 -1
- package/dist/test-max-intelligence.d.ts +2 -0
- package/dist/test-max-intelligence.d.ts.map +1 -0
- package/dist/test-max-intelligence.js +52 -0
- package/dist/test-max-intelligence.js.map +1 -0
- package/dist/test-memory.js +0 -2
- package/dist/test-memory.js.map +1 -1
- package/dist/test-reflective.js +0 -6
- package/dist/test-reflective.js.map +1 -1
- package/dist/test-resilience.d.ts +2 -0
- package/dist/test-resilience.d.ts.map +1 -0
- package/dist/test-resilience.js +41 -0
- package/dist/test-resilience.js.map +1 -0
- package/dist/tools/orchestrator.d.ts +2 -47
- package/dist/tools/orchestrator.d.ts.map +1 -1
- package/dist/tools/orchestrator.js +224 -215
- package/dist/tools/orchestrator.js.map +1 -1
- package/dist/tools/sequential-thinking.d.ts +16 -95
- package/dist/tools/sequential-thinking.d.ts.map +1 -1
- package/dist/tools/sequential-thinking.js +313 -781
- package/dist/tools/sequential-thinking.js.map +1 -1
- package/dist/types/index.d.ts +18 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +0 -3
- package/dist/types/index.js.map +1 -1
- package/dist/utils/dag.d.ts +0 -20
- package/dist/utils/dag.d.ts.map +1 -1
- package/dist/utils/dag.js +8 -48
- package/dist/utils/dag.js.map +1 -1
- package/dist/utils/memory.d.ts +5 -0
- package/dist/utils/memory.d.ts.map +1 -1
- package/dist/utils/memory.js +66 -60
- package/dist/utils/memory.js.map +1 -1
- package/dist/utils/mutex.d.ts +6 -0
- package/dist/utils/mutex.d.ts.map +1 -0
- package/dist/utils/mutex.js +22 -0
- package/dist/utils/mutex.js.map +1 -0
- package/dist/utils/resilience.d.ts +23 -0
- package/dist/utils/resilience.d.ts.map +1 -0
- package/dist/utils/resilience.js +82 -0
- package/dist/utils/resilience.js.map +1 -0
- package/dist/utils/tool-cache.d.ts +9 -0
- package/dist/utils/tool-cache.d.ts.map +1 -0
- package/dist/utils/tool-cache.js +23 -0
- package/dist/utils/tool-cache.js.map +1 -0
- package/dist/utils/vector-memory.d.ts +18 -0
- package/dist/utils/vector-memory.d.ts.map +1 -0
- package/dist/utils/vector-memory.js +86 -0
- package/dist/utils/vector-memory.js.map +1 -0
- 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
|
-
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
73
|
-
|
|
74
|
-
async
|
|
47
|
+
async initStorage(force = false) {
|
|
48
|
+
await this.mutex.dispatch(() => this._initStorage(force));
|
|
49
|
+
}
|
|
50
|
+
async _saveToStorage() {
|
|
75
51
|
try {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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(
|
|
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]
|
|
60
|
+
console.error('[Brain] Save failed:', error);
|
|
88
61
|
}
|
|
89
62
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
63
|
+
async saveToStorage() {
|
|
64
|
+
await this.mutex.dispatch(() => this._saveToStorage());
|
|
65
|
+
}
|
|
93
66
|
async process(input) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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:
|
|
74
|
+
sessionId: '',
|
|
175
75
|
currentStep: 0,
|
|
176
76
|
totalThoughts: 0,
|
|
177
77
|
status: 'in_progress',
|
|
178
|
-
message: `
|
|
179
|
-
nextSuggestedActions: ['start_session', 'list_sessions']
|
|
78
|
+
message: `Validation Error: ${validationResult.error.message}`
|
|
180
79
|
};
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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
|
|
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:
|
|
169
|
+
id: uuidv4(),
|
|
253
170
|
stepNumber: session.currentStep,
|
|
254
|
-
thought: input.thought
|
|
255
|
-
thoughtType:
|
|
171
|
+
thought: `DECOMPOSITION: ${input.thought}`,
|
|
172
|
+
thoughtType: 'decomposition',
|
|
256
173
|
timestamp: new Date().toISOString(),
|
|
257
|
-
confidence:
|
|
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:
|
|
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
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
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
|
|
353
|
-
|
|
354
|
-
id: thoughtId,
|
|
222
|
+
const thought = {
|
|
223
|
+
id: uuidv4(),
|
|
355
224
|
stepNumber: session.currentStep,
|
|
356
|
-
thought:
|
|
357
|
-
thoughtType: '
|
|
225
|
+
thought: `RESEARCH PLAN: Generated plan to investigate "${topic}"`,
|
|
226
|
+
thoughtType: 'plan',
|
|
358
227
|
timestamp: new Date().toISOString(),
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
confidence: input.confidence ?? 75,
|
|
362
|
-
parentId: originalThought.parentId
|
|
228
|
+
confidence: 100,
|
|
229
|
+
metadata: { planId }
|
|
363
230
|
};
|
|
364
|
-
session.thoughtHistory.push(
|
|
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
|
|
373
|
-
|
|
374
|
-
|
|
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
|
|
384
|
-
|
|
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
|
|
388
|
-
|
|
389
|
-
id: thoughtId,
|
|
249
|
+
const failureThought = {
|
|
250
|
+
id: uuidv4(),
|
|
390
251
|
stepNumber: session.currentStep,
|
|
391
|
-
thought:
|
|
392
|
-
thoughtType: '
|
|
252
|
+
thought: `STRATEGIC FAILURE: Task failed after multiple healing attempts. Error: ${input.thought}`,
|
|
253
|
+
thoughtType: 'reflection',
|
|
393
254
|
timestamp: new Date().toISOString(),
|
|
394
|
-
|
|
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
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
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
|
-
|
|
465
|
-
|
|
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
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
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
|
|
486
|
-
currentStep:
|
|
299
|
+
sessionId,
|
|
300
|
+
currentStep: 0,
|
|
487
301
|
totalThoughts: session.totalThoughts,
|
|
488
|
-
status:
|
|
489
|
-
message:
|
|
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
|
|
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
|
|
529
|
-
|
|
530
|
-
id: thoughtId,
|
|
311
|
+
const thought = {
|
|
312
|
+
id: uuidv4(),
|
|
531
313
|
stepNumber: session.currentStep,
|
|
532
|
-
thought:
|
|
533
|
-
thoughtType: '
|
|
314
|
+
thought: input.thought || '',
|
|
315
|
+
thoughtType: input.thoughtType || 'initial_analysis',
|
|
534
316
|
timestamp: new Date().toISOString(),
|
|
535
|
-
confidence: input.confidence ??
|
|
536
|
-
|
|
537
|
-
|
|
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
|
-
|
|
598
|
-
message: `
|
|
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
|
|
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
|
-
|
|
616
|
-
|
|
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: '
|
|
652
|
-
message: `
|
|
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
|
|
662
|
-
if (!input.
|
|
663
|
-
return
|
|
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:
|
|
368
|
+
id: uuidv4(),
|
|
668
369
|
stepNumber: session.currentStep,
|
|
669
|
-
thought:
|
|
670
|
-
thoughtType: '
|
|
370
|
+
thought: `Selected Option: ${selected.branchLabel || 'Unknown'} - ${selected.thought}`,
|
|
371
|
+
thoughtType: 'synthesis',
|
|
671
372
|
timestamp: new Date().toISOString(),
|
|
672
|
-
|
|
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: `
|
|
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(
|
|
694
|
-
|
|
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:
|
|
394
|
+
id: uuidv4(),
|
|
700
395
|
stepNumber: session.currentStep,
|
|
701
|
-
thought:
|
|
702
|
-
thoughtType: '
|
|
396
|
+
thought: `REFLEXION: ${input.thought}`,
|
|
397
|
+
thoughtType: 'reflection',
|
|
703
398
|
timestamp: new Date().toISOString(),
|
|
704
|
-
confidence:
|
|
399
|
+
confidence: 80,
|
|
400
|
+
metadata: { executionResult: input.executionResult }
|
|
705
401
|
};
|
|
706
402
|
session.thoughtHistory.push(thought);
|
|
707
|
-
|
|
708
|
-
|
|
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:
|
|
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(
|
|
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
|
|
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
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
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
|
|
439
|
+
console.error('[Brain] Failed to parse conclusion JSON:', e);
|
|
789
440
|
}
|
|
790
441
|
if (!plan) {
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
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
|
-
|
|
798
|
-
|
|
799
|
-
action: '
|
|
800
|
-
|
|
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:
|
|
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: `
|
|
809
|
-
executionResult:
|
|
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:
|
|
877
|
-
totalThoughts:
|
|
878
|
-
status:
|
|
471
|
+
currentStep: 0,
|
|
472
|
+
totalThoughts: 0,
|
|
473
|
+
status: 'in_progress',
|
|
879
474
|
message: `Error: ${message}`
|
|
880
475
|
};
|
|
881
476
|
}
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
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
|
-
|
|
889
|
-
|
|
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
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
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
|
-
|
|
967
|
-
const
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
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();
|