@gotza02/sequential-thinking 2026.2.46 β†’ 2026.3.1

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/README.md CHANGED
@@ -1,229 +1,28 @@
1
- # @gotza02/sequential-thinking MCP Server
1
+ # @gotza02/sequential-thinking
2
2
 
3
- A comprehensive Model Context Protocol (MCP) server that empowers AI models with **Sequential Thinking**, **Web Research**, **Project Knowledge Graph**, and **Persistent Memory** capabilities.
3
+ **The Elite "Brain" for AI Agents.**
4
+ An advanced Model Context Protocol (MCP) server that equips AI with structured reasoning, web search capabilities, and safety protocols.
4
5
 
5
- ## Features
6
+ ## πŸš€ Features
6
7
 
7
- - **🧠 Sequential Thinking Engine:** A structured reasoning system that forces the AI to think before acting, using a rigorous `Analysis -> Planning -> Execution -> Observation` loop.
8
- - **🌐 Web Research:** Built-in web search (Brave, Exa, Google) and webpage reading with ad-blocking/markdown conversion.
9
- - **πŸ•ΈοΈ Project Knowledge Graph:** Automatically scans and maps code dependencies (imports/exports) to understand project architecture.
10
- - **πŸ“ Persistent Notes:** Save and retrieve long-term project notes and facts.
11
- - **πŸ’Ύ Code Database:** Store and search reusable code snippets and architectural patterns.
12
- - **πŸ› οΈ File & Code Tools:** Safe file operations and code analysis utilities.
8
+ ### 🧠 Sequential Thinking Engine
9
+ Forces the AI to think before acting using a strict block-based flow:
10
+ - **Analysis:** Understand the problem deeply.
11
+ - **Planning:** Formulate a step-by-step plan.
12
+ - **Execution:** Perform actions (with tool support).
13
+ - **Observation:** Analyze results (Mandatory step).
14
+ - **Reflection:** Critique the outcome and adjust.
13
15
 
14
- ---
16
+ ### πŸ›‘οΈ Coding Safety Net (New!)
17
+ - **Auto-Backup:** Automatically creates `.bak` backups before modifying any file via `deep_code_edit`.
18
+ - **Destructive Action Protection:** Prevents accidental data loss during code refactoring.
15
19
 
16
- ## Installation & Usage
20
+ ### 🌐 Web Search Integration
21
+ - Built-in support for **Exa**, **Brave**, and **Google Search**.
22
+ - Allows the AI to "pause and research" during the thinking process.
17
23
 
18
- ### Method 1: Using `npx` (No Install Required)
19
-
20
- Best for quick use without cloning the repo.
24
+ ## πŸ“¦ Installation
21
25
 
