verifiable-thinking-mcp 0.4.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.
- package/LICENSE +21 -0
- package/README.md +339 -0
- package/package.json +75 -0
- package/src/index.ts +38 -0
- package/src/lib/cache.ts +246 -0
- package/src/lib/compression.ts +804 -0
- package/src/lib/compute/cache.ts +86 -0
- package/src/lib/compute/classifier.ts +555 -0
- package/src/lib/compute/confidence.ts +79 -0
- package/src/lib/compute/context.ts +154 -0
- package/src/lib/compute/extract.ts +200 -0
- package/src/lib/compute/filter.ts +224 -0
- package/src/lib/compute/index.ts +171 -0
- package/src/lib/compute/math.ts +247 -0
- package/src/lib/compute/patterns.ts +564 -0
- package/src/lib/compute/registry.ts +145 -0
- package/src/lib/compute/solvers/arithmetic.ts +65 -0
- package/src/lib/compute/solvers/calculus.ts +249 -0
- package/src/lib/compute/solvers/derivation-core.ts +371 -0
- package/src/lib/compute/solvers/derivation-latex.ts +160 -0
- package/src/lib/compute/solvers/derivation-mistakes.ts +1046 -0
- package/src/lib/compute/solvers/derivation-simplify.ts +451 -0
- package/src/lib/compute/solvers/derivation-transform.ts +620 -0
- package/src/lib/compute/solvers/derivation.ts +67 -0
- package/src/lib/compute/solvers/facts.ts +120 -0
- package/src/lib/compute/solvers/formula.ts +728 -0
- package/src/lib/compute/solvers/index.ts +36 -0
- package/src/lib/compute/solvers/logic.ts +422 -0
- package/src/lib/compute/solvers/probability.ts +307 -0
- package/src/lib/compute/solvers/statistics.ts +262 -0
- package/src/lib/compute/solvers/word-problems.ts +408 -0
- package/src/lib/compute/types.ts +107 -0
- package/src/lib/concepts.ts +111 -0
- package/src/lib/domain.ts +731 -0
- package/src/lib/extraction.ts +912 -0
- package/src/lib/index.ts +122 -0
- package/src/lib/judge.ts +260 -0
- package/src/lib/math/ast.ts +842 -0
- package/src/lib/math/index.ts +8 -0
- package/src/lib/math/operators.ts +171 -0
- package/src/lib/math/tokenizer.ts +477 -0
- package/src/lib/patterns.ts +200 -0
- package/src/lib/session.ts +825 -0
- package/src/lib/think/challenge.ts +323 -0
- package/src/lib/think/complexity.ts +504 -0
- package/src/lib/think/confidence-drift.ts +507 -0
- package/src/lib/think/consistency.ts +347 -0
- package/src/lib/think/guidance.ts +188 -0
- package/src/lib/think/helpers.ts +568 -0
- package/src/lib/think/hypothesis.ts +216 -0
- package/src/lib/think/index.ts +127 -0
- package/src/lib/think/prompts.ts +262 -0
- package/src/lib/think/route.ts +358 -0
- package/src/lib/think/schema.ts +98 -0
- package/src/lib/think/scratchpad-schema.ts +662 -0
- package/src/lib/think/spot-check.ts +961 -0
- package/src/lib/think/types.ts +93 -0
- package/src/lib/think/verification.ts +260 -0
- package/src/lib/tokens.ts +177 -0
- package/src/lib/verification.ts +620 -0
- package/src/prompts/index.ts +10 -0
- package/src/prompts/templates.ts +336 -0
- package/src/resources/index.ts +8 -0
- package/src/resources/sessions.ts +196 -0
- package/src/tools/compress.ts +138 -0
- package/src/tools/index.ts +5 -0
- package/src/tools/scratchpad.ts +2659 -0
- package/src/tools/sessions.ts +144 -0
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-built reasoning prompts/templates for common use cases
|
|
3
|
+
* Guides LLMs on how to use the think tool effectively
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface ReasoningTemplate {
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
domain: "math" | "logic" | "code" | "general";
|
|
10
|
+
suggested_steps: number;
|
|
11
|
+
system_prompt: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const templates: Record<string, ReasoningTemplate> = {
|
|
15
|
+
"mathematical-proof": {
|
|
16
|
+
name: "Mathematical Proof",
|
|
17
|
+
description: "Step-by-step mathematical derivation with verification",
|
|
18
|
+
domain: "math",
|
|
19
|
+
suggested_steps: 5,
|
|
20
|
+
system_prompt: `You are solving a mathematical problem step by step.
|
|
21
|
+
For each step:
|
|
22
|
+
1. State the operation or theorem being applied
|
|
23
|
+
2. Show the transformation clearly
|
|
24
|
+
3. Use verify=true to check arithmetic and algebraic validity
|
|
25
|
+
4. Mark final answer with is_final=true
|
|
26
|
+
|
|
27
|
+
Enable track_concepts to track mathematical entities (variables, functions, theorems).`,
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
"logical-deduction": {
|
|
31
|
+
name: "Logical Deduction",
|
|
32
|
+
description: "Formal logical reasoning with premise validation",
|
|
33
|
+
domain: "logic",
|
|
34
|
+
suggested_steps: 4,
|
|
35
|
+
system_prompt: `You are performing logical deduction.
|
|
36
|
+
For each step:
|
|
37
|
+
1. State premises explicitly
|
|
38
|
+
2. Apply one inference rule per step (modus ponens, modus tollens, etc.)
|
|
39
|
+
3. Use verify=true to check logical consistency
|
|
40
|
+
|
|
41
|
+
Avoid introducing new premises without justification.`,
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
"code-review": {
|
|
45
|
+
name: "Code Review",
|
|
46
|
+
description: "Systematic code analysis for bugs and improvements",
|
|
47
|
+
domain: "code",
|
|
48
|
+
suggested_steps: 6,
|
|
49
|
+
system_prompt: `You are reviewing code for correctness and quality.
|
|
50
|
+
For each step:
|
|
51
|
+
1. Focus on one aspect: syntax, logic, edge cases, performance, security
|
|
52
|
+
2. Quote specific code when identifying issues
|
|
53
|
+
3. Use verify=true to check assertions about code behavior
|
|
54
|
+
4. Use compress_context=true if reviewing large files
|
|
55
|
+
|
|
56
|
+
Categories to check: null handling, off-by-one errors, resource leaks, error handling, type safety.`,
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
debugging: {
|
|
60
|
+
name: "Debugging",
|
|
61
|
+
description: "Systematic bug investigation with hypothesis testing",
|
|
62
|
+
domain: "code",
|
|
63
|
+
suggested_steps: 5,
|
|
64
|
+
system_prompt: `You are debugging a reported issue.
|
|
65
|
+
For each step:
|
|
66
|
+
1. Form a hypothesis about the bug cause
|
|
67
|
+
2. Identify evidence that supports or refutes it
|
|
68
|
+
3. Use branching (branch_id) to explore multiple hypotheses in parallel
|
|
69
|
+
4. Use verify=true to validate assumptions about code behavior
|
|
70
|
+
|
|
71
|
+
Structure: Symptom → Hypothesis → Evidence → Conclusion → Fix`,
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
"problem-decomposition": {
|
|
75
|
+
name: "Problem Decomposition",
|
|
76
|
+
description: "Breaking complex problems into manageable sub-problems",
|
|
77
|
+
domain: "general",
|
|
78
|
+
suggested_steps: 4,
|
|
79
|
+
system_prompt: `You are decomposing a complex problem.
|
|
80
|
+
For each step:
|
|
81
|
+
1. Identify the core question or goal
|
|
82
|
+
2. Break into independent sub-problems where possible
|
|
83
|
+
3. Note dependencies between sub-problems
|
|
84
|
+
4. Use track_concepts=true to maintain a concept graph
|
|
85
|
+
|
|
86
|
+
Aim for sub-problems that can be solved independently and combined.`,
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
"comparative-analysis": {
|
|
90
|
+
name: "Comparative Analysis",
|
|
91
|
+
description: "Systematic comparison of alternatives with trade-offs",
|
|
92
|
+
domain: "general",
|
|
93
|
+
suggested_steps: 5,
|
|
94
|
+
system_prompt: `You are comparing multiple options or approaches.
|
|
95
|
+
For each step:
|
|
96
|
+
1. Define evaluation criteria first
|
|
97
|
+
2. Analyze each option against criteria
|
|
98
|
+
3. Use branch_id to evaluate options in parallel
|
|
99
|
+
4. Synthesize findings with weighted trade-offs
|
|
100
|
+
|
|
101
|
+
Avoid bias: evaluate all options with same criteria before concluding.`,
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// Prompts for FastMCP - using 'as const' for proper type inference
|
|
106
|
+
export const mathematicalProofPrompt = {
|
|
107
|
+
name: "mathematical-proof",
|
|
108
|
+
description: "Guide for step-by-step mathematical proofs with verification",
|
|
109
|
+
arguments: [
|
|
110
|
+
{
|
|
111
|
+
name: "problem",
|
|
112
|
+
description: "The mathematical problem to solve",
|
|
113
|
+
required: true,
|
|
114
|
+
},
|
|
115
|
+
] as const,
|
|
116
|
+
load: async (args: { problem?: string }) => {
|
|
117
|
+
const template = templates["mathematical-proof"]!;
|
|
118
|
+
return {
|
|
119
|
+
messages: [
|
|
120
|
+
{
|
|
121
|
+
role: "system" as const,
|
|
122
|
+
content: {
|
|
123
|
+
type: "text" as const,
|
|
124
|
+
text: template.system_prompt,
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
role: "user" as const,
|
|
129
|
+
content: {
|
|
130
|
+
type: "text" as const,
|
|
131
|
+
text: `Problem: ${args.problem || "Not specified"}\n\nUse the 'think' tool with domain="math" and verify=true for each step.`,
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
};
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export const logicalDeductionPrompt = {
|
|
140
|
+
name: "logical-deduction",
|
|
141
|
+
description: "Guide for formal logical reasoning with premise validation",
|
|
142
|
+
arguments: [
|
|
143
|
+
{
|
|
144
|
+
name: "premises",
|
|
145
|
+
description: "The premises to reason from",
|
|
146
|
+
required: true,
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: "conclusion",
|
|
150
|
+
description: "The conclusion to prove (optional)",
|
|
151
|
+
required: false,
|
|
152
|
+
},
|
|
153
|
+
] as const,
|
|
154
|
+
load: async (args: { premises?: string; conclusion?: string }) => {
|
|
155
|
+
const template = templates["logical-deduction"]!;
|
|
156
|
+
const goal = args.conclusion ? `Prove: ${args.conclusion}` : "Derive valid conclusions";
|
|
157
|
+
return {
|
|
158
|
+
messages: [
|
|
159
|
+
{
|
|
160
|
+
role: "system" as const,
|
|
161
|
+
content: {
|
|
162
|
+
type: "text" as const,
|
|
163
|
+
text: template.system_prompt,
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
role: "user" as const,
|
|
168
|
+
content: {
|
|
169
|
+
type: "text" as const,
|
|
170
|
+
text: `Premises:\n${args.premises || "Not specified"}\n\n${goal}\n\nUse the 'think' tool with domain="logic" and verify=true.`,
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
};
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
export const codeReviewPrompt = {
|
|
179
|
+
name: "code-review",
|
|
180
|
+
description: "Guide for systematic code review",
|
|
181
|
+
arguments: [
|
|
182
|
+
{
|
|
183
|
+
name: "code",
|
|
184
|
+
description: "The code to review",
|
|
185
|
+
required: true,
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
name: "focus",
|
|
189
|
+
description: "Specific focus areas (e.g., security, performance)",
|
|
190
|
+
required: false,
|
|
191
|
+
},
|
|
192
|
+
] as const,
|
|
193
|
+
load: async (args: { code?: string; focus?: string }) => {
|
|
194
|
+
const template = templates["code-review"]!;
|
|
195
|
+
const focusNote = args.focus ? `Focus on: ${args.focus}` : "";
|
|
196
|
+
return {
|
|
197
|
+
messages: [
|
|
198
|
+
{
|
|
199
|
+
role: "system" as const,
|
|
200
|
+
content: {
|
|
201
|
+
type: "text" as const,
|
|
202
|
+
text: template.system_prompt,
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
role: "user" as const,
|
|
207
|
+
content: {
|
|
208
|
+
type: "text" as const,
|
|
209
|
+
text: `Review this code:\n\`\`\`\n${args.code || "No code provided"}\n\`\`\`\n${focusNote}\n\nUse the 'think' tool with domain="code" and verify=true.`,
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
};
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
export const debuggingPrompt = {
|
|
218
|
+
name: "debugging",
|
|
219
|
+
description: "Guide for systematic bug investigation",
|
|
220
|
+
arguments: [
|
|
221
|
+
{
|
|
222
|
+
name: "symptom",
|
|
223
|
+
description: "The bug symptom or error message",
|
|
224
|
+
required: true,
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
name: "context",
|
|
228
|
+
description: "Relevant code or context",
|
|
229
|
+
required: false,
|
|
230
|
+
},
|
|
231
|
+
] as const,
|
|
232
|
+
load: async (args: { symptom?: string; context?: string }) => {
|
|
233
|
+
const template = templates.debugging!;
|
|
234
|
+
const contextNote = args.context ? `\nContext:\n${args.context}` : "";
|
|
235
|
+
return {
|
|
236
|
+
messages: [
|
|
237
|
+
{
|
|
238
|
+
role: "system" as const,
|
|
239
|
+
content: {
|
|
240
|
+
type: "text" as const,
|
|
241
|
+
text: template.system_prompt,
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
role: "user" as const,
|
|
246
|
+
content: {
|
|
247
|
+
type: "text" as const,
|
|
248
|
+
text: `Bug symptom: ${args.symptom || "Not specified"}${contextNote}\n\nUse the 'think' tool with domain="code" to investigate.`,
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
],
|
|
252
|
+
};
|
|
253
|
+
},
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
export const problemDecompositionPrompt = {
|
|
257
|
+
name: "problem-decomposition",
|
|
258
|
+
description: "Guide for breaking complex problems into sub-problems",
|
|
259
|
+
arguments: [
|
|
260
|
+
{
|
|
261
|
+
name: "problem",
|
|
262
|
+
description: "The complex problem to decompose",
|
|
263
|
+
required: true,
|
|
264
|
+
},
|
|
265
|
+
] as const,
|
|
266
|
+
load: async (args: { problem?: string }) => {
|
|
267
|
+
const template = templates["problem-decomposition"]!;
|
|
268
|
+
return {
|
|
269
|
+
messages: [
|
|
270
|
+
{
|
|
271
|
+
role: "system" as const,
|
|
272
|
+
content: {
|
|
273
|
+
type: "text" as const,
|
|
274
|
+
text: template.system_prompt,
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
role: "user" as const,
|
|
279
|
+
content: {
|
|
280
|
+
type: "text" as const,
|
|
281
|
+
text: `Problem: ${args.problem || "Not specified"}\n\nUse the 'think' tool with track_concepts=true to decompose.`,
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
],
|
|
285
|
+
};
|
|
286
|
+
},
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
export const comparativeAnalysisPrompt = {
|
|
290
|
+
name: "comparative-analysis",
|
|
291
|
+
description: "Guide for comparing alternatives with trade-offs",
|
|
292
|
+
arguments: [
|
|
293
|
+
{
|
|
294
|
+
name: "options",
|
|
295
|
+
description: "The options to compare",
|
|
296
|
+
required: true,
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
name: "criteria",
|
|
300
|
+
description: "Evaluation criteria (optional)",
|
|
301
|
+
required: false,
|
|
302
|
+
},
|
|
303
|
+
] as const,
|
|
304
|
+
load: async (args: { options?: string; criteria?: string }) => {
|
|
305
|
+
const template = templates["comparative-analysis"]!;
|
|
306
|
+
const criteriaNote = args.criteria ? `\nCriteria: ${args.criteria}` : "";
|
|
307
|
+
return {
|
|
308
|
+
messages: [
|
|
309
|
+
{
|
|
310
|
+
role: "system" as const,
|
|
311
|
+
content: {
|
|
312
|
+
type: "text" as const,
|
|
313
|
+
text: template.system_prompt,
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
role: "user" as const,
|
|
318
|
+
content: {
|
|
319
|
+
type: "text" as const,
|
|
320
|
+
text: `Compare these options: ${args.options || "Not specified"}${criteriaNote}\n\nUse the 'think' tool with branch_id to evaluate each option.`,
|
|
321
|
+
},
|
|
322
|
+
},
|
|
323
|
+
],
|
|
324
|
+
};
|
|
325
|
+
},
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
// Export all prompts for registration
|
|
329
|
+
export const allPrompts = [
|
|
330
|
+
mathematicalProofPrompt,
|
|
331
|
+
logicalDeductionPrompt,
|
|
332
|
+
codeReviewPrompt,
|
|
333
|
+
debuggingPrompt,
|
|
334
|
+
problemDecompositionPrompt,
|
|
335
|
+
comparativeAnalysisPrompt,
|
|
336
|
+
];
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Resources - Expose session data as MCP resources
|
|
3
|
+
* Allows external tools to read reasoning chains
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { SessionManager } from "../lib/session.ts";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Resource template for accessing individual sessions
|
|
10
|
+
* URI: session://{session_id}
|
|
11
|
+
*/
|
|
12
|
+
export const sessionResource = {
|
|
13
|
+
name: "Session",
|
|
14
|
+
uriTemplate: "session://{session_id}",
|
|
15
|
+
description:
|
|
16
|
+
"Access reasoning session data including thoughts, branches, and verification results",
|
|
17
|
+
mimeType: "application/json",
|
|
18
|
+
arguments: [
|
|
19
|
+
{
|
|
20
|
+
name: "session_id",
|
|
21
|
+
description: "The session identifier",
|
|
22
|
+
required: true,
|
|
23
|
+
},
|
|
24
|
+
] as const,
|
|
25
|
+
load: async (args: { session_id?: string }) => {
|
|
26
|
+
const sessionId = args.session_id;
|
|
27
|
+
if (!sessionId) {
|
|
28
|
+
return {
|
|
29
|
+
text: JSON.stringify({ error: "session_id is required" }),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const session = SessionManager.get(sessionId);
|
|
34
|
+
if (!session) {
|
|
35
|
+
return {
|
|
36
|
+
text: JSON.stringify({ error: `Session '${sessionId}' not found` }),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const data = {
|
|
41
|
+
id: session.id,
|
|
42
|
+
created_at: new Date(session.created_at).toISOString(),
|
|
43
|
+
updated_at: new Date(session.updated_at).toISOString(),
|
|
44
|
+
branches: Array.from(session.branches),
|
|
45
|
+
thought_count: session.thoughts.length,
|
|
46
|
+
thoughts: session.thoughts.map((t) => ({
|
|
47
|
+
id: t.id,
|
|
48
|
+
step_number: t.step_number,
|
|
49
|
+
branch_id: t.branch_id,
|
|
50
|
+
thought: t.thought,
|
|
51
|
+
timestamp: new Date(t.timestamp).toISOString(),
|
|
52
|
+
verification: t.verification,
|
|
53
|
+
concepts: t.concepts,
|
|
54
|
+
})),
|
|
55
|
+
metadata: session.metadata,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
text: JSON.stringify(data, null, 2),
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Resource template for session summaries
|
|
66
|
+
* URI: session://{session_id}/summary
|
|
67
|
+
*/
|
|
68
|
+
export const sessionSummaryResource = {
|
|
69
|
+
name: "Session Summary",
|
|
70
|
+
uriTemplate: "session://{session_id}/summary",
|
|
71
|
+
description: "Get a text summary of a reasoning session",
|
|
72
|
+
mimeType: "text/plain",
|
|
73
|
+
arguments: [
|
|
74
|
+
{
|
|
75
|
+
name: "session_id",
|
|
76
|
+
description: "The session identifier",
|
|
77
|
+
required: true,
|
|
78
|
+
},
|
|
79
|
+
] as const,
|
|
80
|
+
load: async (args: { session_id?: string }) => {
|
|
81
|
+
const sessionId = args.session_id;
|
|
82
|
+
if (!sessionId) {
|
|
83
|
+
return { text: "Error: session_id is required" };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const summary = SessionManager.getSummary(sessionId);
|
|
87
|
+
if (!summary) {
|
|
88
|
+
return { text: `Error: Session '${sessionId}' not found` };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return { text: summary };
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Resource template for session branch data
|
|
97
|
+
* URI: session://{session_id}/branch/{branch_id}
|
|
98
|
+
*/
|
|
99
|
+
export const sessionBranchResource = {
|
|
100
|
+
name: "Session Branch",
|
|
101
|
+
uriTemplate: "session://{session_id}/branch/{branch_id}",
|
|
102
|
+
description: "Access thoughts from a specific branch in a session",
|
|
103
|
+
mimeType: "application/json",
|
|
104
|
+
arguments: [
|
|
105
|
+
{
|
|
106
|
+
name: "session_id",
|
|
107
|
+
description: "The session identifier",
|
|
108
|
+
required: true,
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: "branch_id",
|
|
112
|
+
description: "The branch identifier (default: main)",
|
|
113
|
+
required: false,
|
|
114
|
+
},
|
|
115
|
+
] as const,
|
|
116
|
+
load: async (args: { session_id?: string; branch_id?: string }) => {
|
|
117
|
+
const sessionId = args.session_id;
|
|
118
|
+
const branchId = args.branch_id || "main";
|
|
119
|
+
|
|
120
|
+
if (!sessionId) {
|
|
121
|
+
return {
|
|
122
|
+
text: JSON.stringify({ error: "session_id is required" }),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const thoughts = SessionManager.getThoughts(sessionId, branchId);
|
|
127
|
+
if (thoughts.length === 0) {
|
|
128
|
+
const session = SessionManager.get(sessionId);
|
|
129
|
+
if (!session) {
|
|
130
|
+
return {
|
|
131
|
+
text: JSON.stringify({ error: `Session '${sessionId}' not found` }),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
text: JSON.stringify({
|
|
136
|
+
error: `Branch '${branchId}' not found or empty`,
|
|
137
|
+
available_branches: Array.from(session.branches),
|
|
138
|
+
}),
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const data = {
|
|
143
|
+
session_id: sessionId,
|
|
144
|
+
branch_id: branchId,
|
|
145
|
+
thought_count: thoughts.length,
|
|
146
|
+
thoughts: thoughts.map((t) => ({
|
|
147
|
+
id: t.id,
|
|
148
|
+
step_number: t.step_number,
|
|
149
|
+
thought: t.thought,
|
|
150
|
+
timestamp: new Date(t.timestamp).toISOString(),
|
|
151
|
+
verification: t.verification,
|
|
152
|
+
concepts: t.concepts,
|
|
153
|
+
})),
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
text: JSON.stringify(data, null, 2),
|
|
158
|
+
};
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Static resource listing all active sessions
|
|
164
|
+
*/
|
|
165
|
+
export const sessionsListResource = {
|
|
166
|
+
name: "Sessions List",
|
|
167
|
+
uri: "session://list",
|
|
168
|
+
description: "List all active reasoning sessions",
|
|
169
|
+
mimeType: "application/json",
|
|
170
|
+
load: async () => {
|
|
171
|
+
const sessions = SessionManager.list();
|
|
172
|
+
|
|
173
|
+
const data = {
|
|
174
|
+
count: sessions.length,
|
|
175
|
+
sessions: sessions.map((s) => ({
|
|
176
|
+
id: s.id,
|
|
177
|
+
thought_count: s.thought_count,
|
|
178
|
+
branches: s.branches,
|
|
179
|
+
age_seconds: Math.round(s.age_ms / 1000),
|
|
180
|
+
})),
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
text: JSON.stringify(data, null, 2),
|
|
185
|
+
};
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// Export all resources
|
|
190
|
+
export const allResources = [sessionsListResource];
|
|
191
|
+
|
|
192
|
+
export const allResourceTemplates = [
|
|
193
|
+
sessionResource,
|
|
194
|
+
sessionSummaryResource,
|
|
195
|
+
sessionBranchResource,
|
|
196
|
+
];
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { type CompressionResult, compress, quickCompress } from "../lib/compression.ts";
|
|
3
|
+
import { calculateTokenUsage } from "../lib/tokens.ts";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Standalone compress tool - Enhanced CPC-style context compression
|
|
7
|
+
* Features: TF-IDF, NCD relevance, coreference/causal constraints, filler removal
|
|
8
|
+
*/
|
|
9
|
+
export const compressTool = {
|
|
10
|
+
name: "compress",
|
|
11
|
+
description: `Compress context using enhanced CPC-style sentence-level relevance scoring.
|
|
12
|
+
|
|
13
|
+
Features:
|
|
14
|
+
- TF-IDF + NCD (gzip-based) query relevance scoring
|
|
15
|
+
- Coreference constraints (keeps pronoun antecedents)
|
|
16
|
+
- Causal chain preservation (keeps premises for "therefore" etc.)
|
|
17
|
+
- Filler/meta-cognition removal
|
|
18
|
+
- Repetition detection and penalization
|
|
19
|
+
|
|
20
|
+
Up to 10x faster than token-level compression methods. Keeps sentences most relevant
|
|
21
|
+
to the query while maintaining coherence by preserving original sentence order.
|
|
22
|
+
|
|
23
|
+
Use this to reduce token costs before sending large contexts to LLMs.`,
|
|
24
|
+
|
|
25
|
+
parameters: z.object({
|
|
26
|
+
context: z
|
|
27
|
+
.string()
|
|
28
|
+
.max(1_000_000, "Context exceeds 1MB limit - split into smaller chunks")
|
|
29
|
+
.describe("The text/context to compress"),
|
|
30
|
+
query: z
|
|
31
|
+
.string()
|
|
32
|
+
.max(10_000, "Query exceeds 10KB limit")
|
|
33
|
+
.describe("Focus query - sentences relevant to this are kept"),
|
|
34
|
+
target_ratio: z
|
|
35
|
+
.number()
|
|
36
|
+
.min(0.1)
|
|
37
|
+
.max(1.0)
|
|
38
|
+
.default(0.5)
|
|
39
|
+
.describe("Target compression ratio (0.5 = keep ~50%)"),
|
|
40
|
+
max_tokens: z
|
|
41
|
+
.number()
|
|
42
|
+
.int()
|
|
43
|
+
.min(50)
|
|
44
|
+
.optional()
|
|
45
|
+
.describe("Alternative: specify max tokens instead of ratio"),
|
|
46
|
+
boost_reasoning: z
|
|
47
|
+
.boolean()
|
|
48
|
+
.default(true)
|
|
49
|
+
.describe("Boost sentences with reasoning keywords (therefore, because, etc.)"),
|
|
50
|
+
use_ncd: z.boolean().default(true).describe("Use NCD (gzip-based) query similarity scoring"),
|
|
51
|
+
enforce_coref: z
|
|
52
|
+
.boolean()
|
|
53
|
+
.default(true)
|
|
54
|
+
.describe("Keep antecedent sentences when pronouns are selected"),
|
|
55
|
+
enforce_causal: z
|
|
56
|
+
.boolean()
|
|
57
|
+
.default(true)
|
|
58
|
+
.describe("Keep premise sentences when causal conclusions are selected"),
|
|
59
|
+
remove_fillers: z
|
|
60
|
+
.boolean()
|
|
61
|
+
.default(true)
|
|
62
|
+
.describe("Remove filler phrases (basically, actually, let me think, etc.)"),
|
|
63
|
+
}),
|
|
64
|
+
|
|
65
|
+
execute: async (args: {
|
|
66
|
+
context: string;
|
|
67
|
+
query: string;
|
|
68
|
+
target_ratio?: number;
|
|
69
|
+
max_tokens?: number;
|
|
70
|
+
boost_reasoning?: boolean;
|
|
71
|
+
use_ncd?: boolean;
|
|
72
|
+
enforce_coref?: boolean;
|
|
73
|
+
enforce_causal?: boolean;
|
|
74
|
+
remove_fillers?: boolean;
|
|
75
|
+
}): Promise<string> => {
|
|
76
|
+
let result: CompressionResult;
|
|
77
|
+
|
|
78
|
+
// Use max_tokens mode if specified
|
|
79
|
+
if (args.max_tokens) {
|
|
80
|
+
const compressed = quickCompress(args.context, args.query, args.max_tokens);
|
|
81
|
+
const originalTokens = Math.ceil(args.context.length / 4);
|
|
82
|
+
const compressedTokens = Math.ceil(compressed.length / 4);
|
|
83
|
+
|
|
84
|
+
result = {
|
|
85
|
+
compressed,
|
|
86
|
+
original_tokens: originalTokens,
|
|
87
|
+
compressed_tokens: compressedTokens,
|
|
88
|
+
ratio: compressed.length / args.context.length,
|
|
89
|
+
kept_sentences: compressed.split(/(?<=[.!?])\s+/).length,
|
|
90
|
+
dropped_sentences: [],
|
|
91
|
+
};
|
|
92
|
+
} else {
|
|
93
|
+
// Standard ratio-based compression with all options
|
|
94
|
+
result = compress(args.context, args.query, {
|
|
95
|
+
target_ratio: args.target_ratio ?? 0.5,
|
|
96
|
+
boost_reasoning: args.boost_reasoning ?? true,
|
|
97
|
+
useNCD: args.use_ncd ?? true,
|
|
98
|
+
enforceCoref: args.enforce_coref ?? true,
|
|
99
|
+
enforceCausalChains: args.enforce_causal ?? true,
|
|
100
|
+
removeFillers: args.remove_fillers ?? true,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const output = formatCompressResult(result);
|
|
105
|
+
const tokens = calculateTokenUsage(args, output);
|
|
106
|
+
|
|
107
|
+
return `${output}\n\n---\n_tokens: ${tokens.input_tokens} in, ${tokens.output_tokens} out, ${tokens.total_tokens} total_`;
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
function formatCompressResult(result: CompressionResult): string {
|
|
112
|
+
const savings = Math.round((1 - result.ratio) * 100);
|
|
113
|
+
|
|
114
|
+
const lines = [
|
|
115
|
+
`**Compression Results**`,
|
|
116
|
+
`- Tokens: ${result.original_tokens} → ${result.compressed_tokens} (${savings}% reduction)`,
|
|
117
|
+
`- Sentences kept: ${result.kept_sentences}`,
|
|
118
|
+
`- Sentences dropped: ${result.dropped_sentences.length}`,
|
|
119
|
+
];
|
|
120
|
+
|
|
121
|
+
// Add enhancement details if present
|
|
122
|
+
if (result.enhancements) {
|
|
123
|
+
const enh = result.enhancements;
|
|
124
|
+
const enhParts: string[] = [];
|
|
125
|
+
if (enh.fillers_removed > 0) enhParts.push(`fillers=${enh.fillers_removed}`);
|
|
126
|
+
if (enh.coref_constraints_applied > 0) enhParts.push(`coref=${enh.coref_constraints_applied}`);
|
|
127
|
+
if (enh.causal_constraints_applied > 0)
|
|
128
|
+
enhParts.push(`causal=${enh.causal_constraints_applied}`);
|
|
129
|
+
if (enh.repetitions_penalized > 0) enhParts.push(`repetitions=${enh.repetitions_penalized}`);
|
|
130
|
+
if (enhParts.length > 0) {
|
|
131
|
+
lines.push(`- Enhancements: ${enhParts.join(", ")}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
lines.push(``, `**Compressed Context:**`, result.compressed);
|
|
136
|
+
|
|
137
|
+
return lines.join("\n");
|
|
138
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// Re-export SessionManager for hint state access
|
|
2
|
+
export { SessionManager } from "../lib/session.ts";
|
|
3
|
+
export { compressTool } from "./compress.ts";
|
|
4
|
+
export { scratchpadTool } from "./scratchpad.ts";
|
|
5
|
+
export { clearSessionTool, getSessionTool, listSessionsTool } from "./sessions.ts";
|