@gotza02/sequential-thinking 2026.2.22 β 2026.2.24
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 +79 -144
- package/SYSTEM_INSTRUCTION.md +58 -0
- package/dist/graph.js +18 -2
- package/dist/index.js +15 -1
- package/dist/lib.js +16 -4
- package/dist/tools/codestore.js +50 -26
- package/dist/tools/human.js +151 -80
- package/dist/tools/notes.js +10 -5
- package/package.json +10 -3
- package/dist/test_ts_req.d.ts +0 -1
- package/dist/test_ts_req.js +0 -46
package/README.md
CHANGED
|
@@ -1,161 +1,96 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @gotza02/sequential-thinking MCP Server
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A comprehensive Model Context Protocol (MCP) server that empowers AI models with **Sequential Thinking**, **Web Research**, **Project Knowledge Graph**, and **Persistent Memory** capabilities.
|
|
4
4
|
|
|
5
|
-
##
|
|
6
|
-
- **Deep Thinking:** Step-by-step reasoning with auto-correction (Loop Breaker).
|
|
7
|
-
- **Code Intelligence:** Dependency graph mapping (`build_project_graph`) with **Incremental Caching** & surgical code editing.
|
|
8
|
-
- **Memory:** Long-term project notes, reusable code database, and thought history.
|
|
9
|
-
- **Research:** Integrated Web search (Brave/Exa) & webpage reading.
|
|
10
|
-
- **REST API:** Built-in HTTP server wrapper for easy integration with web tools and external services.
|
|
5
|
+
## Features
|
|
11
6
|
|
|
12
|
-
|
|
7
|
+
- **π§ Sequential Thinking:** Structured reasoning engine with block-based context management (Analysis -> Planning -> Execution -> Observation).
|
|
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.
|
|
11
|
+
- **πΎ Code Database:** Store and search reusable code snippets.
|
|
12
|
+
- **π οΈ File & Code Tools:** Safe file operations and code analysis utilities.
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
**Option A: Run Temporarily (Recommended for testing)**
|
|
16
|
-
```bash
|
|
17
|
-
npx -y @gotza02/sequential-thinking
|
|
18
|
-
```
|
|
14
|
+
## Usage
|
|
19
15
|
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
npm install -g @gotza02/sequential-thinking
|
|
23
|
-
```
|
|
16
|
+
### Method 1: Using `npx` (Recommended)
|
|
24
17
|
|
|
25
|
-
|
|
26
|
-
Add this to your MCP settings (`~/.gemini/settings.json` or `claude_desktop_config.json`).
|
|
18
|
+
Run the server directly without global installation. This is best for Claude Desktop or other MCP clients.
|
|
27
19
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"mcpServers": {
|
|
32
|
-
"smartagent": {
|
|
33
|
-
"command": "npx",
|
|
34
|
-
"args": ["-y", "@gotza02/sequential-thinking"],
|
|
35
|
-
"env": { "THOUGHTS_STORAGE_PATH": "thoughts.json" }
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
```
|
|
20
|
+
#### Configuration for Claude Desktop (`claude_desktop_config.json`)
|
|
21
|
+
|
|
22
|
+
To use the **Web Search** features, you must provide at least one API key.
|
|
40
23
|
|
|
41
|
-
**For npm usage:**
|
|
42
|
-
*(Find path with: `npm root -g`)*
|
|
43
24
|
```json
|
|
44
25
|
{
|
|
45
26
|
"mcpServers": {
|
|
46
|
-
"
|
|
47
|
-
"command": "
|
|
48
|
-
"args": [
|
|
27
|
+
"sequential-thinking": {
|
|
28
|
+
"command": "npx",
|
|
29
|
+
"args": [
|
|
30
|
+
"-y",
|
|
31
|
+
"@gotza02/sequential-thinking"
|
|
32
|
+
],
|
|
33
|
+
"env": {
|
|
34
|
+
"BRAVE_API_KEY": "your_brave_api_key_here",
|
|
35
|
+
"EXA_API_KEY": "your_exa_api_key_here",
|
|
36
|
+
"GOOGLE_SEARCH_API_KEY": "your_google_api_key",
|
|
37
|
+
"GOOGLE_SEARCH_CX": "your_google_cx_id"
|
|
38
|
+
}
|
|
49
39
|
}
|
|
50
40
|
}
|
|
51
41
|
}
|
|
52
42
|
```
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
```markdown
|
|
104
|
-
# π€ System Instruction: Ultimate Deep Engineer (Sequential Thinking Extended)
|
|
105
|
-
|
|
106
|
-
You are a Senior AI Software Engineer equipped with the Sequential Thinking MCP Server (Extended Edition). Your mission is to provide the highest quality technical solutions through rigorous logic, deep codebase awareness, and autonomous execution.
|
|
107
|
-
|
|
108
|
-
## π§ CORE MANDATE: Deepest Thinking Protocol
|
|
109
|
-
- **NEVER solve complex queries immediately.** You MUST use the `sequentialthinking` tool to structure your reasoning.
|
|
110
|
-
- **Atomic Analysis:** Use `thoughtType: 'analysis'` to break every request into atomic requirements and constraints before proposing solutions.
|
|
111
|
-
- **Mandatory Reflexion:** Use `thoughtType: 'reflexion'` frequently to critique your own logic, identify potential edge cases, and challenge your assumptions.
|
|
112
|
-
- **Tree of Thoughts:** For critical architectural decisions, use branching to explore multiple paths (Conservative vs. Aggressive) and evaluate them using `thoughtType: 'evaluation'`.
|
|
113
|
-
- **Loop Breaker (Auto-Correction):**
|
|
114
|
-
- **Self-Monitoring:** If you detect yourself repeating a failed strategy or stuck in a loop -> **STOP**.
|
|
115
|
-
- **Mandatory Branching:** You MUST create a new branch (`branchFromThought`) to explore a *radically different* approach.
|
|
116
|
-
- **Explicit Statement:** State "Stuck detected. Branching to Strategy B..." before proceeding.
|
|
117
|
-
- **Verified Completion:** Only set `nextThoughtNeeded: false` when the solution is definitive, verified, and follows project standards.
|
|
118
|
-
|
|
119
|
-
## π οΈ TOOL USAGE TRIGGERS (Context-Action Mapping)
|
|
120
|
-
**You MUST follow these explicit triggers:**
|
|
121
|
-
|
|
122
|
-
1. **Unknown/New Project Context:**
|
|
123
|
-
- **Trigger:** Start of session or new task.
|
|
124
|
-
- **Action:** `build_project_graph` -> `read_file` (README/config).
|
|
125
|
-
- **Goal:** Map the territory before moving.
|
|
126
|
-
|
|
127
|
-
2. **Coding/Refactoring Tasks:**
|
|
128
|
-
- **Trigger:** Request to write or edit code.
|
|
129
|
-
- **Action:** `deep_code_analyze` (on target files) -> `sequentialthinking` (Plan) -> `deep_code_edit` or `edit_file`.
|
|
130
|
-
- **Constraint:** NEVER edit code without reading the file and its related context first.
|
|
131
|
-
|
|
132
|
-
3. **Debugging/Error Fixing:**
|
|
133
|
-
- **Trigger:** User reports a bug or error.
|
|
134
|
-
- **Action:** `read_file` (logs/code) OR `diagnose_error_screenshot` -> `sequentialthinking` (Hypothesis) -> `codebase_investigator` (Verification).
|
|
135
|
-
- **Constraint:** Do not guess. Evidence first.
|
|
136
|
-
|
|
137
|
-
4. **Unknown Libraries/Docs:**
|
|
138
|
-
- **Trigger:** Need to use a specific library/tool you are unsure about.
|
|
139
|
-
- **Action:** `web_search` -> `read_webpage` or `get_code_context_exa`.
|
|
140
|
-
- **Constraint:** Do not hallucinate APIs.
|
|
141
|
-
|
|
142
|
-
## π» DEEP CODING WORKFLOW
|
|
143
|
-
1. **Discovery:** `build_project_graph` -> Identify entry points and core logic.
|
|
144
|
-
2. **Analysis:** `deep_code_analyze` -> Learn existing patterns, styles, and symbols.
|
|
145
|
-
3. **Planning:** `sequentialthinking` -> Draft a detailed implementation plan with reasoning.
|
|
146
|
-
4. **Execution:** `deep_code_edit` or `edit_file` -> Apply changes with precise reasoning.
|
|
147
|
-
5. **Verification:** `shell_execute` -> Run tests, build scripts, or linters to confirm correctness.
|
|
148
|
-
|
|
149
|
-
## π‘ SAFETY & PRECISION
|
|
150
|
-
- **Surgical Edits:** Prefer `edit_file` or `deep_code_edit` over `write_file` for existing files to minimize risk.
|
|
151
|
-
- **Shell Responsibility:** Explain the purpose of any modification command before running `shell_execute`.
|
|
152
|
-
- **No Assumptions:** If a library or configuration is unknown, use `web_search` or `read_webpage` to ingest documentation before implementation.
|
|
153
|
-
|
|
154
|
-
## π PERSISTENT MEMORY
|
|
155
|
-
- **Long-term Knowledge:** Use `manage_notes` to save architectural decisions, user preferences, project conventions, and "lessons learned" that must persist across sessions.
|
|
156
|
-
- **Code Database:** Use `add_code_snippet` to store reusable patterns and `search_code_db` to retrieve them.
|
|
157
|
-
- **Session Continuity:** Your thought history is saved. If you restart, review the history to maintain context.
|
|
158
|
-
```
|
|
43
|
+
*Note: You only need one of the search provider keys (Brave is recommended for general use).*
|
|
44
|
+
|
|
45
|
+
### Method 2: Running Locally
|
|
46
|
+
|
|
47
|
+
1. **Install dependencies:** `npm install`
|
|
48
|
+
2. **Build:** `npm run build`
|
|
49
|
+
3. **Config:** Point to the built `dist/index.js` file.
|
|
50
|
+
|
|
51
|
+
## π§° Complete Tool List
|
|
52
|
+
|
|
53
|
+
### π§ Core Thinking
|
|
54
|
+
* **`sequentialthinking`**: The main engine for problem-solving. Handles `analysis`, `planning`, `execution`, and `observation` steps.
|
|
55
|
+
* **`start_thinking_block`**: Start a new thinking context (e.g., switch from "Planning" to "Coding"). Helps prevent context pollution.
|
|
56
|
+
* **`get_thinking_blocks`**: View a summary of all discussion topics/blocks.
|
|
57
|
+
* **`summarize_history`**: Compress past thoughts to save token space.
|
|
58
|
+
* **`search_thoughts`**: Search through your thinking history.
|
|
59
|
+
* **`clear_thought_history`**: Reset the thinking state completely.
|
|
60
|
+
|
|
61
|
+
### π Web & Research (Requires API Keys)
|
|
62
|
+
* **`web_search`**: Search the internet.
|
|
63
|
+
* *Requires:* `BRAVE_API_KEY` OR `EXA_API_KEY` OR (`GOOGLE_SEARCH_API_KEY` + `GOOGLE_SEARCH_CX`).
|
|
64
|
+
* **`fetch`**: Fetch raw content from a URL (GET/POST).
|
|
65
|
+
* **`read_webpage`**: Download a webpage and convert it to clean Markdown (removes ads/clutter).
|
|
66
|
+
|
|
67
|
+
### πΈοΈ Project Knowledge Graph
|
|
68
|
+
* **`build_project_graph`**: Scans the current directory to map file dependencies.
|
|
69
|
+
* **`force_rebuild_graph`**: Clears cache and rebuilds the graph from scratch.
|
|
70
|
+
* **`get_file_relationships`**: Shows what a specific file imports and what imports it.
|
|
71
|
+
* **`get_project_graph_summary`**: High-level stats of the project structure.
|
|
72
|
+
* **`get_project_graph_visualization`**: Generates a Mermaid diagram of the dependency graph.
|
|
73
|
+
|
|
74
|
+
### π Notes & Memory
|
|
75
|
+
* **`manage_notes`**: Create, read, update, or delete persistent notes.
|
|
76
|
+
* **`list_notes`**: List all saved notes.
|
|
77
|
+
* **`add_code_snippet`**: Save a useful piece of code to the database.
|
|
78
|
+
* **`search_code_db`**: Find saved code snippets by description or tags.
|
|
79
|
+
|
|
80
|
+
### π» System & Coding
|
|
81
|
+
* (Include standard file system tools provided by the server context, typically `read_file`, `write_file`, etc., if exposed via this MCP, though often provided by the client itself. This server provides specialized graph/analysis tools.)
|
|
82
|
+
|
|
83
|
+
## Configuration Variables
|
|
84
|
+
|
|
85
|
+
| Variable | Description | Required For |
|
|
86
|
+
| :--- | :--- | :--- |
|
|
87
|
+
| `BRAVE_API_KEY` | Brave Search API Token | `web_search` (Provider: Brave) |
|
|
88
|
+
| `EXA_API_KEY` | Exa.ai API Key | `web_search` (Provider: Exa) |
|
|
89
|
+
| `GOOGLE_SEARCH_API_KEY` | Google Custom Search API Key | `web_search` (Provider: Google) |
|
|
90
|
+
| `GOOGLE_SEARCH_CX` | Google Custom Search Engine ID | `web_search` (Provider: Google) |
|
|
91
|
+
| `THOUGHTS_STORAGE_PATH` | Path to save thinking history (default: `thoughts_history.json`) | Persistence |
|
|
92
|
+
| `NOTES_STORAGE_PATH` | Path to save notes (default: `project_notes.json`) | Persistence |
|
|
159
93
|
|
|
160
94
|
## License
|
|
161
|
-
|
|
95
|
+
|
|
96
|
+
MIT
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# System Instruction for `@gotza02/sequential-thinking`
|
|
2
|
+
|
|
3
|
+
You are an advanced AI assistant augmented with a **Sequential Thinking Engine** and **Context-Aware Tools**. Your goal is to solve complex problems methodically, not just by guessing, but by rigorously planning, executing, and observing results.
|
|
4
|
+
|
|
5
|
+
## 1. THE CORE PROTOCOL: Sequential Thinking
|
|
6
|
+
For any non-trivial task (coding, debugging, research, complex analysis), you **MUST** use the `sequentialthinking` tool. Do not just output text; structure your thought process.
|
|
7
|
+
|
|
8
|
+
**The Loop:**
|
|
9
|
+
1. **Analysis:** Understand the request. Break it down.
|
|
10
|
+
2. **Planning:** Decide specifically which tools to call.
|
|
11
|
+
3. **Execution:** Declare your intent to call a tool.
|
|
12
|
+
4. **[TOOL CALL]**: The system executes the tool.
|
|
13
|
+
5. **Observation:** Analyze the tool's output. **CRITICAL:** You must explicitly record what you learned from the tool output before moving on.
|
|
14
|
+
|
|
15
|
+
**Parameters:**
|
|
16
|
+
* `thoughtType`: strict adherence to 'analysis', 'planning', 'execution', 'observation', 'solution'.
|
|
17
|
+
* `blockId`: Use a semantic ID (e.g., `debug-auth`, `research-mcp`) to group related thoughts. Change this ID when switching topics.
|
|
18
|
+
|
|
19
|
+
## 2. TOOL USAGE STRATEGIES
|
|
20
|
+
|
|
21
|
+
### A. Project Exploration (Codebase)
|
|
22
|
+
* **Trigger:** When asked to work on an existing project or understand code.
|
|
23
|
+
* **Action:**
|
|
24
|
+
1. Call `build_project_graph` immediately to map the territory.
|
|
25
|
+
2. Use `get_project_graph_summary` to identify key files.
|
|
26
|
+
3. Use `get_file_relationships` to understand dependencies before modifying any file.
|
|
27
|
+
4. **Never** edit code without understanding what depends on it.
|
|
28
|
+
|
|
29
|
+
### B. Web Research (External Knowledge)
|
|
30
|
+
* **Trigger:** When you lack specific knowledge, need documentation, or current events.
|
|
31
|
+
* **Action:**
|
|
32
|
+
1. Call `web_search` (Provider is auto-handled, but prefer Brave/Exa if detailed).
|
|
33
|
+
2. **Do not** rely on snippets alone. If a result looks promising, use `read_webpage` to ingest the full content into your context.
|
|
34
|
+
3. Synthesize the information in an `observation` thought.
|
|
35
|
+
|
|
36
|
+
### C. Long-term Memory
|
|
37
|
+
* **Trigger:** When the user gives you constraints, preferences, or architectural decisions that matter for the future.
|
|
38
|
+
* **Action:** Call `manage_notes` (action: 'create' or 'update') to save this information. Check these notes (`list_notes`) at the start of new sessions.
|
|
39
|
+
|
|
40
|
+
## 3. AUTOMATION RULES
|
|
41
|
+
|
|
42
|
+
1. **Stuck? Branch Out:** If you find yourself looping or failing 3 times, use `sequentialthinking` with `thoughtType: 'reflexion'` to critique your approach, then start a NEW `blockId` with a fresh strategy.
|
|
43
|
+
2. **Verify Before Solution:** Never declare a `solution` until you have verified it (e.g., by running a test, checking the file content, or validating the syntax).
|
|
44
|
+
3. **One Step at a Time:** Do not chain 10 tool calls in a row without thinking. The correct rhythm is: *Think -> Tool -> Observe -> Think*.
|
|
45
|
+
|
|
46
|
+
## 4. EXAMPLE WORKFLOW
|
|
47
|
+
|
|
48
|
+
**User:** "Fix the bug in the login page."
|
|
49
|
+
|
|
50
|
+
**Model:**
|
|
51
|
+
1. `sequentialthinking(type='analysis', thought='I need to find the login page code.')`
|
|
52
|
+
2. `sequentialthinking(type='planning', thought='I will search for files named login.')`
|
|
53
|
+
3. `sequentialthinking(type='execution', relatedToolCall='glob')`
|
|
54
|
+
4. `glob(pattern='*login*')`
|
|
55
|
+
5. `sequentialthinking(type='observation', toolResult='Found src/auth/login.ts')`
|
|
56
|
+
6. `sequentialthinking(type='analysis', thought='Now I need to see who calls this file.')`
|
|
57
|
+
7. `get_file_relationships(filePath='src/auth/login.ts')`
|
|
58
|
+
8. ... (continues until fixed)
|
package/dist/graph.js
CHANGED
|
@@ -252,8 +252,24 @@ export class ProjectKnowledgeGraph {
|
|
|
252
252
|
}
|
|
253
253
|
// Handle: from .module import func OR from package.module import func
|
|
254
254
|
const fromImportMatches = content.matchAll(/^\s*from\s+([.a-zA-Z0-9_]+)\s+import/gm);
|
|
255
|
-
for (const match of fromImportMatches)
|
|
256
|
-
|
|
255
|
+
for (const match of fromImportMatches) {
|
|
256
|
+
let imp = match[1];
|
|
257
|
+
// Convert Python relative import to path (e.g. .module -> ./module)
|
|
258
|
+
if (imp.startsWith('.')) {
|
|
259
|
+
const matchDots = imp.match(/^(\.+)(.*)/);
|
|
260
|
+
if (matchDots) {
|
|
261
|
+
const dots = matchDots[1].length;
|
|
262
|
+
const name = matchDots[2];
|
|
263
|
+
if (dots === 1) {
|
|
264
|
+
imp = `./${name}`;
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
imp = `${'../'.repeat(dots - 1)}${name}`;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
imports.push(imp);
|
|
272
|
+
}
|
|
257
273
|
// 2. Python Symbols (Only top-level defs/classes to avoid nested methods)
|
|
258
274
|
const topLevelFuncMatches = content.matchAll(/^def\s+([a-zA-Z0-9_]+)/gm);
|
|
259
275
|
for (const match of topLevelFuncMatches)
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from 'fs';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { dirname, join } from 'path';
|
|
2
5
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
6
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
7
|
import { SequentialThinkingServer } from './lib.js';
|
|
@@ -13,9 +16,12 @@ import { registerNoteTools } from './tools/notes.js';
|
|
|
13
16
|
import { registerCodingTools } from './tools/coding.js';
|
|
14
17
|
import { registerCodeDbTools } from './tools/codestore.js';
|
|
15
18
|
import { registerHumanTools } from './tools/human.js';
|
|
19
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
20
|
+
const __dirname = dirname(__filename);
|
|
21
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
|
|
16
22
|
const server = new McpServer({
|
|
17
23
|
name: "sequential-thinking-server",
|
|
18
|
-
version:
|
|
24
|
+
version: pkg.version,
|
|
19
25
|
});
|
|
20
26
|
const thinkingServer = new SequentialThinkingServer(process.env.THOUGHTS_STORAGE_PATH || 'thoughts_history.json', parseInt(process.env.THOUGHT_DELAY_MS || '0', 10));
|
|
21
27
|
const knowledgeGraph = new ProjectKnowledgeGraph();
|
|
@@ -39,3 +45,11 @@ runServer().catch((error) => {
|
|
|
39
45
|
console.error("Fatal error running server:", error);
|
|
40
46
|
process.exit(1);
|
|
41
47
|
});
|
|
48
|
+
process.on('SIGINT', () => {
|
|
49
|
+
console.error("\nReceived SIGINT, shutting down...");
|
|
50
|
+
process.exit(0);
|
|
51
|
+
});
|
|
52
|
+
process.on('SIGTERM', () => {
|
|
53
|
+
console.error("\nReceived SIGTERM, shutting down...");
|
|
54
|
+
process.exit(0);
|
|
55
|
+
});
|
package/dist/lib.js
CHANGED
|
@@ -81,16 +81,22 @@ export class SequentialThinkingServer {
|
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
rebuildBlocks() {
|
|
84
|
+
const oldBlocksMap = new Map();
|
|
85
|
+
for (const b of this.blocks) {
|
|
86
|
+
oldBlocksMap.set(b.id, b);
|
|
87
|
+
}
|
|
88
|
+
this.blocks = [];
|
|
84
89
|
const blockMap = new Map();
|
|
85
90
|
for (const t of this.thoughtHistory) {
|
|
86
91
|
const bid = t.blockId || 'default';
|
|
87
92
|
if (!blockMap.has(bid)) {
|
|
93
|
+
const oldBlock = oldBlocksMap.get(bid);
|
|
88
94
|
const newBlock = {
|
|
89
95
|
id: bid,
|
|
90
|
-
topic: t.thought.substring(0, 50),
|
|
91
|
-
status: 'active',
|
|
96
|
+
topic: oldBlock ? oldBlock.topic : t.thought.substring(0, 50),
|
|
97
|
+
status: oldBlock ? oldBlock.status : 'active',
|
|
92
98
|
thoughts: [],
|
|
93
|
-
createdAt: new Date().toISOString(),
|
|
99
|
+
createdAt: oldBlock ? oldBlock.createdAt : new Date().toISOString(),
|
|
94
100
|
updatedAt: new Date().toISOString()
|
|
95
101
|
};
|
|
96
102
|
blockMap.set(bid, newBlock);
|
|
@@ -99,7 +105,13 @@ export class SequentialThinkingServer {
|
|
|
99
105
|
blockMap.get(bid).thoughts.push(t);
|
|
100
106
|
}
|
|
101
107
|
if (this.blocks.length > 0) {
|
|
102
|
-
|
|
108
|
+
// Ensure currentBlockId points to a valid block or the last one
|
|
109
|
+
if (!this.blocks.find(b => b.id === this.currentBlockId)) {
|
|
110
|
+
this.currentBlockId = this.blocks[this.blocks.length - 1].id;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
this.currentBlockId = null;
|
|
103
115
|
}
|
|
104
116
|
}
|
|
105
117
|
rebuildBranches() {
|
package/dist/tools/codestore.js
CHANGED
|
@@ -8,44 +8,68 @@ export function registerCodeDbTools(server, db) {
|
|
|
8
8
|
description: z.string().describe("What this code does and why it is useful"),
|
|
9
9
|
tags: z.array(z.string()).optional().default([]).describe("Tags for categorization")
|
|
10
10
|
}, async (args) => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
try {
|
|
12
|
+
const snippet = await db.addSnippet(args);
|
|
13
|
+
return {
|
|
14
|
+
content: [{ type: "text", text: `Snippet saved with ID: ${snippet.id}` }]
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
return {
|
|
19
|
+
content: [{ type: "text", text: `Error adding snippet: ${error instanceof Error ? error.message : String(error)}` }],
|
|
20
|
+
isError: true
|
|
21
|
+
};
|
|
22
|
+
}
|
|
15
23
|
});
|
|
16
24
|
// 17. search_code_db
|
|
17
25
|
server.tool("search_code_db", "Search the Code Database for existing snippets, patterns, or architectural knowledge.", {
|
|
18
26
|
query: z.string().describe("Search query")
|
|
19
27
|
}, async ({ query }) => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
try {
|
|
29
|
+
const results = await db.searchSnippets(query);
|
|
30
|
+
const patterns = await db.listAllPatterns();
|
|
31
|
+
let output = `--- CODE DATABASE RESULTS ---\n\n`;
|
|
32
|
+
if (results.length > 0) {
|
|
33
|
+
output += `SNIPPETS FOUND:\n`;
|
|
34
|
+
results.forEach(s => {
|
|
35
|
+
output += `ID: ${s.id} | ${s.title} (${s.language})\nDesc: ${s.description}\nCode:\n\`\`\`\n${s.code}\n\`\`\`\n\n`;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
const matchedPatterns = Object.entries(patterns).filter(([k, v]) => k.toLowerCase().includes(query.toLowerCase()) || v.toLowerCase().includes(query.toLowerCase()));
|
|
39
|
+
if (matchedPatterns.length > 0) {
|
|
40
|
+
output += `PATTERNS FOUND:\n`;
|
|
41
|
+
matchedPatterns.forEach(([name, desc]) => {
|
|
42
|
+
output += `- ${name}: ${desc}\n`;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
if (results.length === 0 && matchedPatterns.length === 0) {
|
|
46
|
+
output += "No results found in the Code Database.";
|
|
47
|
+
}
|
|
48
|
+
return { content: [{ type: "text", text: output }] };
|
|
35
49
|
}
|
|
36
|
-
|
|
37
|
-
|
|
50
|
+
catch (error) {
|
|
51
|
+
return {
|
|
52
|
+
content: [{ type: "text", text: `Error searching code DB: ${error instanceof Error ? error.message : String(error)}` }],
|
|
53
|
+
isError: true
|
|
54
|
+
};
|
|
38
55
|
}
|
|
39
|
-
return { content: [{ type: "text", text: output }] };
|
|
40
56
|
});
|
|
41
57
|
// 18. learn_architecture_pattern
|
|
42
58
|
server.tool("learn_architecture_pattern", "Store a high-level architectural or logic pattern in the Code DB (e.g., 'auth-flow', 'error-handling-strategy').", {
|
|
43
59
|
name: z.string().describe("Name of the pattern"),
|
|
44
60
|
description: z.string().describe("Detailed description of the pattern and how it applies to this project")
|
|
45
61
|
}, async ({ name, description }) => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
62
|
+
try {
|
|
63
|
+
await db.learnPattern(name, description);
|
|
64
|
+
return {
|
|
65
|
+
content: [{ type: "text", text: `Pattern '${name}' learned and stored.` }]
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
return {
|
|
70
|
+
content: [{ type: "text", text: `Error learning pattern: ${error instanceof Error ? error.message : String(error)}` }],
|
|
71
|
+
isError: true
|
|
72
|
+
};
|
|
73
|
+
}
|
|
50
74
|
});
|
|
51
75
|
}
|
package/dist/tools/human.js
CHANGED
|
@@ -30,6 +30,34 @@ export class HumanInteractionManager {
|
|
|
30
30
|
status: 'pending'
|
|
31
31
|
};
|
|
32
32
|
this.interactions.set(id, interaction);
|
|
33
|
+
// Handle timeout if specified
|
|
34
|
+
if (params.timeoutMs && params.timeoutMs > 0) {
|
|
35
|
+
setTimeout(() => {
|
|
36
|
+
const current = this.interactions.get(id);
|
|
37
|
+
if (current && current.status === 'pending') {
|
|
38
|
+
if (current.defaultOption) {
|
|
39
|
+
current.status = 'answered';
|
|
40
|
+
current.response = current.defaultOption;
|
|
41
|
+
current.respondedAt = new Date().toISOString();
|
|
42
|
+
// Also resolve pending callbacks if any (future proofing)
|
|
43
|
+
const callback = this.pendingCallbacks.get(id);
|
|
44
|
+
if (callback) {
|
|
45
|
+
callback.resolve(current.response);
|
|
46
|
+
this.pendingCallbacks.delete(id);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
current.status = 'timeout';
|
|
51
|
+
// Resolve pending callback with null or specific timeout error if supported
|
|
52
|
+
const callback = this.pendingCallbacks.get(id);
|
|
53
|
+
if (callback) {
|
|
54
|
+
callback.resolve(null); // Null indicates timeout/no answer
|
|
55
|
+
this.pendingCallbacks.delete(id);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}, params.timeoutMs);
|
|
60
|
+
}
|
|
33
61
|
return interaction;
|
|
34
62
|
}
|
|
35
63
|
/**
|
|
@@ -173,133 +201,176 @@ Urgency Levels:
|
|
|
173
201
|
options: z.array(z.string()).optional()
|
|
174
202
|
.describe("Available options for 'choice' type questions"),
|
|
175
203
|
defaultOption: z.string().optional()
|
|
176
|
-
.describe("Default option if human doesn't respond (for non-critical)")
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
204
|
+
.describe("Default option if human doesn't respond (for non-critical)"),
|
|
205
|
+
timeoutMs: z.number().int().min(1000).optional()
|
|
206
|
+
.describe("Timeout in milliseconds (default: no timeout)")
|
|
207
|
+
}, async ({ question, questionType, urgency, context, options, defaultOption, timeoutMs }) => {
|
|
208
|
+
try {
|
|
209
|
+
// Validate options for choice type
|
|
210
|
+
if (questionType === 'choice' && (!options || options.length < 2)) {
|
|
211
|
+
return {
|
|
212
|
+
content: [{
|
|
213
|
+
type: "text",
|
|
214
|
+
text: "Error: 'choice' question type requires at least 2 options"
|
|
215
|
+
}],
|
|
216
|
+
isError: true
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
const interaction = await manager.createInteraction({
|
|
220
|
+
questionType,
|
|
221
|
+
urgency,
|
|
222
|
+
question,
|
|
223
|
+
context,
|
|
224
|
+
options,
|
|
225
|
+
defaultOption,
|
|
226
|
+
timeoutMs
|
|
227
|
+
});
|
|
228
|
+
const formatted = manager.formatInteraction(interaction);
|
|
180
229
|
return {
|
|
181
230
|
content: [{
|
|
182
231
|
type: "text",
|
|
183
|
-
text:
|
|
184
|
-
}]
|
|
232
|
+
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'.`
|
|
233
|
+
}]
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
return {
|
|
238
|
+
content: [{ type: "text", text: `Error asking human: ${error instanceof Error ? error.message : String(error)}` }],
|
|
185
239
|
isError: true
|
|
186
240
|
};
|
|
187
241
|
}
|
|
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
242
|
});
|
|
204
243
|
// --- respond_to_human Tool ---
|
|
205
244
|
server.tool("respond_to_human", "Provide a response to a pending human-in-the-loop question. Use this after receiving human input.", {
|
|
206
245
|
interactionId: z.string().describe("The interaction ID from ask_human"),
|
|
207
246
|
response: z.string().describe("The human's response to the question")
|
|
208
247
|
}, async ({ interactionId, response }) => {
|
|
209
|
-
|
|
210
|
-
|
|
248
|
+
try {
|
|
249
|
+
const interaction = manager.recordResponse(interactionId, response);
|
|
250
|
+
if (!interaction) {
|
|
251
|
+
return {
|
|
252
|
+
content: [{
|
|
253
|
+
type: "text",
|
|
254
|
+
text: `Error: No pending interaction found with ID "${interactionId}"`
|
|
255
|
+
}],
|
|
256
|
+
isError: true
|
|
257
|
+
};
|
|
258
|
+
}
|
|
211
259
|
return {
|
|
212
260
|
content: [{
|
|
213
261
|
type: "text",
|
|
214
|
-
text:
|
|
215
|
-
|
|
262
|
+
text: `β
Response recorded for interaction ${interactionId}\n\n` +
|
|
263
|
+
`Question: ${interaction.question}\n` +
|
|
264
|
+
`Response: ${response}\n` +
|
|
265
|
+
`Responded at: ${interaction.respondedAt}\n\n` +
|
|
266
|
+
`The AI can now proceed based on this human decision.`
|
|
267
|
+
}]
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
return {
|
|
272
|
+
content: [{ type: "text", text: `Error responding to human: ${error instanceof Error ? error.message : String(error)}` }],
|
|
216
273
|
isError: true
|
|
217
274
|
};
|
|
218
275
|
}
|
|
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
276
|
});
|
|
230
277
|
// --- get_pending_questions Tool ---
|
|
231
278
|
server.tool("get_pending_questions", "Get all pending human-in-the-loop questions that need responses.", {}, async () => {
|
|
232
|
-
|
|
233
|
-
|
|
279
|
+
try {
|
|
280
|
+
const pending = manager.getPendingInteractions();
|
|
281
|
+
if (pending.length === 0) {
|
|
282
|
+
return {
|
|
283
|
+
content: [{
|
|
284
|
+
type: "text",
|
|
285
|
+
text: "β
No pending questions. All human interactions have been addressed."
|
|
286
|
+
}]
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
let output = `π PENDING HUMAN INTERACTIONS (${pending.length})\n`;
|
|
290
|
+
output += `${'β'.repeat(60)}\n\n`;
|
|
291
|
+
for (const interaction of pending) {
|
|
292
|
+
output += manager.formatInteraction(interaction);
|
|
293
|
+
output += '\n';
|
|
294
|
+
}
|
|
234
295
|
return {
|
|
235
296
|
content: [{
|
|
236
297
|
type: "text",
|
|
237
|
-
text:
|
|
298
|
+
text: output
|
|
238
299
|
}]
|
|
239
300
|
};
|
|
240
301
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
302
|
+
catch (error) {
|
|
303
|
+
return {
|
|
304
|
+
content: [{ type: "text", text: `Error getting pending questions: ${error instanceof Error ? error.message : String(error)}` }],
|
|
305
|
+
isError: true
|
|
306
|
+
};
|
|
246
307
|
}
|
|
247
|
-
return {
|
|
248
|
-
content: [{
|
|
249
|
-
type: "text",
|
|
250
|
-
text: output
|
|
251
|
-
}]
|
|
252
|
-
};
|
|
253
308
|
});
|
|
254
309
|
// --- get_interaction_history Tool ---
|
|
255
310
|
server.tool("get_interaction_history", "Get the history of human-AI interactions for context and learning.", {
|
|
256
311
|
limit: z.number().int().min(1).max(100).default(20)
|
|
257
312
|
.describe("Maximum number of interactions to return")
|
|
258
313
|
}, async ({ limit }) => {
|
|
259
|
-
|
|
260
|
-
|
|
314
|
+
try {
|
|
315
|
+
const history = manager.getHistory(limit);
|
|
316
|
+
if (history.length === 0) {
|
|
317
|
+
return {
|
|
318
|
+
content: [{
|
|
319
|
+
type: "text",
|
|
320
|
+
text: "No interaction history found."
|
|
321
|
+
}]
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
let output = `π INTERACTION HISTORY (${history.length} most recent)\n`;
|
|
325
|
+
output += `${'β'.repeat(60)}\n\n`;
|
|
326
|
+
for (const interaction of history) {
|
|
327
|
+
const statusEmoji = {
|
|
328
|
+
pending: 'β³',
|
|
329
|
+
answered: 'β
',
|
|
330
|
+
timeout: 'β±οΈ',
|
|
331
|
+
skipped: 'βοΈ'
|
|
332
|
+
};
|
|
333
|
+
output += `${statusEmoji[interaction.status]} [${interaction.id}]\n`;
|
|
334
|
+
output += ` Type: ${interaction.questionType} | Urgency: ${interaction.urgency}\n`;
|
|
335
|
+
output += ` Q: ${interaction.question.substring(0, 80)}${interaction.question.length > 80 ? '...' : ''}\n`;
|
|
336
|
+
if (interaction.response) {
|
|
337
|
+
output += ` A: ${interaction.response.substring(0, 80)}${interaction.response.length > 80 ? '...' : ''}\n`;
|
|
338
|
+
}
|
|
339
|
+
output += ` Time: ${interaction.timestamp}\n\n`;
|
|
340
|
+
}
|
|
261
341
|
return {
|
|
262
342
|
content: [{
|
|
263
343
|
type: "text",
|
|
264
|
-
text:
|
|
344
|
+
text: output
|
|
265
345
|
}]
|
|
266
346
|
};
|
|
267
347
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
pending: 'β³',
|
|
273
|
-
answered: 'β
',
|
|
274
|
-
timeout: 'β±οΈ',
|
|
275
|
-
skipped: 'βοΈ'
|
|
348
|
+
catch (error) {
|
|
349
|
+
return {
|
|
350
|
+
content: [{ type: "text", text: `Error getting history: ${error instanceof Error ? error.message : String(error)}` }],
|
|
351
|
+
isError: true
|
|
276
352
|
};
|
|
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
353
|
}
|
|
285
|
-
return {
|
|
286
|
-
content: [{
|
|
287
|
-
type: "text",
|
|
288
|
-
text: output
|
|
289
|
-
}]
|
|
290
|
-
};
|
|
291
354
|
});
|
|
292
355
|
// --- clear_old_interactions Tool ---
|
|
293
356
|
server.tool("clear_old_interactions", "Clear old interaction history to free up memory.", {
|
|
294
357
|
hoursOld: z.number().int().min(1).default(24)
|
|
295
358
|
.describe("Clear interactions older than this many hours")
|
|
296
359
|
}, async ({ hoursOld }) => {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
360
|
+
try {
|
|
361
|
+
const cleared = manager.clearOldInteractions(hoursOld);
|
|
362
|
+
return {
|
|
363
|
+
content: [{
|
|
364
|
+
type: "text",
|
|
365
|
+
text: `ποΈ Cleared ${cleared} interactions older than ${hoursOld} hours.`
|
|
366
|
+
}]
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
catch (error) {
|
|
370
|
+
return {
|
|
371
|
+
content: [{ type: "text", text: `Error clearing interactions: ${error instanceof Error ? error.message : String(error)}` }],
|
|
372
|
+
isError: true
|
|
373
|
+
};
|
|
374
|
+
}
|
|
304
375
|
});
|
|
305
376
|
}
|
package/dist/tools/notes.js
CHANGED
|
@@ -14,22 +14,25 @@ export function registerNoteTools(server, notesManager) {
|
|
|
14
14
|
}, async ({ action, title, content, tags, searchQuery, noteId, priority, expiresAt, includeExpired }) => {
|
|
15
15
|
try {
|
|
16
16
|
switch (action) {
|
|
17
|
-
case 'add':
|
|
17
|
+
case 'add': {
|
|
18
18
|
if (!title || !content) {
|
|
19
19
|
return { content: [{ type: "text", text: "Error: 'title' and 'content' are required for add action." }], isError: true };
|
|
20
20
|
}
|
|
21
21
|
const newNote = await notesManager.addNote(title, content, tags, priority, expiresAt);
|
|
22
22
|
return { content: [{ type: "text", text: `Note added successfully.\nID: ${newNote.id} (Priority: ${newNote.priority})` }] };
|
|
23
|
-
|
|
23
|
+
}
|
|
24
|
+
case 'list': {
|
|
24
25
|
const notes = await notesManager.listNotes(undefined, includeExpired);
|
|
25
26
|
return { content: [{ type: "text", text: JSON.stringify(notes, null, 2) }] };
|
|
26
|
-
|
|
27
|
+
}
|
|
28
|
+
case 'search': {
|
|
27
29
|
if (!searchQuery) {
|
|
28
30
|
return { content: [{ type: "text", text: "Error: 'searchQuery' is required for search action." }], isError: true };
|
|
29
31
|
}
|
|
30
32
|
const searchResults = await notesManager.searchNotes(searchQuery);
|
|
31
33
|
return { content: [{ type: "text", text: searchResults.length > 0 ? JSON.stringify(searchResults, null, 2) : "No matching notes found." }] };
|
|
32
|
-
|
|
34
|
+
}
|
|
35
|
+
case 'update': {
|
|
33
36
|
if (!noteId) {
|
|
34
37
|
return { content: [{ type: "text", text: "Error: 'noteId' is required for update action." }], isError: true };
|
|
35
38
|
}
|
|
@@ -38,12 +41,14 @@ export function registerNoteTools(server, notesManager) {
|
|
|
38
41
|
return { content: [{ type: "text", text: `Error: Note with ID ${noteId} not found.` }], isError: true };
|
|
39
42
|
}
|
|
40
43
|
return { content: [{ type: "text", text: `Note updated successfully.` }] };
|
|
41
|
-
|
|
44
|
+
}
|
|
45
|
+
case 'delete': {
|
|
42
46
|
if (!noteId) {
|
|
43
47
|
return { content: [{ type: "text", text: "Error: 'noteId' is required for delete action." }], isError: true };
|
|
44
48
|
}
|
|
45
49
|
const deleted = await notesManager.deleteNote(noteId);
|
|
46
50
|
return { content: [{ type: "text", text: deleted ? "Note deleted successfully." : `Error: Note with ID ${noteId} not found.` }], isError: !deleted };
|
|
51
|
+
}
|
|
47
52
|
default:
|
|
48
53
|
return { content: [{ type: "text", text: `Error: Unknown action '${action}'` }], isError: true };
|
|
49
54
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gotza02/sequential-thinking",
|
|
3
|
-
"version": "2026.2.
|
|
3
|
+
"version": "2026.2.24",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"mcp-server-sequential-thinking": "dist/index.js"
|
|
22
22
|
},
|
|
23
23
|
"files": [
|
|
24
|
-
"dist"
|
|
24
|
+
"dist",
|
|
25
|
+
"SYSTEM_INSTRUCTION.md"
|
|
25
26
|
],
|
|
26
27
|
"scripts": {
|
|
27
28
|
"build": "tsc",
|
|
@@ -29,7 +30,9 @@
|
|
|
29
30
|
"start:http": "node dist/http-server.js",
|
|
30
31
|
"prepare": "npm run build",
|
|
31
32
|
"watch": "tsc --watch",
|
|
32
|
-
"test": "vitest run --coverage"
|
|
33
|
+
"test": "vitest run --coverage",
|
|
34
|
+
"lint": "eslint src/**/*.ts",
|
|
35
|
+
"format": "prettier --write \"src/**/*.{ts,json}\""
|
|
33
36
|
},
|
|
34
37
|
"dependencies": {
|
|
35
38
|
"@modelcontextprotocol/sdk": "^1.25.2",
|
|
@@ -50,6 +53,10 @@
|
|
|
50
53
|
"@types/turndown": "^5.0.6",
|
|
51
54
|
"@types/yargs": "^17.0.35",
|
|
52
55
|
"@vitest/coverage-v8": "^3.2.4",
|
|
56
|
+
"eslint": "^8.57.0",
|
|
57
|
+
"@typescript-eslint/parser": "^7.1.1",
|
|
58
|
+
"@typescript-eslint/eslint-plugin": "^7.1.1",
|
|
59
|
+
"prettier": "^3.2.5",
|
|
53
60
|
"shx": "^0.4.0",
|
|
54
61
|
"vitest": "^3.2.4"
|
|
55
62
|
}
|
package/dist/test_ts_req.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/test_ts_req.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { ProjectKnowledgeGraph } from './graph.js';
|
|
2
|
-
import * as fs from 'fs/promises';
|
|
3
|
-
async function test() {
|
|
4
|
-
const tempFile = 'temp_req.ts';
|
|
5
|
-
await fs.writeFile(tempFile, 'import fs = require("fs");\nexport = fs;');
|
|
6
|
-
try {
|
|
7
|
-
const graph = new ProjectKnowledgeGraph();
|
|
8
|
-
await graph.build(process.cwd());
|
|
9
|
-
const rel = graph.getRelationships(tempFile);
|
|
10
|
-
console.log("Imports:", rel?.imports);
|
|
11
|
-
// Note: 'fs' is a built-in, so it might not be in 'imports' array unless resolved to a file.
|
|
12
|
-
// But ProjectKnowledgeGraph parser ADDS it to 'imports' list initially.
|
|
13
|
-
// finalizeFileNodes only keeps it if it resolves to a node OR if we assume internal logic keeps it?
|
|
14
|
-
// Wait, 'finalizeFileNodes' logic:
|
|
15
|
-
// for (const importPath of imports) {
|
|
16
|
-
// resolved = resolvePath(...)
|
|
17
|
-
// if (resolved && nodes.has(resolved)) { imports.push(resolved) }
|
|
18
|
-
// }
|
|
19
|
-
// It FILTERS out imports that don't resolve to files in the project!
|
|
20
|
-
// So 'fs' will be DROPPED.
|
|
21
|
-
// This makes verifying the PARSER hard via 'getRelationships'.
|
|
22
|
-
// However, 'symbols' are kept.
|
|
23
|
-
// 'import fs = require...' creates a symbol 'fs'?
|
|
24
|
-
// The parser only pushes to 'imports' or 'symbols'.
|
|
25
|
-
// Let's create a local file 'my_dep.ts' and import THAT.
|
|
26
|
-
await fs.writeFile('my_dep.ts', 'export const x = 1;');
|
|
27
|
-
await fs.writeFile(tempFile, 'import dep = require("./my_dep");');
|
|
28
|
-
await graph.build(process.cwd());
|
|
29
|
-
const rel2 = graph.getRelationships(tempFile);
|
|
30
|
-
console.log("Imports 2:", rel2?.imports);
|
|
31
|
-
if (rel2?.imports.some(i => i.includes('my_dep'))) {
|
|
32
|
-
console.log("PASS: Found 'my_dep' import");
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
console.log("FAIL: 'my_dep' import missing");
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
finally {
|
|
39
|
-
await fs.unlink(tempFile);
|
|
40
|
-
try {
|
|
41
|
-
await fs.unlink('my_dep.ts');
|
|
42
|
-
}
|
|
43
|
-
catch { }
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
test();
|