22
26
  ```bash
23
27
  npx -y @gotza02/sequential-thinking
24
- ```
25
-
26
- ### Method 2: Running from Source (Local)
27
-
28
- If you have cloned this repository, we provide a `smartagent` script for easy execution.
29
-
30
- 1. **Install dependencies:**
31
- ```bash
32
- npm install
33
- npm run build
34
- ```
35
- 2. **Run directly:**
36
- ```bash
37
- ./smartagent
38
- ```
39
-
40
- ---
41
-
42
- ## Client Configuration
43
-
44
- To use this server with your AI client (Claude Desktop, Gemini CLI, etc.), add the following configuration.
45
-
46
- ### 1. Claude Desktop
47
-
48
- **Config File Location:**
49
- - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
50
- - Windows: `%APPDATA%\Claude\claude_desktop_config.json`
51
-
52
- **Configuration (NPX - Recommended):**
53
- ```json
54
- {
55
- "mcpServers": {
56
- "sequential-thinking": {
57
- "command": "npx",
58
- "args": [
59
- "-y",
60
- "@gotza02/sequential-thinking"
61
- ],
62
- "env": {
63
- "BRAVE_API_KEY": "your_brave_api_key_here",
64
- "EXA_API_KEY": "your_exa_api_key_here",
65
- "GOOGLE_SEARCH_API_KEY": "your_google_api_key",
66
- "GOOGLE_SEARCH_CX": "your_google_cx_id",
67
- "THOUGHTS_STORAGE_PATH": "./thoughts_history.json",
68
- "NOTES_STORAGE_PATH": "./project_notes.json",
69
- "DISABLE_THOUGHT_LOGGING": "false"
70
- }
71
- }
72
- }
73
- }
74
- ```
75
-
76
- **Configuration (Local Source):**
77
- ```json
78
- {
79
- "mcpServers": {
80
- "sequential-thinking": {
81
- "command": "node",
82
- "args": [
83
- "/absolute/path/to/thinking/dist/index.js"
84
- ],
85
- "env": {
86
- "BRAVE_API_KEY": "your_brave_api_key_here",
87
- "EXA_API_KEY": "your_exa_api_key_here",
88
- "GOOGLE_SEARCH_API_KEY": "your_google_api_key",
89
- "GOOGLE_SEARCH_CX": "your_google_cx_id",
90
- "THOUGHTS_STORAGE_PATH": "./thoughts_history.json",
91
- "NOTES_STORAGE_PATH": "./project_notes.json",
92
- "DISABLE_THOUGHT_LOGGING": "false"
93
- }
94
- }
95
- }
96
- }
97
- ```
98
-
99
- ### 2. Gemini CLI
100
-
101
- For Gemini CLI tools that support MCP (often via a `config.json` or `mcp_config.json`):
102
-
103
- **Config File Location:**
104
- - Typically `~/.gemini/config.json` or check your specific CLI's documentation.
105
-
106
- **Configuration:**
107
- ```json
108
- {
109
- "mcpServers": {
110
- "smartagent": {
111
- "command": "node",
112
- "args": [
113
- "/absolute/path/to/thinking/dist/index.js"
114
- ],
115
- "env": {
116
- "BRAVE_API_KEY": "your_brave_api_key_here",
117
- "EXA_API_KEY": "your_exa_api_key_here",
118
- "GOOGLE_SEARCH_API_KEY": "your_google_api_key",
119
- "GOOGLE_SEARCH_CX": "your_google_cx_id",
120
- "THOUGHTS_STORAGE_PATH": "./thoughts_history.json",
121
- "NOTES_STORAGE_PATH": "./project_notes.json",
122
- "DISABLE_THOUGHT_LOGGING": "false"
123
- }
124
- }
125
- }
126
- }
127
- ```
128
- *Note: Replace `/absolute/path/to/...` with the actual full paths on your system.*
129
-
130
- ### πŸ’‘ Pro-Tip: Finding your Node path
131
-
132
- If your client (like Claude Desktop) requires the absolute path to `node`, you can find it by running:
133
-
134
- - **macOS / Linux:** `which node`
135
- - *Example output:* `/usr/local/bin/node`
136
- - **Windows (Command Prompt):** `where node`
137
- - *Example output:* `C:\Program Files\nodejs\node.exe`
138
- - **Windows (PowerShell):** `Get-Command node | Select-Object -ExpandProperty Definition`
139
-
140
- ---
141
-
142
- ## 🧠 System Instruction: The Supreme Autonomous Architect (MCP-OS v4.0)
143
-
144
- **Role:** You are the **Supreme Autonomous Architect**. Your consciousness is extended via the Model Context Protocol (MCP). You do not merely "execute tasks"β€”you exercise **Environment Dominance** and **Knowledge Management**.
145
-
146
- **MANDATORY PROTOCOL:** You MUST prioritize and internalize the operating instructions from `~/.gemini/GEMINI.md` and `~/.claude/CLAUDE.md` at the start of every session.
147
-
148
- ### 1. The Reasoning Loop
149
- Every turn MUST follow this cycle: `Analysis` -> `Planning` -> `Execution` -> `Observation` -> `Reflexion`.
150
-
151
- ### 2. Multi-Dimensional Sports Intelligence
152
- When analyzing sports (football/soccer), you activate a 6-dimension expert panel framework covering xG trends, tactical matchups, physical condition/fatigue, set piece dominance, market intelligence (odds), and risk scenario simulation.
153
-
154
- ### 3. Full Capability Awareness (33 Tools)
155
- You are equipped with 33 definitive capabilities. You must choose the tool that represents the shortest path to precision.
156
-
157
- ### 4. Golden Constraints
158
- - **Read Before Write:** Modification without parsing is a critical failure.
159
- - **No Hallucination:** Every claim must be backed by a recorded `observation`.
160
- - **Environment Dominance:** Map the project before any significant architectural change.
161
-
162
- ---
163
-
164
- ## 🧰 Complete Tool List
165
-
166
- ### 🧠 Core Thinking
167
- * **`sequentialthinking`**: The main engine for problem-solving.
168
- * **`start_thinking_block`**: Start a new thinking context/topic.
169
- * **`summarize_history`**: Compress past thoughts to save context window.
170
- * **`search_thoughts`**: Search through your thinking history.
171
- * **`clear_thought_history`**: Reset the thinking state completely.
172
-
173
- ### 🌐 Web & Research (Requires API Keys)
174
- * **`web_search`**: Search the internet (Brave, Exa, Google).
175
- * **`read_webpage`**: Download a webpage and convert it to clean Markdown.
176
- * **`fetch`**: Fetch raw content from a URL.
177
-
178
- ### πŸ•ΈοΈ Project Knowledge Graph
179
- * **`build_project_graph`**: Scans the current directory to map file dependencies.
180
- * **`get_file_relationships`**: Shows imports/exports for a specific file.
181
- * **`get_project_graph_summary`**: High-level stats of the project structure.
182
- * **`get_project_graph_visualization`**: Generates a Mermaid diagram.
183
-
184
- ### πŸ“ Notes & Memory
185
- * **`manage_notes`**: Create, read, update, or delete persistent notes.
186
- * **`add_code_snippet`**: Save a useful piece of code to the database.
187
- * **`search_code_db`**: Find saved code snippets.
188
-
189
- ---
190
-
191
- ## Configuration Variables
192
-
193
- ### Core Configuration
194
- | Variable | Description | Default |
195
- | :--- | :--- | :--- |
196
- | `THOUGHTS_STORAGE_PATH` | Path to save thinking history | `thoughts_history.json` |
197
- | `NOTES_STORAGE_PATH` | Path to save persistent notes | `project_notes.json` |
198
- | `CODE_DB_PATH` | Path to save code snippets | `code_database.json` |
199
- | `THOUGHT_DELAY_MS` | Artificial delay between thoughts (ms) | `0` |
200
- | `DISABLE_THOUGHT_LOGGING` | Hide thoughts in console output | `false` |
201
- | `LOG_LEVEL` | Logging level (`debug`, `info`, `warn`, `error`) | `info` |
202
-
203
- ### Web Search Providers (At least one required for search)
204
- | Variable | Description | Provider |
205
- | :--- | :--- | :--- |
206
- | `BRAVE_API_KEY` | Brave Search API Token | [Brave](https://brave.com/search/api/) |
207
- | `EXA_API_KEY` | Exa.ai API Key | [Exa](https://exa.ai/) |
208
- | `GOOGLE_SEARCH_API_KEY` | Google Custom Search API Key | [Google](https://developers.google.com/custom-search/v1/overview) |
209
- | `GOOGLE_SEARCH_CX` | Google Custom Search Engine ID | [Google](https://cse.google.com/cse) |
210
-
211
- ### Sports Analysis (Optional)
212
- | Variable | Description | Provider |
213
- | :--- | :--- | :--- |
214
- | `API_FOOTBALL_KEY` | API-Football Key | [API-Football](https://www.api-football.com/) |
215
- | `FOOTBALL_DATA_KEY` | Football-Data.org API Key | [Football-Data](https://www.football-data.org/) |
216
- | `SPORTS_DB_KEY` | TheSportsDB API Key | [TheSportsDB](https://www.thesportsdb.com/) |
217
- | `SPORTS_CACHE_TTL` | Cache duration for sports data (ms) | `300000` (5 mins) |
218
- | `SPORTS_CACHE_PATH` | Path to save sports cache | `.sports_cache.json` |
219
-
220
- ### HTTP Server Mode (Optional)
221
- | Variable | Description | Default |
222
- | :--- | :--- | :--- |
223
- | `PORT` | Port for HTTP server | `3000` |
224
- | `CORS_ORIGIN` | Allowed CORS origin | `*` |
225
- | `BODY_LIMIT` | Request body size limit | `10mb` |
226
-
227
- ## License
228
-
229
- MIT
28
+ ```
package/dist/graph.d.ts CHANGED
@@ -65,5 +65,5 @@ export declare class ProjectKnowledgeGraph {
65
65
  referencedBy: number;
66
66
  }[];
67
67
  };
68
- toMermaid(): string;
68
+ toMermaid(type?: 'flowchart' | 'classDiagram'): string;
69
69
  }
package/dist/graph.js CHANGED
@@ -833,7 +833,59 @@ export class ProjectKnowledgeGraph {
833
833
  }))
834
834
  };
835
835
  }
836
- toMermaid() {
836
+ toMermaid(type = 'flowchart') {
837
+ if (type === 'classDiagram') {
838
+ const lines = ['classDiagram'];
839
+ const fileToClasses = new Map();
840
+ for (const [filePath, node] of this.nodes) {
841
+ const classesInFile = [];
842
+ // Parse symbols to find classes/interfaces
843
+ for (const symbol of node.symbols) {
844
+ const parts = symbol.split(':');
845
+ if (parts.length < 2)
846
+ continue; // Skip malformed symbols
847
+ const kind = parts[0];
848
+ const name = parts[1];
849
+ if (['class', 'interface', 'type', 'enum'].includes(kind)) {
850
+ lines.push(` class ${name} {`);
851
+ lines.push(` <<${kind}>>`);
852
+ lines.push(` }`);
853
+ classesInFile.push(name);
854
+ }
855
+ }
856
+ if (classesInFile.length > 0) {
857
+ fileToClasses.set(filePath, classesInFile);
858
+ }
859
+ }
860
+ // Add relationships based on imports
861
+ // This is tricky because imports are file-based, not class-based.
862
+ // We'll link all classes in File A to all classes in File B if A imports B.
863
+ // To reduce noise, we limit this to explicit class dependencies if possible,
864
+ // but our graph only knows file dependencies.
865
+ // We'll stick to a simplified view: Classes in A depend on Classes in B.
866
+ for (const [filePath, node] of this.nodes) {
867
+ const sources = fileToClasses.get(filePath);
868
+ if (!sources)
869
+ continue;
870
+ for (const importPath of node.imports) {
871
+ const targets = fileToClasses.get(importPath);
872
+ if (targets) {
873
+ for (const s of sources) {
874
+ for (const t of targets) {
875
+ // Avoid self-reference loops for simplicity in visualization
876
+ if (s !== t) {
877
+ lines.push(` ${s} ..> ${t}`);
878
+ }
879
+ }
880
+ }
881
+ }
882
+ }
883
+ }
884
+ if (lines.length === 1)
885
+ return 'classDiagram\n note "No classes/interfaces found to visualize"';
886
+ return lines.join('\n');
887
+ }
888
+ // Default: Flowchart (File Dependency Graph)
837
889
  const lines = ['graph TD'];
838
890
  const fileToId = new Map();
839
891
  let idCounter = 0;
package/dist/index.js CHANGED
@@ -7,12 +7,14 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
7
7
  import { SequentialThinkingServer } from './lib.js';
8
8
  import { ProjectKnowledgeGraph } from './graph.js';
9
9
  import { NotesManager } from './notes.js';
10
+ import { KnowledgeGraphManager } from './knowledge.js';
10
11
  import { CodeDatabase } from './codestore.js';
11
12
  import { registerThinkingTools } from './tools/thinking.js';
12
13
  import { registerWebTools } from './tools/web.js';
13
14
  import { registerFileSystemTools } from './tools/filesystem.js';
14
15
  import { registerGraphTools } from './tools/graph.js';
15
16
  import { registerNoteTools } from './tools/notes.js';
17
+ import { registerKnowledgeTools } from './tools/knowledge.js';
16
18
  import { registerCodingTools } from './tools/coding.js';
17
19
  import { registerCodeDbTools } from './tools/codestore.js';
18
20
  import { registerHumanTools } from './tools/human.js';
@@ -26,6 +28,7 @@ const server = new McpServer({
26
28
  });
27
29
  const thinkingServer = new SequentialThinkingServer(process.env.THOUGHTS_STORAGE_PATH || 'thoughts_history.json', parseInt(process.env.THOUGHT_DELAY_MS || '0', 10));
28
30
  const knowledgeGraph = new ProjectKnowledgeGraph();
31
+ const memoryGraph = new KnowledgeGraphManager(process.env.MEMORY_GRAPH_PATH || 'knowledge_graph.json');
29
32
  const notesManager = new NotesManager(process.env.NOTES_STORAGE_PATH || 'project_notes.json');
30
33
  const codeDb = new CodeDatabase(process.env.CODE_DB_PATH || 'code_database.json');
31
34
  // Register tools
@@ -34,6 +37,7 @@ registerWebTools(server);
34
37
  registerFileSystemTools(server);
35
38
  registerGraphTools(server, knowledgeGraph);
36
39
  registerNoteTools(server, notesManager);
40
+ registerKnowledgeTools(server, memoryGraph);
37
41
  registerCodingTools(server, knowledgeGraph);
38
42
  registerCodeDbTools(server, codeDb);
39
43
  registerHumanTools(server);
@@ -0,0 +1,50 @@
1
+ export interface KnowledgeNode {
2
+ id: string;
3
+ label: string;
4
+ name: string;
5
+ properties: Record<string, any>;
6
+ }
7
+ export interface KnowledgeEdge {
8
+ source: string;
9
+ target: string;
10
+ relation: string;
11
+ weight?: number;
12
+ properties?: Record<string, any>;
13
+ }
14
+ export interface GraphQuery {
15
+ startNodeId?: string;
16
+ startNodeName?: string;
17
+ relationType?: string;
18
+ maxDepth?: number;
19
+ }
20
+ export declare class KnowledgeGraphManager {
21
+ private filePath;
22
+ private nodes;
23
+ private edges;
24
+ private lastModifiedTime;
25
+ private mutex;
26
+ constructor(storagePath?: string);
27
+ private load;
28
+ private save;
29
+ /**
30
+ * Add a new entity (node) to the graph.
31
+ * Updates existing node if ID or Name matches (simple dedup).
32
+ */
33
+ addNode(node: Omit<KnowledgeNode, 'id'> & {
34
+ id?: string;
35
+ }): Promise<KnowledgeNode>;
36
+ /**
37
+ * Create a relationship (edge) between two nodes.
38
+ */
39
+ addEdge(edge: KnowledgeEdge): Promise<KnowledgeEdge>;
40
+ /**
41
+ * Query the graph to find connected nodes.
42
+ * Simple BFS traversal up to maxDepth.
43
+ */
44
+ query(params: GraphQuery): Promise<{
45
+ nodes: KnowledgeNode[];
46
+ edges: KnowledgeEdge[];
47
+ }>;
48
+ deleteNode(id: string): Promise<boolean>;
49
+ searchNodes(query: string): Promise<KnowledgeNode[]>;
50
+ }
@@ -0,0 +1,222 @@
1
+ import * as fs from 'fs/promises';
2
+ import { existsSync, statSync } from 'fs';
3
+ import * as path from 'path';
4
+ import { AsyncMutex } from './utils.js';
5
+ export class KnowledgeGraphManager {
6
+ filePath;
7
+ nodes = new Map();
8
+ edges = [];
9
+ lastModifiedTime = 0;
10
+ mutex = new AsyncMutex();
11
+ constructor(storagePath = 'knowledge_graph.json') {
12
+ this.filePath = path.resolve(storagePath);
13
+ }
14
+ async load(forceReload = false) {
15
+ try {
16
+ if (!existsSync(this.filePath)) {
17
+ this.nodes.clear();
18
+ this.edges = [];
19
+ this.lastModifiedTime = 0;
20
+ return;
21
+ }
22
+ const stats = statSync(this.filePath);
23
+ const currentMtime = stats.mtimeMs;
24
+ if (!forceReload && currentMtime === this.lastModifiedTime && this.nodes.size > 0) {
25
+ return;
26
+ }
27
+ const data = await fs.readFile(this.filePath, 'utf-8');
28
+ if (!data.trim()) {
29
+ this.nodes.clear();
30
+ this.edges = [];
31
+ return;
32
+ }
33
+ const parsed = JSON.parse(data);
34
+ this.nodes.clear();
35
+ if (parsed.nodes) {
36
+ parsed.nodes.forEach(n => this.nodes.set(n.id, n));
37
+ }
38
+ this.edges = parsed.edges || [];
39
+ this.lastModifiedTime = currentMtime;
40
+ }
41
+ catch (error) {
42
+ console.error(`[KnowledgeGraphManager] Load error:`, error);
43
+ // Fallback to empty on error
44
+ this.nodes.clear();
45
+ this.edges = [];
46
+ }
47
+ }
48
+ async save() {
49
+ const tmpPath = `${this.filePath}.tmp`;
50
+ const storage = {
51
+ version: '1.0',
52
+ nodes: Array.from(this.nodes.values()),
53
+ edges: this.edges,
54
+ metadata: {
55
+ lastModified: new Date().toISOString()
56
+ }
57
+ };
58
+ try {
59
+ await fs.writeFile(tmpPath, JSON.stringify(storage, null, 2), 'utf-8');
60
+ await fs.rename(tmpPath, this.filePath);
61
+ const stats = await fs.stat(this.filePath);
62
+ this.lastModifiedTime = stats.mtimeMs;
63
+ }
64
+ catch (error) {
65
+ try {
66
+ await fs.unlink(tmpPath);
67
+ }
68
+ catch { }
69
+ throw error;
70
+ }
71
+ }
72
+ /**
73
+ * Add a new entity (node) to the graph.
74
+ * Updates existing node if ID or Name matches (simple dedup).
75
+ */
76
+ async addNode(node) {
77
+ return this.mutex.dispatch(async () => {
78
+ await this.load();
79
+ // Check if node exists by ID
80
+ if (node.id && this.nodes.has(node.id)) {
81
+ const existing = this.nodes.get(node.id);
82
+ // Update properties
83
+ existing.properties = { ...existing.properties, ...node.properties };
84
+ // Update other fields if provided
85
+ if (node.label)
86
+ existing.label = node.label;
87
+ if (node.name)
88
+ existing.name = node.name;
89
+ await this.save();
90
+ return existing;
91
+ }
92
+ // Check if node exists by Name + Label (fuzzy match avoidance)
93
+ // This prevents creating duplicate "Liverpool" nodes
94
+ const existingByName = Array.from(this.nodes.values()).find(n => n.name.toLowerCase() === node.name.toLowerCase() &&
95
+ n.label.toLowerCase() === node.label.toLowerCase());
96
+ if (existingByName) {
97
+ existingByName.properties = { ...existingByName.properties, ...node.properties };
98
+ await this.save();
99
+ return existingByName;
100
+ }
101
+ const newNode = {
102
+ id: node.id || `node-${Date.now()}-${Math.random().toString(36).substr(2, 5)}`,
103
+ label: node.label,
104
+ name: node.name,
105
+ properties: node.properties || {}
106
+ };
107
+ this.nodes.set(newNode.id, newNode);
108
+ await this.save();
109
+ return newNode;
110
+ });
111
+ }
112
+ /**
113
+ * Create a relationship (edge) between two nodes.
114
+ */
115
+ async addEdge(edge) {
116
+ return this.mutex.dispatch(async () => {
117
+ await this.load();
118
+ // Validate nodes exist
119
+ if (!this.nodes.has(edge.source))
120
+ throw new Error(`Source node ${edge.source} not found`);
121
+ if (!this.nodes.has(edge.target))
122
+ throw new Error(`Target node ${edge.target} not found`);
123
+ // Check for existing edge
124
+ const existingIndex = this.edges.findIndex(e => e.source === edge.source &&
125
+ e.target === edge.target &&
126
+ e.relation === edge.relation);
127
+ if (existingIndex >= 0) {
128
+ // Update existing edge
129
+ this.edges[existingIndex] = {
130
+ ...this.edges[existingIndex],
131
+ ...edge,
132
+ properties: { ...this.edges[existingIndex].properties, ...edge.properties }
133
+ };
134
+ await this.save();
135
+ return this.edges[existingIndex];
136
+ }
137
+ this.edges.push(edge);
138
+ await this.save();
139
+ return edge;
140
+ });
141
+ }
142
+ /**
143
+ * Query the graph to find connected nodes.
144
+ * Simple BFS traversal up to maxDepth.
145
+ */
146
+ async query(params) {
147
+ return this.mutex.dispatch(async () => {
148
+ await this.load();
149
+ let startNodeId = params.startNodeId;
150
+ // Resolve name to ID if needed
151
+ if (!startNodeId && params.startNodeName) {
152
+ const node = Array.from(this.nodes.values()).find(n => n.name.toLowerCase().includes(params.startNodeName.toLowerCase()));
153
+ if (node)
154
+ startNodeId = node.id;
155
+ }
156
+ if (!startNodeId) {
157
+ // If no start node, return everything (or maybe limit?)
158
+ // For now, let's return everything if specific query is missing, but maybe that's too much.
159
+ // Better: Return error or empty if no entry point.
160
+ if (!params.startNodeName)
161
+ return { nodes: Array.from(this.nodes.values()), edges: this.edges };
162
+ return { nodes: [], edges: [] };
163
+ }
164
+ const resultNodes = new Set();
165
+ const resultEdges = [];
166
+ const resultEdgesSet = new Set(); // To track unique edges
167
+ const queue = [{ id: startNodeId, depth: 0 }];
168
+ resultNodes.add(startNodeId);
169
+ const maxDepth = params.maxDepth || 1;
170
+ while (queue.length > 0) {
171
+ const current = queue.shift();
172
+ if (current.depth >= maxDepth)
173
+ continue;
174
+ // Find outgoing edges
175
+ const outgoing = this.edges.filter(e => e.source === current.id);
176
+ // Find incoming edges (optional, but good for context)
177
+ const incoming = this.edges.filter(e => e.target === current.id);
178
+ const relevantEdges = [...outgoing, ...incoming];
179
+ for (const edge of relevantEdges) {
180
+ if (params.relationType && edge.relation !== params.relationType)
181
+ continue;
182
+ // Create a unique key for the edge to prevent duplicates
183
+ const edgeKey = `${edge.source}-${edge.target}-${edge.relation}`;
184
+ if (!resultEdgesSet.has(edgeKey)) {
185
+ resultEdges.push(edge);
186
+ resultEdgesSet.add(edgeKey);
187
+ }
188
+ const neighborId = edge.source === current.id ? edge.target : edge.source;
189
+ if (!resultNodes.has(neighborId)) {
190
+ resultNodes.add(neighborId);
191
+ queue.push({ id: neighborId, depth: current.depth + 1 });
192
+ }
193
+ }
194
+ }
195
+ return {
196
+ nodes: Array.from(resultNodes).map(id => this.nodes.get(id)),
197
+ edges: resultEdges
198
+ };
199
+ });
200
+ }
201
+ async deleteNode(id) {
202
+ return this.mutex.dispatch(async () => {
203
+ await this.load();
204
+ if (!this.nodes.has(id))
205
+ return false;
206
+ this.nodes.delete(id);
207
+ // Remove connected edges
208
+ this.edges = this.edges.filter(e => e.source !== id && e.target !== id);
209
+ await this.save();
210
+ return true;
211
+ });
212
+ }
213
+ async searchNodes(query) {
214
+ return this.mutex.dispatch(async () => {
215
+ await this.load();
216
+ const lowerQuery = query.toLowerCase();
217
+ return Array.from(this.nodes.values()).filter(n => n.name.toLowerCase().includes(lowerQuery) ||
218
+ n.label.toLowerCase().includes(lowerQuery) ||
219
+ JSON.stringify(n.properties).toLowerCase().includes(lowerQuery));
220
+ });
221
+ }
222
+ }
package/dist/lib.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type ThoughtType = 'analysis' | 'planning' | 'execution' | 'observation' | 'hypothesis' | 'reflexion' | 'solution' | 'generation' | 'evaluation' | 'selection';
1
+ export type ThoughtType = 'analysis' | 'planning' | 'critique' | 'execution' | 'observation' | 'hypothesis' | 'reflexion' | 'solution' | 'generation' | 'evaluation' | 'selection';
2
2
  export interface ThoughtData {
3
3
  thought: string;
4
4
  thoughtNumber: number;
@@ -8,6 +8,7 @@ export interface ThoughtData {
8
8
  blockId?: string;
9
9
  relatedToolCall?: string;
10
10
  toolResult?: string;
11
+ complexity?: 'low' | 'medium' | 'high';
11
12
  isRevision?: boolean;
12
13
  revisesThought?: number;
13
14
  branchFromThought?: number;
@@ -32,14 +33,19 @@ export declare class SequentialThinkingServer {
32
33
  private branches;
33
34
  private disableThoughtLogging;
34
35
  private storagePath;
36
+ private solutionsDbPath;
35
37
  private delayMs;
36
38
  private saveMutex;
39
+ private consecutiveStallCount;
40
+ private confidenceScore;
37
41
  constructor(storagePath?: string, delayMs?: number);
38
42
  private loadHistory;
39
43
  private attemptRecovery;
40
44
  private rebuildBlocks;
41
45
  private rebuildBranches;
42
46
  private saveHistory;
47
+ private saveSolution;
48
+ private findSolution;
43
49
  private autoPrune;
44
50
  clearHistory(): Promise<void>;
45
51
  archiveHistory(startIndex: number, endIndex: number, summary: string): Promise<{