@gotza02/sequential-thinking 2026.2.20 → 2026.2.22

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 (51) hide show
  1. package/README.md +1 -0
  2. package/dist/codestore.d.ts +28 -0
  3. package/dist/graph.d.ts +60 -0
  4. package/dist/graph.js +19 -0
  5. package/dist/http-server.d.ts +2 -0
  6. package/dist/http-server.js +7 -1
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.js +2 -0
  9. package/dist/lib.d.ts +67 -0
  10. package/dist/lib.js +323 -83
  11. package/dist/notes.d.ts +25 -0
  12. package/dist/system_test.d.ts +1 -0
  13. package/dist/test_ts_req.d.ts +1 -0
  14. package/dist/tools/codestore.d.ts +3 -0
  15. package/dist/tools/coding.d.ts +3 -0
  16. package/dist/tools/filesystem.d.ts +2 -0
  17. package/dist/tools/graph.d.ts +3 -0
  18. package/dist/tools/graph.js +18 -0
  19. package/dist/tools/human.d.ts +65 -0
  20. package/dist/tools/human.js +305 -0
  21. package/dist/tools/notes.d.ts +3 -0
  22. package/dist/tools/thinking.d.ts +3 -0
  23. package/dist/tools/thinking.js +137 -65
  24. package/dist/tools/web.d.ts +2 -0
  25. package/dist/utils.d.ts +32 -0
  26. package/package.json +3 -1
  27. package/dist/chaos.test.js +0 -72
  28. package/dist/codestore.test.js +0 -59
  29. package/dist/coding.test.js +0 -140
  30. package/dist/e2e.test.js +0 -122
  31. package/dist/filesystem.test.js +0 -189
  32. package/dist/graph.test.js +0 -150
  33. package/dist/graph_repro.test.js +0 -63
  34. package/dist/integration.test.js +0 -58
  35. package/dist/notes.test.js +0 -74
  36. package/dist/registration.test.js +0 -39
  37. package/dist/repro_dollar.js +0 -30
  38. package/dist/repro_dollar_simple.js +0 -22
  39. package/dist/repro_history.js +0 -41
  40. package/dist/repro_path.js +0 -17
  41. package/dist/repro_search.test.js +0 -79
  42. package/dist/repro_ts_req.js +0 -3
  43. package/dist/server.test.js +0 -127
  44. package/dist/stress.test.js +0 -68
  45. package/dist/utils.test.js +0 -40
  46. package/dist/verify_cache.test.js +0 -27
  47. package/dist/verify_edit.test.js +0 -66
  48. package/dist/verify_notes.test.js +0 -36
  49. package/dist/verify_viz.test.js +0 -25
  50. package/dist/web_fallback.test.js +0 -103
  51. package/dist/web_read.test.js +0 -60
