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.
Files changed (68) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +339 -0
  3. package/package.json +75 -0
  4. package/src/index.ts +38 -0
  5. package/src/lib/cache.ts +246 -0
  6. package/src/lib/compression.ts +804 -0
  7. package/src/lib/compute/cache.ts +86 -0
  8. package/src/lib/compute/classifier.ts +555 -0
  9. package/src/lib/compute/confidence.ts +79 -0
  10. package/src/lib/compute/context.ts +154 -0
  11. package/src/lib/compute/extract.ts +200 -0
  12. package/src/lib/compute/filter.ts +224 -0
  13. package/src/lib/compute/index.ts +171 -0
  14. package/src/lib/compute/math.ts +247 -0
  15. package/src/lib/compute/patterns.ts +564 -0
  16. package/src/lib/compute/registry.ts +145 -0
  17. package/src/lib/compute/solvers/arithmetic.ts +65 -0
  18. package/src/lib/compute/solvers/calculus.ts +249 -0
  19. package/src/lib/compute/solvers/derivation-core.ts +371 -0
  20. package/src/lib/compute/solvers/derivation-latex.ts +160 -0
  21. package/src/lib/compute/solvers/derivation-mistakes.ts +1046 -0
  22. package/src/lib/compute/solvers/derivation-simplify.ts +451 -0
  23. package/src/lib/compute/solvers/derivation-transform.ts +620 -0
  24. package/src/lib/compute/solvers/derivation.ts +67 -0
  25. package/src/lib/compute/solvers/facts.ts +120 -0
  26. package/src/lib/compute/solvers/formula.ts +728 -0
  27. package/src/lib/compute/solvers/index.ts +36 -0
  28. package/src/lib/compute/solvers/logic.ts +422 -0
  29. package/src/lib/compute/solvers/probability.ts +307 -0
  30. package/src/lib/compute/solvers/statistics.ts +262 -0
  31. package/src/lib/compute/solvers/word-problems.ts +408 -0
  32. package/src/lib/compute/types.ts +107 -0
  33. package/src/lib/concepts.ts +111 -0
  34. package/src/lib/domain.ts +731 -0
  35. package/src/lib/extraction.ts +912 -0
  36. package/src/lib/index.ts +122 -0
  37. package/src/lib/judge.ts +260 -0
  38. package/src/lib/math/ast.ts +842 -0
  39. package/src/lib/math/index.ts +8 -0
  40. package/src/lib/math/operators.ts +171 -0
  41. package/src/lib/math/tokenizer.ts +477 -0
  42. package/src/lib/patterns.ts +200 -0
  43. package/src/lib/session.ts +825 -0
  44. package/src/lib/think/challenge.ts +323 -0
  45. package/src/lib/think/complexity.ts +504 -0
  46. package/src/lib/think/confidence-drift.ts +507 -0
  47. package/src/lib/think/consistency.ts +347 -0
  48. package/src/lib/think/guidance.ts +188 -0
  49. package/src/lib/think/helpers.ts +568 -0
  50. package/src/lib/think/hypothesis.ts +216 -0
  51. package/src/lib/think/index.ts +127 -0
  52. package/src/lib/think/prompts.ts +262 -0
  53. package/src/lib/think/route.ts +358 -0
  54. package/src/lib/think/schema.ts +98 -0
  55. package/src/lib/think/scratchpad-schema.ts +662 -0
  56. package/src/lib/think/spot-check.ts +961 -0
  57. package/src/lib/think/types.ts +93 -0
  58. package/src/lib/think/verification.ts +260 -0
  59. package/src/lib/tokens.ts +177 -0
  60. package/src/lib/verification.ts +620 -0
  61. package/src/prompts/index.ts +10 -0
  62. package/src/prompts/templates.ts +336 -0
  63. package/src/resources/index.ts +8 -0
  64. package/src/resources/sessions.ts +196 -0
  65. package/src/tools/compress.ts +138 -0
  66. package/src/tools/index.ts +5 -0
  67. package/src/tools/scratchpad.ts +2659 -0
  68. 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,8 @@
1
+ export {
2
+ allResources,
3
+ allResourceTemplates,
4
+ sessionBranchResource,
5
+ sessionResource,
6
+ sessionSummaryResource,
7
+ sessionsListResource,
8
+ } from "./sessions.ts";
@@ -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";