@codebolt/codeboltjs 2.0.4 → 2.0.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/core/messageManager.d.ts +47 -0
- package/dist/core/messageManager.js +128 -0
- package/dist/{modules → core}/websocket.d.ts +5 -0
- package/dist/{modules → core}/websocket.js +15 -10
- package/dist/index.d.ts +98 -68
- package/dist/index.js +51 -4
- package/dist/modules/agent.js +26 -58
- package/dist/modules/browser.d.ts +7 -7
- package/dist/modules/browser.js +75 -195
- package/dist/modules/chat.d.ts +8 -20
- package/dist/modules/chat.js +60 -123
- package/dist/modules/codeparsers.d.ts +32 -3
- package/dist/modules/codeparsers.js +295 -3
- package/dist/modules/codeutils.d.ts +24 -7
- package/dist/modules/codeutils.js +113 -126
- package/dist/modules/crawler.d.ts +1 -16
- package/dist/modules/crawler.js +13 -72
- package/dist/modules/dbmemory.js +12 -28
- package/dist/modules/debug.js +17 -33
- package/dist/modules/docutils.d.ts +1 -4
- package/dist/modules/docutils.js +52 -2
- package/dist/modules/fs.d.ts +47 -1
- package/dist/modules/fs.js +151 -162
- package/dist/modules/git.d.ts +7 -14
- package/dist/modules/git.js +54 -163
- package/dist/modules/history.js +11 -27
- package/dist/modules/llm.js +8 -16
- package/dist/modules/outputparsers.d.ts +36 -4
- package/dist/modules/outputparsers.js +56 -5
- package/dist/modules/project.d.ts +4 -5
- package/dist/modules/project.js +23 -45
- package/dist/modules/state.js +29 -69
- package/dist/modules/task.js +19 -43
- package/dist/modules/terminal.d.ts +3 -2
- package/dist/modules/terminal.js +36 -47
- package/dist/modules/tokenizer.js +15 -31
- package/dist/modules/tools.d.ts +0 -6
- package/dist/modules/tools.js +41 -179
- package/dist/modules/utils.js +22 -0
- package/dist/modules/vectordb.js +30 -62
- package/dist/utils/parse-source-code/index.d.ts +9 -0
- package/dist/utils/parse-source-code/index.js +233 -0
- package/dist/utils/parse-source-code/languageParser.d.ts +8 -0
- package/dist/utils/parse-source-code/languageParser.js +137 -0
- package/dist/utils/parse-source-code/queries/c-sharp.d.ts +2 -0
- package/dist/utils/parse-source-code/queries/c-sharp.js +25 -0
- package/dist/utils/parse-source-code/queries/c.d.ts +2 -0
- package/dist/utils/parse-source-code/queries/c.js +17 -0
- package/dist/utils/parse-source-code/queries/cpp.d.ts +2 -0
- package/dist/utils/parse-source-code/queries/cpp.js +25 -0
- package/dist/utils/parse-source-code/queries/go.d.ts +2 -0
- package/dist/utils/parse-source-code/queries/go.js +29 -0
- package/dist/utils/parse-source-code/queries/index.d.ts +12 -0
- package/dist/utils/parse-source-code/queries/index.js +30 -0
- package/dist/utils/parse-source-code/queries/java.d.ts +2 -0
- package/dist/utils/parse-source-code/queries/java.js +17 -0
- package/dist/utils/parse-source-code/queries/javascript.d.ts +2 -0
- package/dist/utils/parse-source-code/queries/javascript.js +67 -0
- package/dist/utils/parse-source-code/queries/php.d.ts +2 -0
- package/dist/utils/parse-source-code/queries/php.js +17 -0
- package/dist/utils/parse-source-code/queries/python.d.ts +2 -0
- package/dist/utils/parse-source-code/queries/python.js +13 -0
- package/dist/utils/parse-source-code/queries/ruby.d.ts +2 -0
- package/dist/utils/parse-source-code/queries/ruby.js +54 -0
- package/dist/utils/parse-source-code/queries/rust.d.ts +2 -0
- package/dist/utils/parse-source-code/queries/rust.js +18 -0
- package/dist/utils/parse-source-code/queries/swift.d.ts +2 -0
- package/dist/utils/parse-source-code/queries/swift.js +47 -0
- package/dist/utils/parse-source-code/queries/typescript.d.ts +2 -0
- package/dist/utils/parse-source-code/queries/typescript.js +34 -0
- package/dist/utils/parse-source-code/tree-sitter-c.wasm +0 -0
- package/dist/utils/parse-source-code/tree-sitter-c_sharp.wasm +0 -0
- package/dist/utils/parse-source-code/tree-sitter-cpp.wasm +0 -0
- package/dist/utils/parse-source-code/tree-sitter-go.wasm +0 -0
- package/dist/utils/parse-source-code/tree-sitter-java.wasm +0 -0
- package/dist/utils/parse-source-code/tree-sitter-javascript.wasm +0 -0
- package/dist/utils/parse-source-code/tree-sitter-php.wasm +0 -0
- package/dist/utils/parse-source-code/tree-sitter-python.wasm +0 -0
- package/dist/utils/parse-source-code/tree-sitter-ruby.wasm +0 -0
- package/dist/utils/parse-source-code/tree-sitter-rust.wasm +0 -0
- package/dist/utils/parse-source-code/tree-sitter-swift.wasm +0 -0
- package/dist/utils/parse-source-code/tree-sitter-tsx.wasm +0 -0
- package/dist/utils/parse-source-code/tree-sitter-typescript.wasm +0 -0
- package/dist/utils/parse-source-code/tree-sitter.wasm +0 -0
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +1 -1
- package/package.json +6 -2
- package/dist/utils/editFile.js +0 -30
- /package/dist/{utils/editFile.d.ts → modules/utils.d.ts} +0 -0
- /package/dist/{modules → utils}/toolBox.d.ts +0 -0
- /package/dist/{modules → utils}/toolBox.js +0 -0
package/dist/modules/tools.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const websocket_1 = __importDefault(require("
|
|
6
|
+
const websocket_1 = __importDefault(require("../core/websocket"));
|
|
7
7
|
/**
|
|
8
8
|
* Object containing methods for interacting with Codebolt MCP (Model Context Protocol) tools.
|
|
9
9
|
* Provides functionality to discover, list, and execute tools.
|
|
@@ -15,26 +15,10 @@ const codeboltMCP = {
|
|
|
15
15
|
* @returns Promise with the enabled toolboxes data
|
|
16
16
|
*/
|
|
17
17
|
getEnabledToolBoxes: () => {
|
|
18
|
-
return
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}));
|
|
23
|
-
websocket_1.default.getWebsocket.on('message', (data) => {
|
|
24
|
-
try {
|
|
25
|
-
const response = JSON.parse(data);
|
|
26
|
-
if (response.type === "getEnabledToolBoxesResponse") {
|
|
27
|
-
resolve(response.data);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
catch (error) {
|
|
31
|
-
reject(new Error("Failed to parse response"));
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
websocket_1.default.getWebsocket.on('error', (error) => {
|
|
35
|
-
reject(error);
|
|
36
|
-
});
|
|
37
|
-
});
|
|
18
|
+
return websocket_1.default.messageManager.sendAndWaitForResponse({
|
|
19
|
+
"type": "codebolttools",
|
|
20
|
+
"action": "getEnabledToolBoxes"
|
|
21
|
+
}, "getEnabledToolBoxesResponse");
|
|
38
22
|
},
|
|
39
23
|
/**
|
|
40
24
|
* Gets the list of locally available toolboxes.
|
|
@@ -42,26 +26,10 @@ const codeboltMCP = {
|
|
|
42
26
|
* @returns Promise with the local toolboxes data
|
|
43
27
|
*/
|
|
44
28
|
getLocalToolBoxes: () => {
|
|
45
|
-
return
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}));
|
|
50
|
-
websocket_1.default.getWebsocket.on('message', (data) => {
|
|
51
|
-
try {
|
|
52
|
-
const response = JSON.parse(data);
|
|
53
|
-
if (response.type === "getLocalToolBoxesResponse") {
|
|
54
|
-
resolve(response.data);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
catch (error) {
|
|
58
|
-
reject(new Error("Failed to parse response"));
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
websocket_1.default.getWebsocket.on('error', (error) => {
|
|
62
|
-
reject(error);
|
|
63
|
-
});
|
|
64
|
-
});
|
|
29
|
+
return websocket_1.default.messageManager.sendAndWaitForResponse({
|
|
30
|
+
"type": "codebolttools",
|
|
31
|
+
"action": "getLocalToolBoxes"
|
|
32
|
+
}, "getLocalToolBoxesResponse");
|
|
65
33
|
},
|
|
66
34
|
/**
|
|
67
35
|
* Gets toolboxes mentioned in a user message.
|
|
@@ -70,36 +38,10 @@ const codeboltMCP = {
|
|
|
70
38
|
* @returns Promise with the mentioned toolboxes
|
|
71
39
|
*/
|
|
72
40
|
getMentionedToolBoxes: (userMessage) => {
|
|
73
|
-
return
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Gets all available toolboxes.
|
|
79
|
-
*
|
|
80
|
-
* @returns Promise with all available toolboxes data
|
|
81
|
-
*/
|
|
82
|
-
getAvailableToolBoxes: () => {
|
|
83
|
-
return new Promise((resolve, reject) => {
|
|
84
|
-
websocket_1.default.getWebsocket.send(JSON.stringify({
|
|
85
|
-
"type": "codebolttools",
|
|
86
|
-
"action": "getAvailableToolBoxes"
|
|
87
|
-
}));
|
|
88
|
-
websocket_1.default.getWebsocket.on('message', (data) => {
|
|
89
|
-
try {
|
|
90
|
-
const response = JSON.parse(data);
|
|
91
|
-
if (response.type === "getAvailableToolBoxesResponse") {
|
|
92
|
-
resolve(response.data);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
catch (error) {
|
|
96
|
-
reject(new Error("Failed to parse response"));
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
websocket_1.default.getWebsocket.on('error', (error) => {
|
|
100
|
-
reject(error);
|
|
101
|
-
});
|
|
102
|
-
});
|
|
41
|
+
return websocket_1.default.messageManager.sendAndWaitForResponse({
|
|
42
|
+
"type": "codebolttools",
|
|
43
|
+
"action": "getAvailableToolBoxes"
|
|
44
|
+
}, "getAvailableToolBoxesResponse");
|
|
103
45
|
},
|
|
104
46
|
/**
|
|
105
47
|
* Searches for available toolboxes matching a query.
|
|
@@ -108,27 +50,11 @@ const codeboltMCP = {
|
|
|
108
50
|
* @returns Promise with matching toolboxes data
|
|
109
51
|
*/
|
|
110
52
|
searchAvailableToolBoxes: (query) => {
|
|
111
|
-
return
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}));
|
|
117
|
-
websocket_1.default.getWebsocket.on('message', (data) => {
|
|
118
|
-
try {
|
|
119
|
-
const response = JSON.parse(data);
|
|
120
|
-
if (response.type === "searchAvailableToolBoxesResponse") {
|
|
121
|
-
resolve(response.data);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
catch (error) {
|
|
125
|
-
reject(new Error("Failed to parse response"));
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
websocket_1.default.getWebsocket.on('error', (error) => {
|
|
129
|
-
reject(error);
|
|
130
|
-
});
|
|
131
|
-
});
|
|
53
|
+
return websocket_1.default.messageManager.sendAndWaitForResponse({
|
|
54
|
+
"type": "codebolttools",
|
|
55
|
+
"action": "searchAvailableToolBoxes",
|
|
56
|
+
"query": query
|
|
57
|
+
}, "searchAvailableToolBoxesResponse");
|
|
132
58
|
},
|
|
133
59
|
/**
|
|
134
60
|
* Lists all tools from the specified toolboxes.
|
|
@@ -137,27 +63,11 @@ const codeboltMCP = {
|
|
|
137
63
|
* @returns Promise with tools from the specified toolboxes
|
|
138
64
|
*/
|
|
139
65
|
listToolsFromToolBoxes: (toolBoxes) => {
|
|
140
|
-
return
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}));
|
|
146
|
-
websocket_1.default.getWebsocket.on('message', (data) => {
|
|
147
|
-
try {
|
|
148
|
-
const response = JSON.parse(data);
|
|
149
|
-
if (response.type === "listToolsFromToolBoxesResponse") {
|
|
150
|
-
resolve(response.data);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
catch (error) {
|
|
154
|
-
reject(new Error("Failed to parse response"));
|
|
155
|
-
}
|
|
156
|
-
});
|
|
157
|
-
websocket_1.default.getWebsocket.on('error', (error) => {
|
|
158
|
-
reject(error);
|
|
159
|
-
});
|
|
160
|
-
});
|
|
66
|
+
return websocket_1.default.messageManager.sendAndWaitForResponse({
|
|
67
|
+
"type": "codebolttools",
|
|
68
|
+
"action": "listToolsFromToolBoxes",
|
|
69
|
+
"toolBoxes": toolBoxes
|
|
70
|
+
}, "listToolsFromToolBoxesResponse");
|
|
161
71
|
},
|
|
162
72
|
/**
|
|
163
73
|
* Configures a specific toolbox with provided configuration.
|
|
@@ -167,28 +77,12 @@ const codeboltMCP = {
|
|
|
167
77
|
* @returns Promise with the configuration result
|
|
168
78
|
*/
|
|
169
79
|
configureToolBox: (name, config) => {
|
|
170
|
-
return
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
}));
|
|
177
|
-
websocket_1.default.getWebsocket.on('message', (data) => {
|
|
178
|
-
try {
|
|
179
|
-
const response = JSON.parse(data);
|
|
180
|
-
if (response.type === "configureToolBoxResponse") {
|
|
181
|
-
resolve(response.data);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
catch (error) {
|
|
185
|
-
reject(new Error("Failed to parse response"));
|
|
186
|
-
}
|
|
187
|
-
});
|
|
188
|
-
websocket_1.default.getWebsocket.on('error', (error) => {
|
|
189
|
-
reject(error);
|
|
190
|
-
});
|
|
191
|
-
});
|
|
80
|
+
return websocket_1.default.messageManager.sendAndWaitForResponse({
|
|
81
|
+
"type": "codebolttools",
|
|
82
|
+
"action": "configureToolBox",
|
|
83
|
+
"mcpName": name,
|
|
84
|
+
"config": config
|
|
85
|
+
}, "configureToolBoxResponse");
|
|
192
86
|
},
|
|
193
87
|
/**
|
|
194
88
|
* Gets detailed information about specific tools.
|
|
@@ -197,27 +91,11 @@ const codeboltMCP = {
|
|
|
197
91
|
* @returns Promise with detailed information about the tools
|
|
198
92
|
*/
|
|
199
93
|
getTools: (tools) => {
|
|
200
|
-
return
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}));
|
|
206
|
-
websocket_1.default.getWebsocket.on('message', (data) => {
|
|
207
|
-
try {
|
|
208
|
-
const response = JSON.parse(data);
|
|
209
|
-
if (response.type === "getToolsResponse") {
|
|
210
|
-
resolve(response.data);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
catch (error) {
|
|
214
|
-
reject(new Error("Failed to parse response"));
|
|
215
|
-
}
|
|
216
|
-
});
|
|
217
|
-
websocket_1.default.getWebsocket.on('error', (error) => {
|
|
218
|
-
reject(error);
|
|
219
|
-
});
|
|
220
|
-
});
|
|
94
|
+
return websocket_1.default.messageManager.sendAndWaitForResponse({
|
|
95
|
+
"type": "codebolttools",
|
|
96
|
+
"action": "getTools",
|
|
97
|
+
"toolboxes": tools
|
|
98
|
+
}, "getToolsResponse");
|
|
221
99
|
},
|
|
222
100
|
/**
|
|
223
101
|
* Executes a specific tool with provided parameters.
|
|
@@ -228,28 +106,12 @@ const codeboltMCP = {
|
|
|
228
106
|
* @returns Promise with the execution result
|
|
229
107
|
*/
|
|
230
108
|
executeTool: (toolbox, toolName, params) => {
|
|
231
|
-
return
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
websocket_1.default.getWebsocket.on('message', (data) => {
|
|
239
|
-
try {
|
|
240
|
-
const response = JSON.parse(data);
|
|
241
|
-
if (response.type === "executeToolResponse") {
|
|
242
|
-
resolve(response.data);
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
catch (error) {
|
|
246
|
-
reject(new Error("Failed to parse response"));
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
websocket_1.default.getWebsocket.on('error', (error) => {
|
|
250
|
-
reject(error);
|
|
251
|
-
});
|
|
252
|
-
});
|
|
253
|
-
},
|
|
109
|
+
return websocket_1.default.messageManager.sendAndWaitForResponse({
|
|
110
|
+
"type": "codebolttools",
|
|
111
|
+
"action": "executeTool",
|
|
112
|
+
"toolName": `${toolbox}--${toolName}`,
|
|
113
|
+
"params": params
|
|
114
|
+
}, "executeToolResponse");
|
|
115
|
+
}
|
|
254
116
|
};
|
|
255
117
|
exports.default = codeboltMCP;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const websocket_1 = __importDefault(require("../core/websocket"));
|
|
7
|
+
const cbutils = {
|
|
8
|
+
editFileAndApplyDiff: (filePath, diff, diffIdentifier, prompt, applyModel) => {
|
|
9
|
+
return websocket_1.default.messageManager.sendAndWaitForResponse({
|
|
10
|
+
"type": "fsEvent",
|
|
11
|
+
"action": "editFileAndApplyDiff",
|
|
12
|
+
message: {
|
|
13
|
+
filePath,
|
|
14
|
+
diff,
|
|
15
|
+
diffIdentifier,
|
|
16
|
+
prompt,
|
|
17
|
+
applyModel
|
|
18
|
+
}
|
|
19
|
+
}, "editFileAndApplyDiffResponse");
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
exports.default = cbutils;
|
package/dist/modules/vectordb.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const websocket_1 = __importDefault(require("
|
|
6
|
+
const websocket_1 = __importDefault(require("../core/websocket"));
|
|
7
7
|
const VectorDB = {
|
|
8
8
|
/**
|
|
9
9
|
* Retrieves a vector from the vector database based on the provided key.
|
|
@@ -12,21 +12,13 @@ const VectorDB = {
|
|
|
12
12
|
* @returns {Promise<GetVectorResponse>} A promise that resolves with the retrieved vector.
|
|
13
13
|
*/
|
|
14
14
|
getVector: async (key) => {
|
|
15
|
-
return
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}));
|
|
23
|
-
websocket_1.default.getWebsocket.on('message', (data) => {
|
|
24
|
-
const response = JSON.parse(data);
|
|
25
|
-
if (response.type === "getVectorResponse") {
|
|
26
|
-
resolve(response);
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
});
|
|
15
|
+
return websocket_1.default.messageManager.sendAndWaitForResponse({
|
|
16
|
+
"type": "vectordbEvent",
|
|
17
|
+
"action": "getVector",
|
|
18
|
+
"message": {
|
|
19
|
+
item: key
|
|
20
|
+
},
|
|
21
|
+
}, "getVectorResponse");
|
|
30
22
|
},
|
|
31
23
|
/**
|
|
32
24
|
* Adds a new vector item to the vector database.
|
|
@@ -36,21 +28,13 @@ const VectorDB = {
|
|
|
36
28
|
* @returns {Promise<AddVectorItemResponse>} A promise that resolves when the item is successfully added.
|
|
37
29
|
*/
|
|
38
30
|
addVectorItem: async (item) => {
|
|
39
|
-
return
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}));
|
|
47
|
-
websocket_1.default.getWebsocket.on('message', (data) => {
|
|
48
|
-
const response = JSON.parse(data);
|
|
49
|
-
if (response.type === "addVectorItemResponse") {
|
|
50
|
-
resolve(response);
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
});
|
|
31
|
+
return websocket_1.default.messageManager.sendAndWaitForResponse({
|
|
32
|
+
"type": "vectordbEvent",
|
|
33
|
+
"action": "addVectorItem",
|
|
34
|
+
"message": {
|
|
35
|
+
item: item
|
|
36
|
+
},
|
|
37
|
+
}, "addVectorItemResponse");
|
|
54
38
|
},
|
|
55
39
|
/**
|
|
56
40
|
* Queries a vector item from the vector database based on the provided key.
|
|
@@ -59,21 +43,13 @@ const VectorDB = {
|
|
|
59
43
|
* @returns {Promise<QueryVectorItemResponse>} A promise that resolves with the queried vector item.
|
|
60
44
|
*/
|
|
61
45
|
queryVectorItem: async (key) => {
|
|
62
|
-
return
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}));
|
|
70
|
-
websocket_1.default.getWebsocket.on('message', (data) => {
|
|
71
|
-
const response = JSON.parse(data);
|
|
72
|
-
if (response.type === "qeryVectorItemResponse") {
|
|
73
|
-
resolve(response);
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
});
|
|
46
|
+
return websocket_1.default.messageManager.sendAndWaitForResponse({
|
|
47
|
+
"type": "vectordbEvent",
|
|
48
|
+
"action": "queryVectorItem",
|
|
49
|
+
"message": {
|
|
50
|
+
item: key
|
|
51
|
+
},
|
|
52
|
+
}, "qeryVectorItemResponse");
|
|
77
53
|
},
|
|
78
54
|
/**
|
|
79
55
|
* Queries a vector item from the vector database based on the provided key.
|
|
@@ -82,22 +58,14 @@ const VectorDB = {
|
|
|
82
58
|
* @returns {Promise<QueryVectorItemResponse>} A promise that resolves with the queried vector item.
|
|
83
59
|
*/
|
|
84
60
|
queryVectorItems: async (items, dbPath) => {
|
|
85
|
-
return
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}));
|
|
94
|
-
websocket_1.default.getWebsocket.on('message', (data) => {
|
|
95
|
-
const response = JSON.parse(data);
|
|
96
|
-
if (response.type === "qeryVectorItemsResponse") {
|
|
97
|
-
resolve(response);
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
});
|
|
61
|
+
return websocket_1.default.messageManager.sendAndWaitForResponse({
|
|
62
|
+
"type": "vectordbEvent",
|
|
63
|
+
"action": "queryVectorItems",
|
|
64
|
+
"message": {
|
|
65
|
+
items,
|
|
66
|
+
dbPath
|
|
67
|
+
},
|
|
68
|
+
}, "qeryVectorItemsResponse");
|
|
101
69
|
},
|
|
102
70
|
};
|
|
103
71
|
exports.default = VectorDB;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const LIST_FILES_LIMIT = 200;
|
|
2
|
+
export declare function parseSourceCodeForDefinitionsTopLevel(dirPath: string): Promise<string>;
|
|
3
|
+
export declare function listFiles(dirPath: string, recursive: boolean): Promise<string[]>;
|
|
4
|
+
export declare function globbyLevelByLevel(options: any): Promise<string[]>;
|
|
5
|
+
export declare function separateFiles(allFiles: string[]): {
|
|
6
|
+
filesToParse: string[];
|
|
7
|
+
remainingFiles: string[];
|
|
8
|
+
};
|
|
9
|
+
export declare function parseFile(filePath: string, languageParsers: any): Promise<string | undefined>;
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseFile = exports.separateFiles = exports.globbyLevelByLevel = exports.listFiles = exports.parseSourceCodeForDefinitionsTopLevel = exports.LIST_FILES_LIMIT = void 0;
|
|
4
|
+
const fs = require("fs/promises");
|
|
5
|
+
const os = require("os");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
const { LanguageParser, loadRequiredLanguageParsers } = require("./languageParser");
|
|
8
|
+
// const { globby } = await import("globby");
|
|
9
|
+
const { globby } = require('@codebolt/globby');
|
|
10
|
+
exports.LIST_FILES_LIMIT = 200;
|
|
11
|
+
// TODO: implement caching behavior to avoid having to keep analyzing project for new tasks.
|
|
12
|
+
async function parseSourceCodeForDefinitionsTopLevel(dirPath) {
|
|
13
|
+
// check if the path exists
|
|
14
|
+
const dirExists = await fs
|
|
15
|
+
.access(path.resolve(dirPath))
|
|
16
|
+
.then(() => true)
|
|
17
|
+
.catch(() => false);
|
|
18
|
+
if (!dirExists) {
|
|
19
|
+
return "This directory does not exist or you do not have permission to access it.";
|
|
20
|
+
}
|
|
21
|
+
// Get all files at top level (not gitignored)
|
|
22
|
+
const allFiles = await listFiles(dirPath, false);
|
|
23
|
+
let result = "";
|
|
24
|
+
// Separate files to parse and remaining files
|
|
25
|
+
const { filesToParse, remainingFiles } = separateFiles(allFiles);
|
|
26
|
+
const languageParsers = await loadRequiredLanguageParsers(filesToParse);
|
|
27
|
+
// Parse specific files we have language parsers for
|
|
28
|
+
// const filesWithoutDefinitions: string[] = []
|
|
29
|
+
for (const file of filesToParse) {
|
|
30
|
+
const definitions = await parseFile(file, languageParsers);
|
|
31
|
+
if (definitions) {
|
|
32
|
+
result += `${path.relative(dirPath, file)}\n${definitions}\n`;
|
|
33
|
+
}
|
|
34
|
+
// else {
|
|
35
|
+
// filesWithoutDefinitions.push(file)
|
|
36
|
+
// }
|
|
37
|
+
}
|
|
38
|
+
// List remaining files' paths
|
|
39
|
+
// let didFindUnparsedFiles = false
|
|
40
|
+
// filesWithoutDefinitions
|
|
41
|
+
// .concat(remainingFiles)
|
|
42
|
+
// .sort()
|
|
43
|
+
// .forEach((file) => {
|
|
44
|
+
// if (!didFindUnparsedFiles) {
|
|
45
|
+
// result += "# Unparsed Files\n\n"
|
|
46
|
+
// didFindUnparsedFiles = true
|
|
47
|
+
// }
|
|
48
|
+
// result += `${path.relative(dirPath, file)}\n`
|
|
49
|
+
// })
|
|
50
|
+
return result ? result : "No source code definitions found.";
|
|
51
|
+
}
|
|
52
|
+
exports.parseSourceCodeForDefinitionsTopLevel = parseSourceCodeForDefinitionsTopLevel;
|
|
53
|
+
async function listFiles(dirPath, recursive) {
|
|
54
|
+
const absolutePath = path.resolve(dirPath);
|
|
55
|
+
// Do not allow listing files in root or home directory, which Claude tends to want to do when the user's prompt is vague.
|
|
56
|
+
const root = process.platform === "win32" ? path.parse(absolutePath).root : "/";
|
|
57
|
+
const isRoot = absolutePath === root;
|
|
58
|
+
if (isRoot) {
|
|
59
|
+
return [root];
|
|
60
|
+
}
|
|
61
|
+
const homeDir = os.homedir();
|
|
62
|
+
const isHomeDir = absolutePath === homeDir;
|
|
63
|
+
if (isHomeDir) {
|
|
64
|
+
return [homeDir];
|
|
65
|
+
}
|
|
66
|
+
const dirsToIgnore = [
|
|
67
|
+
"node_modules",
|
|
68
|
+
"__pycache__",
|
|
69
|
+
"env",
|
|
70
|
+
"venv",
|
|
71
|
+
"target/dependency",
|
|
72
|
+
"build/dependencies",
|
|
73
|
+
"dist",
|
|
74
|
+
"out",
|
|
75
|
+
"bundle",
|
|
76
|
+
"vendor",
|
|
77
|
+
"tmp",
|
|
78
|
+
"temp",
|
|
79
|
+
"deps",
|
|
80
|
+
"pkg",
|
|
81
|
+
"Pods",
|
|
82
|
+
".*", // Ignore all hidden directories and files
|
|
83
|
+
].map((dir) => `**/${dir}/**`);
|
|
84
|
+
const options = {
|
|
85
|
+
cwd: dirPath,
|
|
86
|
+
dot: false, // do not ignore hidden files/directories
|
|
87
|
+
absolute: true,
|
|
88
|
+
markDirectories: true, // Append a / on any directories matched
|
|
89
|
+
gitignore: recursive, // globby ignores any files that are gitignored
|
|
90
|
+
ignore: recursive ? dirsToIgnore : undefined, // just in case there is no gitignore, we ignore sensible defaults
|
|
91
|
+
onlyFiles: false, // true by default, false means it will list directories on their own too
|
|
92
|
+
};
|
|
93
|
+
// * globs all files in one dir, ** globs files in nested directories
|
|
94
|
+
const files = recursive
|
|
95
|
+
? await globbyLevelByLevel(options)
|
|
96
|
+
: (await globby("*", options)).slice(0, exports.LIST_FILES_LIMIT);
|
|
97
|
+
return files;
|
|
98
|
+
}
|
|
99
|
+
exports.listFiles = listFiles;
|
|
100
|
+
// globby doesnt natively support top down level by level globbing, so we implement it ourselves
|
|
101
|
+
async function globbyLevelByLevel(options) {
|
|
102
|
+
let results = [];
|
|
103
|
+
const globbingProcess = async () => {
|
|
104
|
+
let currentLevel = 0;
|
|
105
|
+
// const { globby } = await import("globby");
|
|
106
|
+
while (results.length < exports.LIST_FILES_LIMIT) {
|
|
107
|
+
const pattern = currentLevel === 0 ? "*" : `${"*/".repeat(currentLevel)}*`;
|
|
108
|
+
const filesAtLevel = await globby(pattern, options);
|
|
109
|
+
if (filesAtLevel.length === 0) {
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
results.push(...filesAtLevel);
|
|
113
|
+
if (results.length >= exports.LIST_FILES_LIMIT) {
|
|
114
|
+
results = results.slice(0, exports.LIST_FILES_LIMIT);
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
currentLevel++;
|
|
118
|
+
}
|
|
119
|
+
return results;
|
|
120
|
+
};
|
|
121
|
+
// Timeout after 10 seconds and return partial results
|
|
122
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
123
|
+
setTimeout(() => reject(new Error("Globbing timeout")), 10000);
|
|
124
|
+
});
|
|
125
|
+
try {
|
|
126
|
+
return await Promise.race([globbingProcess(), timeoutPromise]);
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
console.log(error);
|
|
130
|
+
console.warn("Globbing timed out, returning partial results");
|
|
131
|
+
return results;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
exports.globbyLevelByLevel = globbyLevelByLevel;
|
|
135
|
+
function separateFiles(allFiles) {
|
|
136
|
+
const extensions = [
|
|
137
|
+
"js",
|
|
138
|
+
"jsx",
|
|
139
|
+
"ts",
|
|
140
|
+
"tsx",
|
|
141
|
+
"py",
|
|
142
|
+
// Rust
|
|
143
|
+
"rs",
|
|
144
|
+
"go",
|
|
145
|
+
// C
|
|
146
|
+
"c",
|
|
147
|
+
"h",
|
|
148
|
+
// C++
|
|
149
|
+
"cpp",
|
|
150
|
+
"hpp",
|
|
151
|
+
// C#
|
|
152
|
+
"cs",
|
|
153
|
+
// Ruby
|
|
154
|
+
"rb",
|
|
155
|
+
"java",
|
|
156
|
+
"php",
|
|
157
|
+
"swift",
|
|
158
|
+
].map((e) => `.${e}`);
|
|
159
|
+
const filesToParse = allFiles.filter((file) => extensions.includes(path.extname(file))).slice(0, 50); // 50 files max
|
|
160
|
+
const remainingFiles = allFiles.filter((file) => !filesToParse.includes(file));
|
|
161
|
+
return { filesToParse, remainingFiles };
|
|
162
|
+
}
|
|
163
|
+
exports.separateFiles = separateFiles;
|
|
164
|
+
/*
|
|
165
|
+
Parsing files using tree-sitter
|
|
166
|
+
|
|
167
|
+
1. Parse the file content into an AST (Abstract Syntax Tree) using the appropriate language grammar (set of rules that define how the components of a language like keywords, expressions, and statements can be combined to create valid programs).
|
|
168
|
+
2. Create a query using a language-specific query string, and run it against the AST's root node to capture specific syntax elements.
|
|
169
|
+
- We use tag queries to identify named entities in a program, and then use a syntax capture to label the entity and its name. A notable example of this is GitHub's search-based code navigation.
|
|
170
|
+
- Our custom tag queries are based on tree-sitter's default tag queries, but modified to only capture definitions.
|
|
171
|
+
3. Sort the captures by their position in the file, output the name of the definition, and format by i.e. adding "|----\n" for gaps between captured sections.
|
|
172
|
+
|
|
173
|
+
This approach allows us to focus on the most relevant parts of the code (defined by our language-specific queries) and provides a concise yet informative view of the file's structure and key elements.
|
|
174
|
+
|
|
175
|
+
- https://github.com/tree-sitter/node-tree-sitter/blob/master/test/query_test.js
|
|
176
|
+
- https://github.com/tree-sitter/tree-sitter/blob/master/lib/binding_web/test/query-test.js
|
|
177
|
+
- https://github.com/tree-sitter/tree-sitter/blob/master/lib/binding_web/test/helper.js
|
|
178
|
+
- https://tree-sitter.github.io/tree-sitter/code-navigation-systems
|
|
179
|
+
*/
|
|
180
|
+
async function parseFile(filePath, languageParsers) {
|
|
181
|
+
const fileContent = await fs.readFile(filePath, "utf8");
|
|
182
|
+
const ext = path.extname(filePath).toLowerCase().slice(1);
|
|
183
|
+
const { parser, query } = languageParsers[ext] || {};
|
|
184
|
+
if (!parser || !query) {
|
|
185
|
+
return `Unsupported file type: ${filePath}`;
|
|
186
|
+
}
|
|
187
|
+
let formattedOutput = "";
|
|
188
|
+
try {
|
|
189
|
+
// Parse the file content into an Abstract Syntax Tree (AST), a tree-like representation of the code
|
|
190
|
+
const tree = parser.parse(fileContent);
|
|
191
|
+
// Apply the query to the AST and get the captures
|
|
192
|
+
// Captures are specific parts of the AST that match our query patterns, each capture represents a node in the AST that we're interested in.
|
|
193
|
+
const captures = query.captures(tree.rootNode);
|
|
194
|
+
// Sort captures by their start position
|
|
195
|
+
captures.sort((a, b) => a.node.startPosition.row - b.node.startPosition.row);
|
|
196
|
+
// Split the file content into individual lines
|
|
197
|
+
const lines = fileContent.split("\n");
|
|
198
|
+
// Keep track of the last line we've processed
|
|
199
|
+
let lastLine = -1;
|
|
200
|
+
captures.forEach((capture) => {
|
|
201
|
+
const { node, name } = capture;
|
|
202
|
+
// Get the start and end lines of the current AST node
|
|
203
|
+
const startLine = node.startPosition.row;
|
|
204
|
+
const endLine = node.endPosition.row;
|
|
205
|
+
// Once we've retrieved the nodes we care about through the language query, we filter for lines with definition names only.
|
|
206
|
+
// name.startsWith("name.reference.") > refs can be used for ranking purposes, but we don't need them for the output
|
|
207
|
+
// previously we did `name.startsWith("name.definition.")` but this was too strict and excluded some relevant definitions
|
|
208
|
+
// Add separator if there's a gap between captures
|
|
209
|
+
if (lastLine !== -1 && startLine > lastLine + 1) {
|
|
210
|
+
formattedOutput += "|----\n";
|
|
211
|
+
}
|
|
212
|
+
// Only add the first line of the definition
|
|
213
|
+
// query captures includes the definition name and the definition implementation, but we only want the name (I found discrepencies in the naming structure for various languages, i.e. javascript names would be 'name' and typescript names would be 'name.definition)
|
|
214
|
+
if (name.includes("name") && lines[startLine]) {
|
|
215
|
+
formattedOutput += `│${lines[startLine]}\n`;
|
|
216
|
+
}
|
|
217
|
+
// Adds all the captured lines
|
|
218
|
+
// for (let i = startLine; i <= endLine; i++) {
|
|
219
|
+
// formattedOutput += `│${lines[i]}\n`
|
|
220
|
+
// }
|
|
221
|
+
//}
|
|
222
|
+
lastLine = endLine;
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
catch (error) {
|
|
226
|
+
console.log(`Error parsing file: ${error}\n`);
|
|
227
|
+
}
|
|
228
|
+
if (formattedOutput.length > 0) {
|
|
229
|
+
return `|----\n${formattedOutput}|----\n`;
|
|
230
|
+
}
|
|
231
|
+
return undefined;
|
|
232
|
+
}
|
|
233
|
+
exports.parseFile = parseFile;
|