@lyy0709/contextweaver 1.0.0

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,263 @@
1
+ import {
2
+ codebaseRetrievalSchema,
3
+ handleCodebaseRetrieval
4
+ } from "./chunk-XVKMTPCT.js";
5
+ import "./chunk-LPFRFKFW.js";
6
+ import {
7
+ logger
8
+ } from "./chunk-YVLGQTLG.js";
9
+ import "./chunk-V2USKRIC.js";
10
+
11
+ // src/mcp/server.ts
12
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
13
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
14
+ import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
15
+
16
+ // src/mcp/tools/enhancePrompt.ts
17
+ import { z } from "zod";
18
+ var enhancePromptSchema = z.object({
19
+ prompt: z.string().describe("The original prompt to enhance"),
20
+ conversation_history: z.string().optional().describe(
21
+ "Recent conversation history for context. Format: 'User: ...\\nAssistant: ...'"
22
+ ),
23
+ project_root_path: z.string().optional().describe("Project root path for context")
24
+ });
25
+ function formatEnvMissingResponse(missingVars) {
26
+ const configPath = "~/.contextweaver/.env";
27
+ const text = `## \u26A0\uFE0F \u914D\u7F6E\u7F3A\u5931
28
+
29
+ ContextWeaver \u7684 Prompt Enhancer \u9700\u8981\u914D\u7F6E\u5916\u90E8 LLM API\u3002
30
+
31
+ ### \u7F3A\u5931\u7684\u73AF\u5883\u53D8\u91CF
32
+ ${missingVars.map((v) => `- \`${v}\``).join("\n")}
33
+
34
+ ### \u914D\u7F6E\u6B65\u9AA4
35
+
36
+ \u8BF7\u7F16\u8F91\u914D\u7F6E\u6587\u4EF6\uFF1A\`${configPath}\`\uFF0C\u6DFB\u52A0\u6216\u53D6\u6D88\u6CE8\u91CA\u4EE5\u4E0B\u914D\u7F6E\uFF1A
37
+
38
+ \`\`\`bash
39
+ # Prompt Enhancer \u914D\u7F6E\uFF08\u4F7F\u7528 enhance-prompt \u5DE5\u5177\u65F6\u9700\u8981\uFF09
40
+ # PROMPT_ENHANCER_ENDPOINT=openai
41
+ # PROMPT_ENHANCER_BASE_URL=
42
+ PROMPT_ENHANCER_TOKEN=your-api-key-here
43
+ # PROMPT_ENHANCER_MODEL=
44
+ # PROMPT_ENHANCER_TEMPLATE=
45
+ \`\`\`
46
+
47
+ \u4FDD\u5B58\u6587\u4EF6\u540E\u91CD\u65B0\u8C03\u7528\u6B64\u5DE5\u5177\u5373\u53EF\u3002
48
+ `;
49
+ return {
50
+ content: [
51
+ {
52
+ type: "text",
53
+ text
54
+ }
55
+ ]
56
+ };
57
+ }
58
+ async function handleEnhancePrompt(args) {
59
+ logger.info({ hasHistory: Boolean(args.conversation_history) }, "MCP enhance-prompt \u8C03\u7528\u5F00\u59CB");
60
+ const { checkEnhancerEnv } = await import("./config-WTC56Y2R.js");
61
+ const envCheck = checkEnhancerEnv();
62
+ if (!envCheck.isValid) {
63
+ logger.warn({ missingVars: envCheck.missingVars }, "Prompt Enhancer \u73AF\u5883\u53D8\u91CF\u672A\u914D\u7F6E");
64
+ return formatEnvMissingResponse(envCheck.missingVars);
65
+ }
66
+ try {
67
+ const { enhancePrompt } = await import("./enhancer-QHNMR35J.js");
68
+ const result = await enhancePrompt({
69
+ prompt: args.prompt,
70
+ conversationHistory: args.conversation_history,
71
+ projectRootPath: args.project_root_path
72
+ });
73
+ return {
74
+ content: [
75
+ {
76
+ type: "text",
77
+ text: result.enhanced
78
+ }
79
+ ]
80
+ };
81
+ } catch (err) {
82
+ const error = err;
83
+ logger.error({ error: error.message, stack: error.stack }, "MCP enhance-prompt \u8C03\u7528\u5931\u8D25");
84
+ return {
85
+ content: [
86
+ {
87
+ type: "text",
88
+ text: `Error: ${error.message || "unknown error"}`
89
+ }
90
+ ],
91
+ isError: true
92
+ };
93
+ }
94
+ }
95
+
96
+ // src/mcp/server.ts
97
+ var SERVER_NAME = "contextweaver";
98
+ var TOOLS = [
99
+ {
100
+ name: "codebase-retrieval",
101
+ description: `
102
+ IMPORTANT: This is the PRIMARY tool for searching the codebase.
103
+ It uses a hybrid engine (Semantic + Exact Match) to find relevant code.
104
+ Think of it as the "Google Search" for this repository.
105
+
106
+ Capabilities:
107
+ 1. Semantic Search: Understands "what code does" (e.g., "auth logic") via high-dimensional embeddings.
108
+ 2. Exact Match: Filters by precise symbols (e.g., class names) via FTS (Full Text Search).
109
+ 3. Zen Context: Returns code with localized context (breadcrumbs) to avoid token overflow.
110
+
111
+ <RULES>
112
+ # 1. Tool Selection (When to use)
113
+ - ALWAYS use this tool FIRST for any code exploration or understanding task.
114
+ - DO NOT try to guess file paths. If you don't have the exact path, use this tool.
115
+ - DO NOT use 'grep' or 'find' for semantic understanding. Only use them for exhaustive text matching (e.g. "Find ALL occurrences of string 'foo'").
116
+
117
+ # 2. Before Editing (Critical)
118
+ - Before creating a plan or editing any file, YOU MUST call this tool to gather context.
119
+ - Ask for ALL symbols involved in the edit (classes, functions, types, constants).
120
+ - Do not assume you remember the code structure. Verify it with this tool.
121
+
122
+ # 3. Query Strategy (How to use)
123
+ - Split your intent:
124
+ - Put the "Goal/Context" in 'information_request'.
125
+ - Put "Known Class/Func Names" in 'technical_terms'.
126
+ - If the first search is too broad, add more specific 'technical_terms'.
127
+ </RULES>
128
+
129
+ Examples of GOOD queries:
130
+ * [Goal: Understand Auth]
131
+ information_request: "How is user authentication flow handled?"
132
+ * [Goal: Fix DB Pool bug]
133
+ information_request: "Logic for database connection pooling and error handling"
134
+ technical_terms: ["PoolConfig", "Connection", "release"]
135
+
136
+ Examples of BAD queries:
137
+ * "Show me src/main.ts" (Use 'read_file' instead)
138
+ * "Find definition of constructor of class Foo" (Use this tool, but put "Foo" in technical_terms)
139
+ * "Find all references to function bar across the whole project" (Use 'grep' tool for exhaustive reference counting)
140
+ `,
141
+ inputSchema: {
142
+ type: "object",
143
+ properties: {
144
+ repo_path: {
145
+ type: "string",
146
+ description: "The absolute file system path to the repository root."
147
+ },
148
+ information_request: {
149
+ type: "string",
150
+ description: "The SEMANTIC GOAL. Describe the functionality, logic, or behavior you are looking for in full natural language sentences. Focus on 'how it works' rather than exact names. (e.g., 'Trace the execution flow of the login process')"
151
+ },
152
+ technical_terms: {
153
+ type: "array",
154
+ items: { type: "string" },
155
+ description: "HARD FILTERS. An optional list of EXACT, KNOWN identifiers (class/function names, constants) that MUST appear in the code. Only use terms you are 100% sure exist. Leave empty if exploring."
156
+ }
157
+ },
158
+ required: ["repo_path", "information_request"]
159
+ }
160
+ },
161
+ {
162
+ name: "enhance-prompt",
163
+ description: `
164
+ Enhance a user prompt by calling an external LLM API.
165
+
166
+ Use this tool when you want to turn a rough requirement into a clearer, more specific, and actionable prompt.
167
+
168
+ Features:
169
+ - Customizable template via env var
170
+ - Automatic language detection (Chinese input -> Chinese output)
171
+ - Optional conversation history support
172
+ `,
173
+ inputSchema: {
174
+ type: "object",
175
+ properties: {
176
+ prompt: {
177
+ type: "string",
178
+ description: "The original prompt to enhance"
179
+ },
180
+ conversation_history: {
181
+ type: "string",
182
+ description: "Recent conversation history for context. Format: 'User: ...\\nAssistant: ...'"
183
+ },
184
+ project_root_path: {
185
+ type: "string",
186
+ description: "Project root path for context"
187
+ }
188
+ },
189
+ required: ["prompt"]
190
+ }
191
+ }
192
+ ];
193
+ async function startMcpServer() {
194
+ logger.info({ name: SERVER_NAME }, "\u542F\u52A8 MCP \u670D\u52A1\u5668");
195
+ const server = new Server(
196
+ {
197
+ name: SERVER_NAME,
198
+ version: "1.0.0"
199
+ },
200
+ {
201
+ capabilities: {
202
+ tools: {}
203
+ }
204
+ }
205
+ );
206
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
207
+ logger.debug("\u6536\u5230 list_tools \u8BF7\u6C42");
208
+ return { tools: TOOLS };
209
+ });
210
+ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
211
+ const { name, arguments: args } = request.params;
212
+ logger.info({ tool: name }, "\u6536\u5230 call_tool \u8BF7\u6C42");
213
+ const rawToken = extra._meta?.progressToken;
214
+ const progressToken = typeof rawToken === "string" || typeof rawToken === "number" ? rawToken : void 0;
215
+ const onProgress = progressToken ? async (current, total, message) => {
216
+ try {
217
+ await extra.sendNotification({
218
+ method: "notifications/progress",
219
+ params: {
220
+ progressToken,
221
+ progress: current,
222
+ total,
223
+ message
224
+ }
225
+ });
226
+ } catch (err) {
227
+ logger.debug({ error: err.message }, "\u53D1\u9001\u8FDB\u5EA6\u901A\u77E5\u5931\u8D25");
228
+ }
229
+ } : void 0;
230
+ try {
231
+ switch (name) {
232
+ case "codebase-retrieval": {
233
+ const parsed = codebaseRetrievalSchema.parse(args);
234
+ return await handleCodebaseRetrieval(parsed, void 0, onProgress);
235
+ }
236
+ case "enhance-prompt": {
237
+ const parsed = enhancePromptSchema.parse(args);
238
+ return await handleEnhancePrompt(parsed);
239
+ }
240
+ default:
241
+ throw new Error(`Unknown tool: ${name}`);
242
+ }
243
+ } catch (err) {
244
+ const error = err;
245
+ logger.error({ error: error.message, stack: error.stack, tool: name }, "\u5DE5\u5177\u8C03\u7528\u5931\u8D25");
246
+ return {
247
+ content: [
248
+ {
249
+ type: "text",
250
+ text: `Error: ${error.message}`
251
+ }
252
+ ],
253
+ isError: true
254
+ };
255
+ }
256
+ });
257
+ const transport = new StdioServerTransport();
258
+ logger.info("MCP \u670D\u52A1\u5668\u5DF2\u542F\u52A8\uFF0C\u7B49\u5F85\u8FDE\u63A5...");
259
+ await server.connect(transport);
260
+ }
261
+ export {
262
+ startMcpServer
263
+ };
package/package.json ADDED
@@ -0,0 +1,82 @@
1
+ {
2
+ "name": "@lyy0709/contextweaver",
3
+ "version": "1.0.0",
4
+ "description": "A context weaving tool for LLMs — with Prompt Enhancer",
5
+ "license": "MIT",
6
+ "author": "lyy0709",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/lyy0709/ContextWeaver.git"
10
+ },
11
+ "homepage": "https://github.com/lyy0709/ContextWeaver#readme",
12
+ "private": false,
13
+ "type": "module",
14
+ "bin": {
15
+ "contextweaver": "dist/index.js",
16
+ "cw": "dist/index.js"
17
+ },
18
+ "files": [
19
+ "dist/**/*.js",
20
+ "dist/**/*.d.ts"
21
+ ],
22
+ "engines": {
23
+ "node": ">=20"
24
+ },
25
+ "scripts": {
26
+ "build": "tsup src/index.ts src/mcp/main.ts --format esm --dts --out-dir dist --sourcemap --clean",
27
+ "build:release": "tsup src/index.ts src/mcp/main.ts --format esm --dts --out-dir dist --clean",
28
+ "dev": "tsup src/index.ts src/mcp/main.ts --format esm --dts --out-dir dist --sourcemap --watch",
29
+ "fmt": "biome check --write ./src",
30
+ "test": "vitest run",
31
+ "test:watch": "vitest"
32
+ },
33
+ "dependencies": {
34
+ "@keqingmoe/tree-sitter": "^0.26.2",
35
+ "@lancedb/lancedb": "^0.22.0",
36
+ "@modelcontextprotocol/sdk": "^1.25.1",
37
+ "better-sqlite3": "^12.2.0",
38
+ "cac": "^6.7.14",
39
+ "chardet": "^2.1.1",
40
+ "dotenv": "^17.2.3",
41
+ "fdir": "^6.5.0",
42
+ "iconv-lite": "^0.7.1",
43
+ "ignore": "^7.0.5",
44
+ "p-limit": "^7.2.0",
45
+ "pino": "^10.1.0",
46
+ "tree-sitter-c": "^0.24.1",
47
+ "tree-sitter-c-sharp": "^0.23.1",
48
+ "tree-sitter-cpp": "^0.23.4",
49
+ "tree-sitter-go": "0.25.0",
50
+ "tree-sitter-java": "0.23.5",
51
+ "tree-sitter-javascript": "0.25.0",
52
+ "tree-sitter-python": "0.25.0",
53
+ "tree-sitter-rust": "0.24.0",
54
+ "tree-sitter-typescript": "0.23.2",
55
+ "zod": "^4.2.1"
56
+ },
57
+ "devDependencies": {
58
+ "@biomejs/biome": "2.3.10",
59
+ "@types/better-sqlite3": "^7.6.13",
60
+ "@types/node": "^24.0.0",
61
+ "knip": "^5.78.0",
62
+ "tsup": "^8.5.1",
63
+ "typescript": "^5.9.3",
64
+ "vitest": "^4.0.18"
65
+ },
66
+ "pnpm": {
67
+ "onlyBuiltDependencies": [
68
+ "@keqingmoe/tree-sitter",
69
+ "better-sqlite3",
70
+ "esbuild",
71
+ "tree-sitter-c",
72
+ "tree-sitter-c-sharp",
73
+ "tree-sitter-cpp",
74
+ "tree-sitter-go",
75
+ "tree-sitter-java",
76
+ "tree-sitter-javascript",
77
+ "tree-sitter-python",
78
+ "tree-sitter-rust",
79
+ "tree-sitter-typescript"
80
+ ]
81
+ }
82
+ }