@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.
- package/dist/coding.test.js +13 -0
- package/dist/graph.js +69 -23
- package/dist/index.js +1 -1
- package/dist/tools/filesystem.js +8 -1
- package/dist/utils.js +28 -0
- package/package.json +10 -10
|
@@ -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
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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.
|
|
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();
|
package/dist/tools/filesystem.js
CHANGED
|
@@ -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
|
|
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.
|
|
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.
|
|
32
|
+
"@modelcontextprotocol/sdk": "^1.25.2",
|
|
33
33
|
"@mozilla/readability": "^0.6.0",
|
|
34
|
-
"chalk": "^5.
|
|
34
|
+
"chalk": "^5.6.2",
|
|
35
35
|
"jsdom": "^27.4.0",
|
|
36
36
|
"turndown": "^7.2.2",
|
|
37
|
-
"typescript": "^5.
|
|
38
|
-
"yargs": "^
|
|
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": "^
|
|
42
|
+
"@types/node": "^25.0.9",
|
|
43
43
|
"@types/turndown": "^5.0.6",
|
|
44
|
-
"@types/yargs": "^17.0.
|
|
45
|
-
"@vitest/coverage-v8": "^2.
|
|
46
|
-
"shx": "^0.
|
|
47
|
-
"vitest": "^2.
|
|
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
|
}
|