@@ -0,0 +1,65 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ /**
3
+ * Human-in-the-Loop interaction record
4
+ */
5
+ interface HumanInteraction {
6
+ id: string;
7
+ timestamp: string;
8
+ questionType: 'confirmation' | 'choice' | 'input' | 'review';
9
+ urgency: 'low' | 'medium' | 'high' | 'critical';
10
+ question: string;
11
+ context?: string;
12
+ options?: string[];
13
+ defaultOption?: string;
14
+ status: 'pending' | 'answered' | 'timeout' | 'skipped';
15
+ response?: string;
16
+ respondedAt?: string;
17
+ }
18
+ /**
19
+ * Human-in-the-Loop Manager
20
+ * Manages interactions between AI and human operators
21
+ */
22
+ export declare class HumanInteractionManager {
23
+ private interactions;
24
+ private pendingCallbacks;
25
+ constructor();
26
+ /**
27
+ * Generate unique interaction ID
28
+ */
29
+ private generateId;
30
+ /**
31
+ * Create a new human interaction request
32
+ */
33
+ createInteraction(params: {
34
+ questionType: 'confirmation' | 'choice' | 'input' | 'review';
35
+ urgency: 'low' | 'medium' | 'high' | 'critical';
36
+ question: string;
37
+ context?: string;
38
+ options?: string[];
39
+ defaultOption?: string;
40
+ timeoutMs?: number;
41
+ }): Promise<HumanInteraction>;
42
+ /**
43
+ * Record a response to an interaction
44
+ */
45
+ recordResponse(id: string, response: string): HumanInteraction | null;
46
+ /**
47
+ * Get all pending interactions
48
+ */
49
+ getPendingInteractions(): HumanInteraction[];
50
+ /**
51
+ * Get interaction history
52
+ */
53
+ getHistory(limit?: number): HumanInteraction[];
54
+ /**
55
+ * Clear old interactions (older than specified hours)
56
+ */
57
+ clearOldInteractions(hoursOld?: number): number;
58
+ /**
59
+ * Format interaction for display
60
+ */
61
+ formatInteraction(interaction: HumanInteraction): string;
62
+ }
63
+ export declare function getHumanManager(): HumanInteractionManager;
64
+ export declare function registerHumanTools(server: McpServer): void;
65
+ export {};
@@ -0,0 +1,305 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Human-in-the-Loop Manager
4
+ * Manages interactions between AI and human operators
5
+ */
6
+ export class HumanInteractionManager {
7
+ interactions = new Map();
8
+ pendingCallbacks = new Map();
9
+ constructor() { }
10
+ /**
11
+ * Generate unique interaction ID
12
+ */
13
+ generateId() {
14
+ return `hitl_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
15
+ }
16
+ /**
17
+ * Create a new human interaction request
18
+ */
19
+ async createInteraction(params) {
20
+ const id = this.generateId();
21
+ const interaction = {
22
+ id,
23
+ timestamp: new Date().toISOString(),
24
+ questionType: params.questionType,
25
+ urgency: params.urgency,
26
+ question: params.question,
27
+ context: params.context,
28
+ options: params.options,
29
+ defaultOption: params.defaultOption,
30
+ status: 'pending'
31
+ };
32
+ this.interactions.set(id, interaction);
33
+ return interaction;
34
+ }
35
+ /**
36
+ * Record a response to an interaction
37
+ */
38
+ recordResponse(id, response) {
39
+ const interaction = this.interactions.get(id);
40
+ if (!interaction)
41
+ return null;
42
+ interaction.status = 'answered';
43
+ interaction.response = response;
44
+ interaction.respondedAt = new Date().toISOString();
45
+ // Resolve any pending callback
46
+ const callback = this.pendingCallbacks.get(id);
47
+ if (callback) {
48
+ clearTimeout(callback.timeout);
49
+ callback.resolve(response);
50
+ this.pendingCallbacks.delete(id);
51
+ }
52
+ return interaction;
53
+ }
54
+ /**
55
+ * Get all pending interactions
56
+ */
57
+ getPendingInteractions() {
58
+ return Array.from(this.interactions.values())
59
+ .filter(i => i.status === 'pending')
60
+ .sort((a, b) => {
61
+ // Sort by urgency then by timestamp
62
+ const urgencyOrder = { critical: 0, high: 1, medium: 2, low: 3 };
63
+ const urgencyDiff = urgencyOrder[a.urgency] - urgencyOrder[b.urgency];
64
+ if (urgencyDiff !== 0)
65
+ return urgencyDiff;
66
+ return new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime();
67
+ });
68
+ }
69
+ /**
70
+ * Get interaction history
71
+ */
72
+ getHistory(limit = 50) {
73
+ return Array.from(this.interactions.values())
74
+ .sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())
75
+ .slice(0, limit);
76
+ }
77
+ /**
78
+ * Clear old interactions (older than specified hours)
79
+ */
80
+ clearOldInteractions(hoursOld = 24) {
81
+ const cutoff = Date.now() - (hoursOld * 60 * 60 * 1000);
82
+ let cleared = 0;
83
+ for (const [id, interaction] of this.interactions) {
84
+ if (new Date(interaction.timestamp).getTime() < cutoff) {
85
+ this.interactions.delete(id);
86
+ cleared++;
87
+ }
88
+ }
89
+ return cleared;
90
+ }
91
+ /**
92
+ * Format interaction for display
93
+ */
94
+ formatInteraction(interaction) {
95
+ const urgencyEmoji = {
96
+ critical: '🚨',
97
+ high: '⚠️',
98
+ medium: '📋',
99
+ low: 'ℹ️'
100
+ };
101
+ const typeLabel = {
102
+ confirmation: 'ยืนยัน (Yes/No)',
103
+ choice: 'เลือกตัวเลือก',
104
+ input: 'ต้องการข้อมูล',
105
+ review: 'ตรวจสอบ/อนุมัติ'
106
+ };
107
+ let output = `\n${'═'.repeat(60)}\n`;
108
+ output += `${urgencyEmoji[interaction.urgency]} HUMAN INPUT REQUIRED [${interaction.urgency.toUpperCase()}]\n`;
109
+ output += `${'─'.repeat(60)}\n`;
110
+ output += `📌 Type: ${typeLabel[interaction.questionType]}\n`;
111
+ output += `🆔 ID: ${interaction.id}\n`;
112
+ output += `⏰ Time: ${interaction.timestamp}\n`;
113
+ output += `${'─'.repeat(60)}\n`;
114
+ output += `❓ Question:\n ${interaction.question}\n`;
115
+ if (interaction.context) {
116
+ output += `\n📝 Context:\n ${interaction.context}\n`;
117
+ }
118
+ if (interaction.options && interaction.options.length > 0) {
119
+ output += `\n📋 Options:\n`;
120
+ interaction.options.forEach((opt, i) => {
121
+ const isDefault = opt === interaction.defaultOption;
122
+ output += ` ${i + 1}. ${opt}${isDefault ? ' (default)' : ''}\n`;
123
+ });
124
+ }
125
+ if (interaction.defaultOption && interaction.questionType === 'confirmation') {
126
+ output += `\n Default: ${interaction.defaultOption}\n`;
127
+ }
128
+ output += `${'═'.repeat(60)}\n`;
129
+ output += `💡 To respond, use: respond_to_human tool with id="${interaction.id}"\n`;
130
+ return output;
131
+ }
132
+ }
133
+ // Singleton instance for the manager
134
+ let humanManager = null;
135
+ export function getHumanManager() {
136
+ if (!humanManager) {
137
+ humanManager = new HumanInteractionManager();
138
+ }
139
+ return humanManager;
140
+ }
141
+ export function registerHumanTools(server) {
142
+ const manager = getHumanManager();
143
+ // --- ask_human Tool ---
144
+ server.tool("ask_human", `Request human input or decision during AI operation. Use this tool when:
145
+ - A destructive or irreversible action needs confirmation (e.g., "Delete database?")
146
+ - Multiple valid approaches exist and human preference is needed
147
+ - Critical decisions that could have significant impact
148
+ - Clarification is needed on ambiguous requirements
149
+ - Review/approval is required before proceeding
150
+
151
+ This transforms the AI from "guessing" to "collaborative" mode.
152
+
153
+ Question Types:
154
+ - confirmation: Yes/No questions (e.g., "Proceed with deletion?")
155
+ - choice: Select from predefined options (e.g., "Which framework?")
156
+ - input: Free-form text input needed (e.g., "What should the function be named?")
157
+ - review: Present work for human review/approval
158
+
159
+ Urgency Levels:
160
+ - critical: Immediate response required, blocks all operations
161
+ - high: Important decision, should respond soon
162
+ - medium: Normal priority question
163
+ - low: Nice to have input, can proceed with default if no response`, {
164
+ question: z.string().describe("The question to ask the human"),
165
+ questionType: z.enum(['confirmation', 'choice', 'input', 'review'])
166
+ .default('input')
167
+ .describe("Type of question being asked"),
168
+ urgency: z.enum(['low', 'medium', 'high', 'critical'])
169
+ .default('medium')
170
+ .describe("Urgency level of the question"),
171
+ context: z.string().optional()
172
+ .describe("Additional context explaining why this input is needed"),
173
+ options: z.array(z.string()).optional()
174
+ .describe("Available options for 'choice' type questions"),
175
+ defaultOption: z.string().optional()
176
+ .describe("Default option if human doesn't respond (for non-critical)")
177
+ }, async ({ question, questionType, urgency, context, options, defaultOption }) => {
178
+ // Validate options for choice type
179
+ if (questionType === 'choice' && (!options || options.length < 2)) {
180
+ return {
181
+ content: [{
182
+ type: "text",
183
+ text: "Error: 'choice' question type requires at least 2 options"
184
+ }],
185
+ isError: true
186
+ };
187
+ }
188
+ const interaction = await manager.createInteraction({
189
+ questionType,
190
+ urgency,
191
+ question,
192
+ context,
193
+ options,
194
+ defaultOption
195
+ });
196
+ const formatted = manager.formatInteraction(interaction);
197
+ return {
198
+ content: [{
199
+ type: "text",
200
+ text: formatted + `\n\n⏳ Status: WAITING FOR HUMAN RESPONSE\n\nThe AI should pause this line of action until a response is received via 'respond_to_human' or 'get_pending_questions'.`
201
+ }]
202
+ };
203
+ });
204
+ // --- respond_to_human Tool ---
205
+ server.tool("respond_to_human", "Provide a response to a pending human-in-the-loop question. Use this after receiving human input.", {
206
+ interactionId: z.string().describe("The interaction ID from ask_human"),
207
+ response: z.string().describe("The human's response to the question")
208
+ }, async ({ interactionId, response }) => {
209
+ const interaction = manager.recordResponse(interactionId, response);
210
+ if (!interaction) {
211
+ return {
212
+ content: [{
213
+ type: "text",
214
+ text: `Error: No pending interaction found with ID "${interactionId}"`
215
+ }],
216
+ isError: true
217
+ };
218
+ }
219
+ return {
220
+ content: [{
221
+ type: "text",
222
+ text: `✅ Response recorded for interaction ${interactionId}\n\n` +
223
+ `Question: ${interaction.question}\n` +
224
+ `Response: ${response}\n` +
225
+ `Responded at: ${interaction.respondedAt}\n\n` +
226
+ `The AI can now proceed based on this human decision.`
227
+ }]
228
+ };
229
+ });
230
+ // --- get_pending_questions Tool ---
231
+ server.tool("get_pending_questions", "Get all pending human-in-the-loop questions that need responses.", {}, async () => {
232
+ const pending = manager.getPendingInteractions();
233
+ if (pending.length === 0) {
234
+ return {
235
+ content: [{
236
+ type: "text",
237
+ text: "✅ No pending questions. All human interactions have been addressed."
238
+ }]
239
+ };
240
+ }
241
+ let output = `📋 PENDING HUMAN INTERACTIONS (${pending.length})\n`;
242
+ output += `${'═'.repeat(60)}\n\n`;
243
+ for (const interaction of pending) {
244
+ output += manager.formatInteraction(interaction);
245
+ output += '\n';
246
+ }
247
+ return {
248
+ content: [{
249
+ type: "text",
250
+ text: output
251
+ }]
252
+ };
253
+ });
254
+ // --- get_interaction_history Tool ---
255
+ server.tool("get_interaction_history", "Get the history of human-AI interactions for context and learning.", {
256
+ limit: z.number().int().min(1).max(100).default(20)
257
+ .describe("Maximum number of interactions to return")
258
+ }, async ({ limit }) => {
259
+ const history = manager.getHistory(limit);
260
+ if (history.length === 0) {
261
+ return {
262
+ content: [{
263
+ type: "text",
264
+ text: "No interaction history found."
265
+ }]
266
+ };
267
+ }
268
+ let output = `📜 INTERACTION HISTORY (${history.length} most recent)\n`;
269
+ output += `${'═'.repeat(60)}\n\n`;
270
+ for (const interaction of history) {
271
+ const statusEmoji = {
272
+ pending: '⏳',
273
+ answered: '✅',
274
+ timeout: '⏱️',
275
+ skipped: '⏭️'
276
+ };
277
+ output += `${statusEmoji[interaction.status]} [${interaction.id}]\n`;
278
+ output += ` Type: ${interaction.questionType} | Urgency: ${interaction.urgency}\n`;
279
+ output += ` Q: ${interaction.question.substring(0, 80)}${interaction.question.length > 80 ? '...' : ''}\n`;
280
+ if (interaction.response) {
281
+ output += ` A: ${interaction.response.substring(0, 80)}${interaction.response.length > 80 ? '...' : ''}\n`;
282
+ }
283
+ output += ` Time: ${interaction.timestamp}\n\n`;
284
+ }
285
+ return {
286
+ content: [{
287
+ type: "text",
288
+ text: output
289
+ }]
290
+ };
291
+ });
292
+ // --- clear_old_interactions Tool ---
293
+ server.tool("clear_old_interactions", "Clear old interaction history to free up memory.", {
294
+ hoursOld: z.number().int().min(1).default(24)
295
+ .describe("Clear interactions older than this many hours")
296
+ }, async ({ hoursOld }) => {
297
+ const cleared = manager.clearOldInteractions(hoursOld);
298
+ return {
299
+ content: [{
300
+ type: "text",
301
+ text: `🗑️ Cleared ${cleared} interactions older than ${hoursOld} hours.`
302
+ }]
303
+ };
304
+ });
305
+ }
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { NotesManager } from '../notes.js';
3
+ export declare function registerNoteTools(server: McpServer, notesManager: NotesManager): void;
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { SequentialThinkingServer } from '../lib.js';
3
+ export declare function registerThinkingTools(server: McpServer, thinkingServer: SequentialThinkingServer): void;
@@ -1,71 +1,94 @@
1
1
  import { z } from "zod";
2
2
  export function registerThinkingTools(server, thinkingServer) {
3
- // --- Sequential Thinking Tool ---
4
- server.tool("sequentialthinking", `A specialized tool for Deepest Thinking, providing dynamic and reflective problem-solving.
5
- This tool mandates a rigorous analysis process that adapts and evolves as understanding deepens.
6
- Use this tool ALWAYS for complex queries to ensure the most thorough and accurate solution.
3
+ // --- Sequential Thinking Tool (Opus 4.5 Interleaved Mode) ---
4
+ server.tool("sequentialthinking", `CORE THINKING ENGINE (OPUS-4.5 INTERLEAVED MODE).
5
+ Use this tool to structure your reasoning, plan actions, and analyze results.
6
+ The system is now BLOCK-BASED to handle complex, multi-stage tasks.
7
7
 
8
- Deepest Thinking Requirements:
9
- - Mandatory Analysis: Break down problems into atomic requirements before generating solutions.
10
- - Mandatory Reflexion: Critique your own thoughts regularly to identify biases or errors.
11
- - Mandatory Branching: Explore alternative hypotheses (Conservative/Balanced/Aggressive) for critical decisions.
12
- - Dynamic Depth: Adjust total_thoughts as new complexities are discovered.
13
- - Correctness focus: Repeat the process until a verified, satisfactory answer is reached.
8
+ ═══════════════════════════════════════════════════════════════
9
+ THOUGHT TYPES (NEW)
10
+ ═══════════════════════════════════════════════════════════════
11
+ - 'analysis' : Understand the problem / Break down requirements
12
+ - 'planning' : Formulate a plan / Decide next steps BEFORE executing
13
+ - 'execution' : Explicitly state what tool you are about to call
14
+ - 'observation' : Record the OUTPUT of a tool call (MANDATORY after execution)
15
+ - 'hypothesis' : Form a new hypothesis based on observations
16
+ - 'reflexion' : Critique your progress / Check for errors / Self-review
17
+ - 'solution' : Final answer / Task completion
14
18
 
15
- When to use this tool:
16
- - Breaking down complex problems into steps
17
- - Planning and design with room for revision
18
- - Analysis that might need course correction
19
- - Problems where the full scope might not be clear initially
20
- - Problems that require a multi-step solution
21
- - Tasks that need to maintain context over multiple steps
22
- - Situations where irrelevant information needs to be filtered out
19
+ Legacy types (still supported):
20
+ - 'generation' : Generate multiple options
21
+ - 'evaluation' : Evaluate options with scoring
22
+ - 'selection' : Select the best option
23
23
 
24
- Key features:
25
- - Tree of Thoughts: Generate and evaluate multiple options.
26
- - Self-Critique: Check for risks, biases, and errors in thinking.
27
- - Hypothesis Testing: Formulate and verify hypotheses based on Chain of Thought.
28
- - Branch Merging: Combine insights from multiple divergent paths.
24
+ ═══════════════════════════════════════════════════════════════
25
+ INTERLEAVED WORKFLOW RULE (CRITICAL)
26
+ ═══════════════════════════════════════════════════════════════
27
+ The correct flow is:
29
28
 
30
- Troubleshooting & Stuck States:
31
- - If you realize you are stuck in a loop or a bug persists after 2 attempts:
32
- 1. Do NOT continue linear thoughts.
33
- 2. Create a NEW BRANCH ('branchFromThought') from a point before the error.
34
- 3. Explicitly state "Stuck detected, branching to explore Approach B".
35
- 4. Change your fundamental assumptions or implementation strategy completely.
29
+ Analysis -> Planning -> Execution -> [Call Tool] -> Observation -> Analysis -> ...
36
30
 
37
- Parameters explained:
38
- - thought: Your current thinking step (analysis, revision, question, hypothesis).
39
- - nextThoughtNeeded: True if you need more thinking, even if at what seemed like the end.
40
- - thoughtNumber: Current number in sequence.
41
- - totalThoughts: Current estimate of thoughts needed (can be adjusted).
42
- - isRevision: True if this thought revises previous thinking.
43
- - revisesThought: Which thought number is being reconsidered.
44
- - branchFromThought: The branching point thought number.
45
- - branchId: Identifier for the current branch.
46
- - thoughtType: The type of thought (analysis, generation, evaluation, reflexion, selection).
47
- - score: Score for evaluation (1-10).
48
- - options: List of options generated.
49
- - selectedOption: The option selected.
31
+ 1. BEFORE calling any tool, use 'execution' type to declare your intent
32
+ 2. AFTER a tool returns, use 'observation' type to record and analyze the result
33
+ 3. The system will WARN you if you skip the observation step
50
34
 
51
- You MUST:
52
- 1. Use thoughtType: 'analysis' for the first steps to map requirements.
53
- 2. Use thoughtType: 'reflexion' frequently to validate logic.
54
- 3. Use thoughtType: 'evaluation' and 'selection' when choosing between branches.
55
- 4. Only set nextThoughtNeeded to false when the solution is definitive and fully verified.`, {
35
+ Example flow:
36
+ T1: analysis - "I need to read the config file to understand the structure"
37
+ T2: planning - "I will use read_file tool on config.json"
38
+ T3: execution - "Calling read_file on ./config.json" [relatedToolCall: "read_file"]
39
+ [Tool Call: read_file]
40
+ T4: observation - "The config has 3 sections: auth, database, logging" [toolResult: "..."]
41
+ T5: analysis - "Now I need to modify the database section"
42
+ ...
43
+
44
+ ═══════════════════════════════════════════════════════════════
45
+ BLOCKS (Context Grouping)
46
+ ═══════════════════════════════════════════════════════════════
47
+ Thoughts are grouped into 'blocks' by topic. When switching topics:
48
+ - Start a new block with a new blockId (e.g., 'debug-auth', 'implement-api')
49
+ - This prevents false-positive loop detection when changing context
50
+ - Old blocks are auto-archived to save memory
51
+
52
+ ═══════════════════════════════════════════════════════════════
53
+ SMART WARNINGS
54
+ ═══════════════════════════════════════════════════════════════
55
+ The system will warn you when:
56
+ - STALLING: Too many thinking steps without execution
57
+ - LOOP: Repeating the same action
58
+ - MISSING OBSERVATION: Skipping result analysis after tool call
59
+ - NO PLANNING: Executing without a planning step
60
+ - NO VERIFICATION: Ending without testing/checking
61
+
62
+ ═══════════════════════════════════════════════════════════════
63
+ TROUBLESHOOTING
64
+ ═══════════════════════════════════════════════════════════════
65
+ If stuck in a loop:
66
+ 1. Do NOT continue linear thoughts
67
+ 2. Create a NEW BRANCH ('branchFromThought') from before the error
68
+ 3. State "Stuck detected, branching to explore Approach B"
69
+ 4. Change your assumptions completely`, {
56
70
  thought: z.string().describe("Your current thinking step"),
57
- nextThoughtNeeded: z.boolean().describe("Whether another thought step is needed"),
58
- thoughtNumber: z.number().int().min(1).describe("Current thought number (numeric value, e.g., 1, 2, 3)"),
59
- totalThoughts: z.number().int().min(1).describe("Estimated total thoughts needed (numeric value, e.g., 5, 10)"),
71
+ thoughtType: z.enum([
72
+ 'analysis', 'planning', 'execution', 'observation',
73
+ 'hypothesis', 'reflexion', 'solution',
74
+ 'generation', 'evaluation', 'selection'
75
+ ]).describe("The structural role of this thought (see THOUGHT TYPES above)"),
76
+ thoughtNumber: z.number().int().min(1).describe("Current thought number (e.g., 1, 2, 3)"),
77
+ totalThoughts: z.number().int().min(1).describe("Estimated total thoughts needed (can be adjusted)"),
78
+ nextThoughtNeeded: z.boolean().describe("True if more thinking/action is needed"),
79
+ // New Interleaved Fields
80
+ blockId: z.string().optional().describe("ID for the current topic block (e.g., 'auth-debug', 'api-research'). Keep same ID to stay in context."),
81
+ relatedToolCall: z.string().optional().describe("If type='execution', specify the tool name here (e.g., 'read_file', 'edit_file')"),
82
+ toolResult: z.string().optional().describe("If type='observation', summarize the key findings from the tool output here"),
83
+ // Legacy Fields (backwards compatible)
60
84
  isRevision: z.boolean().optional().describe("Whether this revises previous thinking"),
61
- revisesThought: z.number().int().min(1).optional().describe("Which thought is being reconsidered"),
85
+ revisesThought: z.number().int().min(1).optional().describe("Which thought number is being reconsidered"),
62
86
  branchFromThought: z.number().int().min(1).optional().describe("Branching point thought number"),
63
- branchId: z.string().optional().describe("Branch identifier"),
64
- needsMoreThoughts: z.boolean().optional().describe("If more thoughts are needed"),
65
- thoughtType: z.enum(['analysis', 'generation', 'evaluation', 'reflexion', 'selection']).optional().describe("The type of thought"),
66
- score: z.number().min(1).max(10).optional().describe("Score for evaluation (1-10)"),
67
- options: z.array(z.string()).optional().describe("List of options generated"),
68
- selectedOption: z.string().optional().describe("The option selected")
87
+ branchId: z.string().optional().describe("Branch identifier (e.g., 'approach-b', 'alternative')"),
88
+ needsMoreThoughts: z.boolean().optional().describe("If more thoughts are needed beyond totalThoughts"),
89
+ score: z.number().min(1).max(10).optional().describe("Score for evaluation type (1-10)"),
90
+ options: z.array(z.string()).optional().describe("List of options for generation type"),
91
+ selectedOption: z.string().optional().describe("The option selected for selection type")
69
92
  }, async (args) => {
70
93
  const result = await thinkingServer.processThought(args);
71
94
  return {
@@ -73,15 +96,15 @@ You MUST:
73
96
  isError: result.isError
74
97
  };
75
98
  });
76
- // 11. clear_thought_history
77
- server.tool("clear_thought_history", "Clear the sequential thinking history.", {}, async () => {
99
+ // --- Clear Thought History ---
100
+ server.tool("clear_thought_history", "Clear the sequential thinking history. Use this to start fresh when changing to a completely different task.", {}, async () => {
78
101
  await thinkingServer.clearHistory();
79
102
  return {
80
- content: [{ type: "text", text: "Thought history cleared." }]
103
+ content: [{ type: "text", text: "Thought history cleared. All blocks reset." }]
81
104
  };
82
105
  });
83
- // 12. summarize_history
84
- server.tool("summarize_history", "Compress multiple thoughts into a single summary thought to save space/context.", {
106
+ // --- Summarize History ---
107
+ server.tool("summarize_history", "Compress multiple thoughts into a single summary thought to save space/context. Useful for long-running tasks.", {
85
108
  startIndex: z.number().int().min(1).describe("The starting thought number to summarize"),
86
109
  endIndex: z.number().int().min(1).describe("The ending thought number to summarize"),
87
110
  summary: z.string().describe("The summary text that replaces the range")
@@ -99,9 +122,9 @@ You MUST:
99
122
  };
100
123
  }
101
124
  });
102
- // 13. search_thoughts
103
- server.tool("search_thoughts", "Search through the thinking history to recall specific details or past decisions.", {
104
- query: z.string().describe("The search term or keyword to look for")
125
+ // --- Search Thoughts ---
126
+ server.tool("search_thoughts", "Search through the thinking history to recall specific details, past decisions, or tool results.", {
127
+ query: z.string().describe("The search term or keyword to look for (searches thought content, types, blocks, and tool calls)")
105
128
  }, async ({ query }) => {
106
129
  try {
107
130
  const results = await thinkingServer.searchHistory(query);
@@ -121,4 +144,53 @@ You MUST:
121
144
  };
122
145
  }
123
146
  });
147
+ // --- Start New Block ---
148
+ server.tool("start_thinking_block", "Explicitly start a new thinking block for a new topic/context. Use this when switching between distinct tasks to prevent false loop detection.", {
149
+ blockId: z.string().describe("Unique ID for the new block (e.g., 'debug-auth', 'implement-feature-x')"),
150
+ topic: z.string().describe("Short description of what this block is about")
151
+ }, async ({ blockId, topic }) => {
152
+ try {
153
+ thinkingServer.startNewBlock(blockId, topic);
154
+ return {
155
+ content: [{
156
+ type: "text",
157
+ text: `New thinking block started.\nBlock ID: ${blockId}\nTopic: ${topic}\n\nPrevious block has been archived. You can now think about "${topic}" without interference from previous context.`
158
+ }]
159
+ };
160
+ }
161
+ catch (error) {
162
+ return {
163
+ content: [{ type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
164
+ isError: true
165
+ };
166
+ }
167
+ });
168
+ // --- Get Blocks Summary ---
169
+ server.tool("get_thinking_blocks", "Get a summary of all thinking blocks to understand your thinking history across different topics.", {}, async () => {
170
+ try {
171
+ const blocks = thinkingServer.getBlocksSummary();
172
+ const currentBlock = thinkingServer.getCurrentBlock();
173
+ if (blocks.length === 0) {
174
+ return {
175
+ content: [{ type: "text", text: "No thinking blocks found. Start thinking to create your first block." }]
176
+ };
177
+ }
178
+ let output = `Thinking Blocks Summary (${blocks.length} blocks):\n\n`;
179
+ for (const block of blocks) {
180
+ const isCurrent = currentBlock && block.id === currentBlock.id;
181
+ output += `${isCurrent ? '>>> ' : ' '}[${block.status.toUpperCase()}] ${block.id}\n`;
182
+ output += ` Topic: ${block.topic}\n`;
183
+ output += ` Thoughts: ${block.thoughtCount}\n\n`;
184
+ }
185
+ return {
186
+ content: [{ type: "text", text: output }]
187
+ };
188
+ }
189
+ catch (error) {
190
+ return {
191
+ content: [{ type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
192
+ isError: true
193
+ };
194
+ }
195
+ });
124
196
  }
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerWebTools(server: McpServer): void;
@@ -0,0 +1,32 @@
1
+ export declare function execAsync(command: string, options?: {
2
+ timeout?: number;
3
+ maxBuffer?: number;
4
+ }): Promise<{
5
+ stdout: string;
6
+ stderr: string;
7
+ }>;
8
+ export declare class AsyncMutex {
9
+ private mutex;
10
+ lock(): Promise<() => void>;
11
+ dispatch<T>(fn: (() => T | PromiseLike<T>)): Promise<T>;
12
+ }
13
+ export declare function validatePath(requestedPath: string): string;
14
+ export declare function validatePublicUrl(urlString: string): Promise<void>;
15
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
16
+ declare class Logger {
17
+ private level;
18
+ constructor();
19
+ private shouldLog;
20
+ debug(msg: string, ...args: any[]): void;
21
+ info(msg: string, ...args: any[]): void;
22
+ warn(msg: string, ...args: any[]): void;
23
+ error(msg: string, ...args: any[]): void;
24
+ }
25
+ export declare const logger: Logger;
26
+ export declare const DEFAULT_HEADERS: {
27
+ 'User-Agent': string;
28
+ Accept: string;
29
+ 'Accept-Language': string;
30
+ };
31
+ export declare function fetchWithRetry(url: string, options?: any, retries?: number, backoff?: number): Promise<Response>;
32
+ export {};