@gotza02/sequential-thinking 2026.2.4 → 2026.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,13 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest';
2
+ import { ProjectKnowledgeGraph } from './graph.js';
3
+ // Note: In a real test we'd use a temporary directory
4
+ describe('Deep Coding Tools Logic', () => {
5
+ let graph;
6
+ beforeEach(() => {
7
+ graph = new ProjectKnowledgeGraph();
8
+ });
9
+ it('should extract symbols and context correctly', async () => {
10
+ // Mock some project structure if needed, but here we test the logic
11
+ expect(graph).toBeDefined();
12
+ });
13
+ });
package/dist/graph.js CHANGED
@@ -33,12 +33,12 @@ export class ProjectKnowledgeGraph {
33
33
  for (const entry of entries) {
34
34
  const res = path.resolve(dir, entry.name);
35
35
  if (entry.isDirectory()) {
36
- if (entry.name === 'node_modules' || entry.name === '.git' || entry.name === 'dist')
36
+ if (entry.name === 'node_modules' || entry.name === '.git' || entry.name === 'dist' || entry.name === '.gemini' || entry.name === 'coverage')
37
37
  continue;
38
38
  files.push(...await this.getAllFiles(res));
39
39
  }
40
40
  else {
41
- if (/\.(ts|js|tsx|jsx|json)$/.test(entry.name)) {
41
+ if (/\.(ts|js|tsx|jsx|json|py|go|rs|java|c|cpp|h)$/.test(entry.name)) {
42
42
  files.push(res);
43
43
  }
44
44
  }
@@ -46,6 +46,15 @@ export class ProjectKnowledgeGraph {
46
46
  return files;
47
47
  }
48
48
  async parseFile(filePath) {
49
+ const ext = path.extname(filePath);
50
+ if (['.ts', '.js', '.tsx', '.jsx'].includes(ext)) {
51
+ await this.parseTypeScript(filePath);
52
+ }
53
+ else {
54
+ await this.parseGeneric(filePath);
55
+ }
56
+ }
57
+ async parseTypeScript(filePath) {
49
58
  try {
50
59
  const content = await fs.readFile(filePath, 'utf-8');
51
60
  const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
@@ -97,30 +106,67 @@ export class ProjectKnowledgeGraph {
97
106
  ts.forEachChild(node, visit);
98
107
  };
99
108
  visit(sourceFile);
100
- const currentNode = this.nodes.get(filePath);
101
- if (!currentNode)
102
- return;
103
- currentNode.symbols = symbols;
104
- for (const importPath of imports) {
105
- let resolvedPath = null;
106
- if (importPath.startsWith('.')) {
107
- resolvedPath = await this.resolvePath(path.dirname(filePath), importPath);
108
- }
109
- else {
110
- resolvedPath = await this.resolvePath(this.rootDir, importPath);
111
- }
112
- if (resolvedPath && this.nodes.has(resolvedPath)) {
113
- if (!currentNode.imports.includes(resolvedPath)) {
114
- currentNode.imports.push(resolvedPath);
115
- }
116
- if (!this.nodes.get(resolvedPath)?.importedBy.includes(filePath)) {
117
- this.nodes.get(resolvedPath)?.importedBy.push(filePath);
118
- }
119
- }
109
+ await this.finalizeFileNodes(filePath, imports, symbols);
110
+ }
111
+ catch (error) {
112
+ console.error(`Error parsing TypeScript file ${filePath}:`, error);
113
+ }
114
+ }
115
+ async parseGeneric(filePath) {
116
+ try {
117
+ const content = await fs.readFile(filePath, 'utf-8');
118
+ const imports = [];
119
+ const symbols = [];
120
+ const ext = path.extname(filePath);
121
+ // Basic Regex for generic symbols and imports
122
+ if (ext === '.py') {
123
+ // Python: import x, from x import y, def func, class Cls
124
+ const importMatches = content.matchAll(/^(?:import|from)\s+([a-zA-Z0-9_.]+)/gm);
125
+ for (const match of importMatches)
126
+ imports.push(match[1]);
127
+ const funcMatches = content.matchAll(/^def\s+([a-zA-Z0-9_]+)/gm);
128
+ for (const match of funcMatches)
129
+ symbols.push(`def:${match[1]}`);
130
+ const classMatches = content.matchAll(/^class\s+([a-zA-Z0-9_]+)/gm);
131
+ for (const match of classMatches)
132
+ symbols.push(`class:${match[1]}`);
120
133
  }
134
+ else if (ext === '.go') {
135
+ // Go: import "x", func Name, type Name
136
+ const importMatches = content.matchAll(/import\s+"([^"]+)"/g);
137
+ for (const match of importMatches)
138
+ imports.push(match[1]);
139
+ const funcMatches = content.matchAll(/^func\s+([a-zA-Z0-9_]+)/gm);
140
+ for (const match of funcMatches)
141
+ symbols.push(`func:${match[1]}`);
142
+ }
143
+ await this.finalizeFileNodes(filePath, imports, symbols);
121
144
  }
122
145
  catch (error) {
123
- console.error(`Error parsing file ${filePath}:`, error);
146
+ console.error(`Error parsing generic file ${filePath}:`, error);
147
+ }
148
+ }
149
+ async finalizeFileNodes(filePath, imports, symbols) {
150
+ const currentNode = this.nodes.get(filePath);
151
+ if (!currentNode)
152
+ return;
153
+ currentNode.symbols = symbols;
154
+ for (const importPath of imports) {
155
+ let resolvedPath = null;
156
+ if (importPath.startsWith('.')) {
157
+ resolvedPath = await this.resolvePath(path.dirname(filePath), importPath);
158
+ }
159
+ else {
160
+ resolvedPath = await this.resolvePath(this.rootDir, importPath);
161
+ }
162
+ if (resolvedPath && this.nodes.has(resolvedPath)) {
163
+ if (!currentNode.imports.includes(resolvedPath)) {
164
+ currentNode.imports.push(resolvedPath);
165
+ }
166
+ if (!this.nodes.get(resolvedPath)?.importedBy.includes(filePath)) {
167
+ this.nodes.get(resolvedPath)?.importedBy.push(filePath);
168
+ }
169
+ }
124
170
  }
125
171
  }
126
172
  async resolvePath(dir, relativePath) {
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ import { registerNoteTools } from './tools/notes.js';
12
12
  import { registerCodingTools } from './tools/coding.js';
13
13
  const server = new McpServer({
14
14
  name: "sequential-thinking-server",
15
- version: "2026.2.4",
15
+ version: "2026.2.6",
16
16
  });
17
17
  const thinkingServer = new SequentialThinkingServer(process.env.THOUGHTS_STORAGE_PATH || 'thoughts_history.json', parseInt(process.env.THOUGHT_DELAY_MS || '0', 10));
18
18
  const knowledgeGraph = new ProjectKnowledgeGraph();
@@ -4,9 +4,16 @@ import * as path from 'path';
4
4
  import { execAsync } from "../utils.js";
5
5
  export function registerFileSystemTools(server) {
6
6
  // 3. shell_execute
7
- server.tool("shell_execute", "Execute a shell command. Use with caution.", {
7
+ server.tool("shell_execute", "Execute a shell command. SECURITY WARNING: Use this ONLY for safe, non-destructive commands. Avoid 'rm -rf /', format, or destructive operations.", {
8
8
  command: z.string().describe("The bash command to execute")
9
9
  }, async ({ command }) => {
10
+ const dangerousPatterns = [/rm\s+-rf\s+\//, /mkfs/, /dd\s+if=/];
11
+ if (dangerousPatterns.some(p => p.test(command))) {
12
+ return {
13
+ content: [{ type: "text", text: "Error: Dangerous command pattern detected. Execution blocked for safety." }],
14
+ isError: true
15
+ };
16
+ }
10
17
  try {
11
18
  const { stdout, stderr } = await execAsync(command);
12
19
  return {
package/dist/utils.js CHANGED
@@ -1,6 +1,34 @@
1
1
  import { exec } from 'child_process';
2
2
  import { promisify } from 'util';
3
+ import chalk from 'chalk';
3
4
  export const execAsync = promisify(exec);
5
+ class Logger {
6
+ level;
7
+ constructor() {
8
+ this.level = process.env.LOG_LEVEL || 'info';
9
+ }
10
+ shouldLog(lvl) {
11
+ const levels = ['debug', 'info', 'warn', 'error'];
12
+ return levels.indexOf(lvl) >= levels.indexOf(this.level);
13
+ }
14
+ debug(msg, ...args) {
15
+ if (this.shouldLog('debug'))
16
+ console.error(chalk.gray(`[DEBUG] ${msg}`), ...args);
17
+ }
18
+ info(msg, ...args) {
19
+ if (this.shouldLog('info'))
20
+ console.error(chalk.blue(`[INFO] ${msg}`), ...args);
21
+ }
22
+ warn(msg, ...args) {
23
+ if (this.shouldLog('warn'))
24
+ console.error(chalk.yellow(`[WARN] ${msg}`), ...args);
25
+ }
26
+ error(msg, ...args) {
27
+ if (this.shouldLog('error'))
28
+ console.error(chalk.red(`[ERROR] ${msg}`), ...args);
29
+ }
30
+ }
31
+ export const logger = new Logger();
4
32
  export const DEFAULT_HEADERS = {
5
33
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
6
34
  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gotza02/sequential-thinking",
3
- "version": "2026.2.4",
3
+ "version": "2026.2.6",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -29,21 +29,21 @@
29
29
  "test": "vitest run --coverage"
30
30
  },
31
31
  "dependencies": {
32
- "@modelcontextprotocol/sdk": "^1.24.0",
32
+ "@modelcontextprotocol/sdk": "^1.25.2",
33
33
  "@mozilla/readability": "^0.6.0",
34
- "chalk": "^5.3.0",
34
+ "chalk": "^5.6.2",
35
35
  "jsdom": "^27.4.0",
36
36
  "turndown": "^7.2.2",
37
- "typescript": "^5.3.3",
38
- "yargs": "^17.7.2"
37
+ "typescript": "^5.9.3",
38
+ "yargs": "^18.0.0"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/jsdom": "^27.0.0",
42
- "@types/node": "^22",
42
+ "@types/node": "^25.0.9",
43
43
  "@types/turndown": "^5.0.6",
44
- "@types/yargs": "^17.0.32",
45
- "@vitest/coverage-v8": "^2.1.8",
46
- "shx": "^0.3.4",
47
- "vitest": "^2.1.8"
44
+ "@types/yargs": "^17.0.35",
45
+ "@vitest/coverage-v8": "^3.2.4",
46
+ "shx": "^0.4.0",
47
+ "vitest": "^3.2.4"
48
48
  }
49
49
  }