@agents-eco/reasoning 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,331 @@
1
+ import { randomUUID } from "node:crypto";
2
+ const REACT_SYSTEM_SUFFIX = `
3
+
4
+ You are a reasoning agent that solves tasks step by step using the ReAct framework.
5
+
6
+ For each step, you MUST follow this format exactly:
7
+
8
+ Thought: <your reasoning about what to do next>
9
+ Action: <tool_name>
10
+ Action Input: <JSON arguments for the tool>
11
+
12
+ After receiving an observation, continue reasoning.
13
+
14
+ When you have enough information to answer, respond with:
15
+
16
+ Thought: <final reasoning>
17
+ Answer: <your final answer>
18
+
19
+ Rules:
20
+ - Always think before acting.
21
+ - Use tools when you need external information or computation.
22
+ - If a tool call fails, reflect on why and try a different approach.
23
+ - Be concise but thorough in your reasoning.
24
+ - If you are unsure, state your uncertainty.
25
+ `;
26
+ const REFLECTION_PROMPT = `
27
+ Reflect on your progress so far. Consider:
28
+ 1. What have you learned from the steps taken?
29
+ 2. Are you on the right track to solve the task?
30
+ 3. What should you do differently?
31
+ 4. How confident are you in your current approach?
32
+
33
+ Provide a brief reflection.
34
+ `;
35
+ const PLAN_PROMPT = `
36
+ Based on the task and your progress so far, create or revise your plan.
37
+ List the remaining steps needed to solve the task.
38
+ Be specific and actionable.
39
+ `;
40
+ /**
41
+ * ReAct (Reason + Act) strategy.
42
+ *
43
+ * Implements the multi-step reasoning loop from SmolAgents / Yao et al. 2022.
44
+ * Each step: Thought -> Action -> Observation, with optional reflection and planning.
45
+ */
46
+ export class ReActStrategy {
47
+ name = "react";
48
+ async reason(task, systemPrompt, tools, config, backend) {
49
+ const startTime = Date.now();
50
+ const steps = [];
51
+ let totalPromptTokens = 0;
52
+ let totalCompletionTokens = 0;
53
+ let llmCalls = 0;
54
+ let toolCallCount = 0;
55
+ // Build system message
56
+ const fullSystemPrompt = systemPrompt + REACT_SYSTEM_SUFFIX + this.buildToolDescriptions(tools);
57
+ const messages = [
58
+ { role: "system", content: fullSystemPrompt },
59
+ { role: "user", content: task },
60
+ ];
61
+ // Optional initial planning step
62
+ if (config.planning) {
63
+ const planStep = await this.planStep(messages, backend, config, steps.length);
64
+ if (planStep) {
65
+ steps.push(planStep);
66
+ messages.push({ role: "assistant", content: `Plan: ${planStep.content}` });
67
+ totalPromptTokens += planStep.tokens?.prompt ?? 0;
68
+ totalCompletionTokens += planStep.tokens?.completion ?? 0;
69
+ llmCalls++;
70
+ await config.hooks?.onPlan?.(planStep.content);
71
+ await config.hooks?.onStep?.(planStep);
72
+ }
73
+ }
74
+ // ReAct loop
75
+ for (let i = 0; i < config.maxSteps; i++) {
76
+ const stepStart = Date.now();
77
+ // Get LLM completion
78
+ let response;
79
+ try {
80
+ response = await backend.complete(messages, {
81
+ temperature: config.temperature ?? 0.3,
82
+ maxTokens: 2048,
83
+ });
84
+ }
85
+ catch (err) {
86
+ const errorStep = this.makeStep(steps.length, "error", `LLM call failed: ${err}`, 0, stepStart);
87
+ steps.push(errorStep);
88
+ await config.hooks?.onError?.(err instanceof Error ? err : new Error(String(err)));
89
+ break;
90
+ }
91
+ llmCalls++;
92
+ totalPromptTokens += response.tokens?.prompt ?? 0;
93
+ totalCompletionTokens += response.tokens?.completion ?? 0;
94
+ const parsed = this.parseResponse(response.content);
95
+ // Handle final answer
96
+ if (parsed.answer) {
97
+ const answerStep = this.makeStep(steps.length, "answer", parsed.answer, 0.9, stepStart);
98
+ if (parsed.thought) {
99
+ const thoughtStep = this.makeStep(steps.length, "thought", parsed.thought, 0.7, stepStart);
100
+ steps.push(thoughtStep);
101
+ await config.hooks?.onThought?.(parsed.thought);
102
+ await config.hooks?.onStep?.(thoughtStep);
103
+ }
104
+ steps.push(answerStep);
105
+ messages.push({ role: "assistant", content: response.content });
106
+ await config.hooks?.onAnswer?.(parsed.answer);
107
+ await config.hooks?.onStep?.(answerStep);
108
+ return this.buildResult(parsed.answer, steps, startTime, totalPromptTokens, totalCompletionTokens, llmCalls, toolCallCount, true);
109
+ }
110
+ // Handle thought
111
+ if (parsed.thought) {
112
+ const thoughtStep = this.makeStep(steps.length, "thought", parsed.thought, 0.7, stepStart);
113
+ steps.push(thoughtStep);
114
+ await config.hooks?.onThought?.(parsed.thought);
115
+ await config.hooks?.onStep?.(thoughtStep);
116
+ if (config.verbose) {
117
+ console.log(`[Step ${steps.length}] Thought: ${parsed.thought}`);
118
+ }
119
+ }
120
+ // Handle action (tool call)
121
+ if (parsed.action && parsed.actionInput) {
122
+ const actionStep = this.makeStep(steps.length, "action", `${parsed.action}(${JSON.stringify(parsed.actionInput)})`, 0.7, stepStart, [{ name: parsed.action, arguments: parsed.actionInput }]);
123
+ steps.push(actionStep);
124
+ await config.hooks?.onAction?.(parsed.action, parsed.actionInput);
125
+ await config.hooks?.onStep?.(actionStep);
126
+ if (config.verbose) {
127
+ console.log(`[Step ${steps.length}] Action: ${parsed.action}(${JSON.stringify(parsed.actionInput)})`);
128
+ }
129
+ // Execute tool
130
+ const toolEntry = tools.get(parsed.action);
131
+ let observation;
132
+ let toolSuccess = true;
133
+ if (!toolEntry) {
134
+ observation = `Error: Tool '${parsed.action}' not found. Available tools: ${Array.from(tools.keys()).join(", ")}`;
135
+ toolSuccess = false;
136
+ }
137
+ else {
138
+ try {
139
+ observation = await toolEntry.handler(parsed.actionInput);
140
+ toolCallCount++;
141
+ }
142
+ catch (err) {
143
+ observation = `Error executing tool '${parsed.action}': ${err}`;
144
+ toolSuccess = false;
145
+ }
146
+ }
147
+ // Record observation
148
+ const obsStep = this.makeStep(steps.length, "observation", observation, toolSuccess ? 0.8 : 0.3, stepStart);
149
+ obsStep.toolResults = [{ name: parsed.action, content: observation, success: toolSuccess }];
150
+ steps.push(obsStep);
151
+ await config.hooks?.onObservation?.(observation);
152
+ await config.hooks?.onStep?.(obsStep);
153
+ if (config.verbose) {
154
+ console.log(`[Step ${steps.length}] Observation: ${observation.slice(0, 200)}`);
155
+ }
156
+ // Add to messages
157
+ messages.push({ role: "assistant", content: response.content });
158
+ messages.push({ role: "user", content: `Observation: ${observation}` });
159
+ }
160
+ else if (!parsed.answer) {
161
+ // No action and no answer — LLM gave unstructured response
162
+ messages.push({ role: "assistant", content: response.content });
163
+ messages.push({
164
+ role: "user",
165
+ content: "Please follow the format: Thought/Action/Action Input or Thought/Answer.",
166
+ });
167
+ }
168
+ // Optional reflection
169
+ if (config.reflection && (i + 1) % 3 === 0) {
170
+ const reflectionStep = await this.reflectStep(messages, backend, config, steps.length);
171
+ if (reflectionStep) {
172
+ steps.push(reflectionStep);
173
+ messages.push({ role: "assistant", content: `Reflection: ${reflectionStep.content}` });
174
+ totalPromptTokens += reflectionStep.tokens?.prompt ?? 0;
175
+ totalCompletionTokens += reflectionStep.tokens?.completion ?? 0;
176
+ llmCalls++;
177
+ await config.hooks?.onReflection?.(reflectionStep.content);
178
+ await config.hooks?.onStep?.(reflectionStep);
179
+ }
180
+ }
181
+ // Optional plan revision
182
+ if (config.planning && config.planInterval && (i + 1) % config.planInterval === 0) {
183
+ const planStep = await this.planStep(messages, backend, config, steps.length);
184
+ if (planStep) {
185
+ steps.push(planStep);
186
+ messages.push({ role: "assistant", content: `Revised Plan: ${planStep.content}` });
187
+ totalPromptTokens += planStep.tokens?.prompt ?? 0;
188
+ totalCompletionTokens += planStep.tokens?.completion ?? 0;
189
+ llmCalls++;
190
+ await config.hooks?.onPlan?.(planStep.content);
191
+ await config.hooks?.onStep?.(planStep);
192
+ }
193
+ }
194
+ }
195
+ // Max steps reached — force a final answer
196
+ messages.push({
197
+ role: "user",
198
+ content: "You have reached the maximum number of steps. Please provide your best answer now based on what you have learned.",
199
+ });
200
+ try {
201
+ const finalResponse = await backend.complete(messages, { temperature: 0.2, maxTokens: 1024 });
202
+ llmCalls++;
203
+ totalPromptTokens += finalResponse.tokens?.prompt ?? 0;
204
+ totalCompletionTokens += finalResponse.tokens?.completion ?? 0;
205
+ const parsed = this.parseResponse(finalResponse.content);
206
+ const answer = parsed.answer || finalResponse.content;
207
+ const answerStep = this.makeStep(steps.length, "answer", answer, 0.5, Date.now());
208
+ steps.push(answerStep);
209
+ return this.buildResult(answer, steps, startTime, totalPromptTokens, totalCompletionTokens, llmCalls, toolCallCount, true);
210
+ }
211
+ catch {
212
+ return this.buildResult("Failed to produce a final answer within the step limit.", steps, startTime, totalPromptTokens, totalCompletionTokens, llmCalls, toolCallCount, false);
213
+ }
214
+ }
215
+ // ── Helpers ─────────────────────────────────────────
216
+ parseResponse(content) {
217
+ const result = {};
218
+ // Extract Thought
219
+ const thoughtMatch = content.match(/Thought:\s*([\s\S]*?)(?=\n(?:Action|Answer):|$)/i);
220
+ if (thoughtMatch)
221
+ result.thought = thoughtMatch[1].trim();
222
+ // Extract Answer
223
+ const answerMatch = content.match(/Answer:\s*([\s\S]*?)$/i);
224
+ if (answerMatch) {
225
+ result.answer = answerMatch[1].trim();
226
+ return result;
227
+ }
228
+ // Extract Action
229
+ const actionMatch = content.match(/Action:\s*(\S+)/i);
230
+ if (actionMatch)
231
+ result.action = actionMatch[1].trim();
232
+ // Extract Action Input
233
+ const inputMatch = content.match(/Action Input:\s*([\s\S]*?)(?=\n(?:Thought|Action|Answer):|$)/i);
234
+ if (inputMatch) {
235
+ try {
236
+ result.actionInput = JSON.parse(inputMatch[1].trim());
237
+ }
238
+ catch {
239
+ // Try to parse as key-value if not valid JSON
240
+ result.actionInput = { input: inputMatch[1].trim() };
241
+ }
242
+ }
243
+ return result;
244
+ }
245
+ buildToolDescriptions(tools) {
246
+ if (tools.size === 0)
247
+ return "\n\nYou have no tools available. Reason through the problem using your knowledge.";
248
+ const lines = ["\n\nAvailable tools:"];
249
+ for (const [name, { def }] of tools) {
250
+ lines.push(`- ${name}: ${def.description}`);
251
+ if (def.parameters && Object.keys(def.parameters).length > 0) {
252
+ lines.push(` Parameters: ${JSON.stringify(def.parameters)}`);
253
+ }
254
+ }
255
+ return lines.join("\n");
256
+ }
257
+ async reflectStep(messages, backend, config, index) {
258
+ const start = Date.now();
259
+ try {
260
+ const reflectionMessages = [
261
+ ...messages,
262
+ { role: "user", content: REFLECTION_PROMPT },
263
+ ];
264
+ const response = await backend.complete(reflectionMessages, { temperature: 0.4, maxTokens: 512 });
265
+ return {
266
+ id: randomUUID(),
267
+ index,
268
+ type: "reflection",
269
+ content: response.content,
270
+ confidence: 0.6,
271
+ durationMs: Date.now() - start,
272
+ tokens: response.tokens,
273
+ timestamp: new Date().toISOString(),
274
+ metadata: {},
275
+ };
276
+ }
277
+ catch {
278
+ return null;
279
+ }
280
+ }
281
+ async planStep(messages, backend, config, index) {
282
+ const start = Date.now();
283
+ try {
284
+ const planMessages = [
285
+ ...messages,
286
+ { role: "user", content: PLAN_PROMPT },
287
+ ];
288
+ const response = await backend.complete(planMessages, { temperature: 0.3, maxTokens: 512 });
289
+ return {
290
+ id: randomUUID(),
291
+ index,
292
+ type: "plan",
293
+ content: response.content,
294
+ confidence: 0.7,
295
+ durationMs: Date.now() - start,
296
+ tokens: response.tokens,
297
+ timestamp: new Date().toISOString(),
298
+ metadata: {},
299
+ };
300
+ }
301
+ catch {
302
+ return null;
303
+ }
304
+ }
305
+ makeStep(index, type, content, confidence, startTime, toolCalls) {
306
+ return {
307
+ id: randomUUID(),
308
+ index,
309
+ type,
310
+ content,
311
+ confidence,
312
+ toolCalls,
313
+ durationMs: Date.now() - startTime,
314
+ timestamp: new Date().toISOString(),
315
+ metadata: {},
316
+ };
317
+ }
318
+ buildResult(answer, steps, startTime, promptTokens, completionTokens, llmCalls, toolCalls, success) {
319
+ return {
320
+ answer,
321
+ steps,
322
+ strategy: "react",
323
+ durationMs: Date.now() - startTime,
324
+ tokens: { prompt: promptTokens, completion: completionTokens, total: promptTokens + completionTokens },
325
+ llmCalls,
326
+ toolCalls,
327
+ success,
328
+ };
329
+ }
330
+ }
331
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.js","sourceRoot":"","sources":["../../src/strategies/react.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { ReasoningStrategy, ReasoningConfig, ReasoningResult, ToolDef, ToolHandler, LLMBackend } from "../types.js";
2
+ /**
3
+ * Tree-of-Thought (ToT) strategy.
4
+ *
5
+ * Explores multiple reasoning paths in a tree structure.
6
+ * Uses beam search to keep the top-k most promising branches.
7
+ * Each branch is scored by the LLM or a heuristic.
8
+ */
9
+ export declare class TreeOfThoughtStrategy implements ReasoningStrategy {
10
+ readonly name: "tot";
11
+ reason(task: string, systemPrompt: string, tools: Map<string, {
12
+ def: ToolDef;
13
+ handler: ToolHandler;
14
+ }>, config: ReasoningConfig, backend: LLMBackend): Promise<ReasoningResult>;
15
+ private generateBranches;
16
+ private llmScore;
17
+ private heuristicScore;
18
+ private wordOverlap;
19
+ private solve;
20
+ private getPath;
21
+ private findBranch;
22
+ private findBranchById;
23
+ private buildResult;
24
+ }
25
+ //# sourceMappingURL=tot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tot.d.ts","sourceRoot":"","sources":["../../src/strategies/tot.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,iBAAiB,EACjB,eAAe,EACf,eAAe,EAIf,OAAO,EACP,WAAW,EACX,UAAU,EAEX,MAAM,aAAa,CAAC;AA0BrB;;;;;;GAMG;AACH,qBAAa,qBAAsB,YAAW,iBAAiB;IAC7D,QAAQ,CAAC,IAAI,EAAG,KAAK,CAAU;IAEzB,MAAM,CACV,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,GAAG,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,WAAW,CAAA;KAAE,CAAC,EAC1D,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,eAAe,CAAC;YA4Hb,gBAAgB;YA2ChB,QAAQ;IAoBtB,OAAO,CAAC,cAAc;IAyBtB,OAAO,CAAC,WAAW;YAYL,KAAK;IA0BnB,OAAO,CAAC,OAAO;IAOf,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,WAAW;CAoBpB"}
@@ -0,0 +1,274 @@
1
+ import { randomUUID } from "node:crypto";
2
+ const TOT_GENERATE_PROMPT = `Given the problem and the current reasoning path, generate {branchFactor} distinct next reasoning steps.
3
+ Each step should explore a different approach or angle.
4
+
5
+ Format each as:
6
+ Option 1: <reasoning step>
7
+ Option 2: <reasoning step>
8
+ ...
9
+
10
+ Be creative and consider diverse approaches.`;
11
+ const TOT_EVALUATE_PROMPT = `Evaluate the following reasoning step on a scale of 0.0 to 1.0.
12
+ Consider: logical soundness, relevance to the problem, likelihood of leading to a correct answer, and novelty.
13
+
14
+ Reasoning step: {thought}
15
+
16
+ Respond with only a number between 0.0 and 1.0.`;
17
+ const TOT_SOLVE_PROMPT = `Based on the following reasoning path, provide a final answer.
18
+
19
+ Reasoning path:
20
+ {path}
21
+
22
+ Final Answer:`;
23
+ /**
24
+ * Tree-of-Thought (ToT) strategy.
25
+ *
26
+ * Explores multiple reasoning paths in a tree structure.
27
+ * Uses beam search to keep the top-k most promising branches.
28
+ * Each branch is scored by the LLM or a heuristic.
29
+ */
30
+ export class TreeOfThoughtStrategy {
31
+ name = "tot";
32
+ async reason(task, systemPrompt, tools, config, backend) {
33
+ const startTime = Date.now();
34
+ const steps = [];
35
+ let totalPromptTokens = 0;
36
+ let totalCompletionTokens = 0;
37
+ let llmCalls = 0;
38
+ const totConfig = config;
39
+ const branchFactor = totConfig.branchFactor ?? 3;
40
+ const maxDepth = totConfig.maxDepth ?? 4;
41
+ const beamWidth = totConfig.beamWidth ?? 2;
42
+ // Root node
43
+ const root = {
44
+ id: randomUUID(),
45
+ thought: task,
46
+ score: 1.0,
47
+ depth: 0,
48
+ children: [],
49
+ isTerminal: false,
50
+ };
51
+ // Beam search
52
+ let currentBeam = [root];
53
+ for (let depth = 1; depth <= maxDepth; depth++) {
54
+ const allCandidates = [];
55
+ for (const parent of currentBeam) {
56
+ // Generate branches
57
+ const path = this.getPath(root, parent.id);
58
+ const branches = await this.generateBranches(task, systemPrompt, path, branchFactor, backend);
59
+ llmCalls++;
60
+ totalPromptTokens += branches.tokens.prompt;
61
+ totalCompletionTokens += branches.tokens.completion;
62
+ // Score each branch
63
+ for (const thought of branches.thoughts) {
64
+ let score;
65
+ if (totConfig.scoringMethod === "heuristic") {
66
+ score = this.heuristicScore(thought, path);
67
+ }
68
+ else {
69
+ const scoreResult = await this.llmScore(thought, backend);
70
+ score = scoreResult.score;
71
+ llmCalls++;
72
+ totalPromptTokens += scoreResult.tokens.prompt;
73
+ totalCompletionTokens += scoreResult.tokens.completion;
74
+ }
75
+ const branch = {
76
+ id: randomUUID(),
77
+ parentId: parent.id,
78
+ thought,
79
+ score,
80
+ depth,
81
+ children: [],
82
+ isTerminal: depth === maxDepth,
83
+ };
84
+ parent.children.push(branch);
85
+ allCandidates.push(branch);
86
+ // Record step
87
+ const step = {
88
+ id: randomUUID(),
89
+ index: steps.length,
90
+ type: "thought",
91
+ content: `[Depth ${depth}, Score ${score.toFixed(2)}] ${thought}`,
92
+ confidence: score,
93
+ durationMs: 0,
94
+ timestamp: new Date().toISOString(),
95
+ metadata: { depth, branchId: branch.id, parentId: parent.id },
96
+ };
97
+ steps.push(step);
98
+ await config.hooks?.onThought?.(thought);
99
+ await config.hooks?.onStep?.(step);
100
+ }
101
+ }
102
+ // Beam selection: keep top-k branches
103
+ allCandidates.sort((a, b) => b.score - a.score);
104
+ currentBeam = allCandidates.slice(0, beamWidth);
105
+ if (config.verbose) {
106
+ console.log(`[ToT Depth ${depth}] ${allCandidates.length} candidates, kept top ${beamWidth}`);
107
+ for (const b of currentBeam) {
108
+ console.log(` Score ${b.score.toFixed(2)}: ${b.thought.slice(0, 80)}`);
109
+ }
110
+ }
111
+ }
112
+ // Get the best terminal branch and solve
113
+ const bestBranch = currentBeam[0];
114
+ if (!bestBranch) {
115
+ return this.buildResult("Unable to find a solution.", steps, startTime, totalPromptTokens, totalCompletionTokens, llmCalls, false);
116
+ }
117
+ const bestPath = this.getPath(root, bestBranch.id);
118
+ const solveResult = await this.solve(task, systemPrompt, bestPath, backend);
119
+ llmCalls++;
120
+ totalPromptTokens += solveResult.tokens.prompt;
121
+ totalCompletionTokens += solveResult.tokens.completion;
122
+ const answerStep = {
123
+ id: randomUUID(),
124
+ index: steps.length,
125
+ type: "answer",
126
+ content: solveResult.answer,
127
+ confidence: bestBranch.score,
128
+ durationMs: Date.now() - startTime,
129
+ timestamp: new Date().toISOString(),
130
+ metadata: { bestBranchId: bestBranch.id, pathLength: bestPath.length },
131
+ };
132
+ steps.push(answerStep);
133
+ await config.hooks?.onAnswer?.(solveResult.answer);
134
+ await config.hooks?.onStep?.(answerStep);
135
+ return this.buildResult(solveResult.answer, steps, startTime, totalPromptTokens, totalCompletionTokens, llmCalls, true);
136
+ }
137
+ // ── Branch Generation ───────────────────────────────
138
+ async generateBranches(task, systemPrompt, path, branchFactor, backend) {
139
+ const pathStr = path.length > 0
140
+ ? `Current reasoning path:\n${path.map((p, i) => `${i + 1}. ${p}`).join("\n")}\n\n`
141
+ : "";
142
+ const prompt = TOT_GENERATE_PROMPT.replace("{branchFactor}", String(branchFactor));
143
+ const messages = [
144
+ { role: "system", content: systemPrompt },
145
+ { role: "user", content: `Problem: ${task}\n\n${pathStr}${prompt}` },
146
+ ];
147
+ const response = await backend.complete(messages, { temperature: 0.8, maxTokens: 1024 });
148
+ // Parse options
149
+ const thoughts = [];
150
+ const optionPattern = /Option\s+\d+:\s*([\s\S]*?)(?=Option\s+\d+:|$)/gi;
151
+ let match;
152
+ while ((match = optionPattern.exec(response.content)) !== null) {
153
+ const text = match[1].trim();
154
+ if (text)
155
+ thoughts.push(text);
156
+ }
157
+ // Fallback: split by newlines if no options found
158
+ if (thoughts.length === 0) {
159
+ const lines = response.content.split("\n").filter((l) => l.trim().length > 10);
160
+ thoughts.push(...lines.slice(0, branchFactor));
161
+ }
162
+ return {
163
+ thoughts: thoughts.slice(0, branchFactor),
164
+ tokens: { prompt: response.tokens?.prompt ?? 0, completion: response.tokens?.completion ?? 0 },
165
+ };
166
+ }
167
+ // ── Scoring ─────────────────────────────────────────
168
+ async llmScore(thought, backend) {
169
+ const prompt = TOT_EVALUATE_PROMPT.replace("{thought}", thought);
170
+ const messages = [{ role: "user", content: prompt }];
171
+ try {
172
+ const response = await backend.complete(messages, { temperature: 0.1, maxTokens: 16 });
173
+ const scoreMatch = response.content.match(/(\d+\.?\d*)/);
174
+ const score = scoreMatch ? Math.max(0, Math.min(1, parseFloat(scoreMatch[1]))) : 0.5;
175
+ return {
176
+ score,
177
+ tokens: { prompt: response.tokens?.prompt ?? 0, completion: response.tokens?.completion ?? 0 },
178
+ };
179
+ }
180
+ catch {
181
+ return { score: 0.5, tokens: { prompt: 0, completion: 0 } };
182
+ }
183
+ }
184
+ heuristicScore(thought, path) {
185
+ let score = 0.5;
186
+ // Length bonus (not too short, not too long)
187
+ const words = thought.split(/\s+/).length;
188
+ if (words >= 10 && words <= 100)
189
+ score += 0.1;
190
+ // Novelty: penalize if too similar to existing path
191
+ for (const p of path) {
192
+ const overlap = this.wordOverlap(thought, p);
193
+ if (overlap > 0.8)
194
+ score -= 0.2;
195
+ }
196
+ // Structure bonus: contains reasoning indicators
197
+ const indicators = ["because", "therefore", "however", "if", "then", "since", "given"];
198
+ for (const ind of indicators) {
199
+ if (thought.toLowerCase().includes(ind)) {
200
+ score += 0.05;
201
+ break;
202
+ }
203
+ }
204
+ return Math.max(0, Math.min(1, score));
205
+ }
206
+ wordOverlap(a, b) {
207
+ const wordsA = new Set(a.toLowerCase().split(/\s+/));
208
+ const wordsB = new Set(b.toLowerCase().split(/\s+/));
209
+ let overlap = 0;
210
+ for (const w of wordsA) {
211
+ if (wordsB.has(w))
212
+ overlap++;
213
+ }
214
+ return overlap / Math.max(wordsA.size, wordsB.size);
215
+ }
216
+ // ── Solve ───────────────────────────────────────────
217
+ async solve(task, systemPrompt, path, backend) {
218
+ const pathStr = path.map((p, i) => `${i + 1}. ${p}`).join("\n");
219
+ const prompt = TOT_SOLVE_PROMPT.replace("{path}", pathStr);
220
+ const messages = [
221
+ { role: "system", content: systemPrompt },
222
+ { role: "user", content: `Problem: ${task}\n\n${prompt}` },
223
+ ];
224
+ const response = await backend.complete(messages, { temperature: 0.2, maxTokens: 1024 });
225
+ const answerMatch = response.content.match(/Final Answer:\s*([\s\S]*?)$/i);
226
+ const answer = answerMatch ? answerMatch[1].trim() : response.content.trim();
227
+ return {
228
+ answer,
229
+ tokens: { prompt: response.tokens?.prompt ?? 0, completion: response.tokens?.completion ?? 0 },
230
+ };
231
+ }
232
+ // ── Path Extraction ─────────────────────────────────
233
+ getPath(root, targetId) {
234
+ const path = [];
235
+ const found = this.findBranch(root, targetId, path);
236
+ if (found)
237
+ return path.map((id) => this.findBranchById(root, id)?.thought ?? "").filter(Boolean);
238
+ return [];
239
+ }
240
+ findBranch(node, targetId, path) {
241
+ path.push(node.id);
242
+ if (node.id === targetId)
243
+ return true;
244
+ for (const child of node.children) {
245
+ if (this.findBranch(child, targetId, path))
246
+ return true;
247
+ }
248
+ path.pop();
249
+ return false;
250
+ }
251
+ findBranchById(node, id) {
252
+ if (node.id === id)
253
+ return node;
254
+ for (const child of node.children) {
255
+ const found = this.findBranchById(child, id);
256
+ if (found)
257
+ return found;
258
+ }
259
+ return null;
260
+ }
261
+ buildResult(answer, steps, startTime, promptTokens, completionTokens, llmCalls, success) {
262
+ return {
263
+ answer,
264
+ steps,
265
+ strategy: "tot",
266
+ durationMs: Date.now() - startTime,
267
+ tokens: { prompt: promptTokens, completion: completionTokens, total: promptTokens + completionTokens },
268
+ llmCalls,
269
+ toolCalls: 0,
270
+ success,
271
+ };
272
+ }
273
+ }
274
+ //# sourceMappingURL=tot.js.map