snow-ai 0.2.14 → 0.2.15

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.
@@ -5,9 +5,6 @@ interface SearchMatch {
5
5
  lineContent: string;
6
6
  column: number;
7
7
  matchedText?: string;
8
- nodeType?: string;
9
- nodeName?: string;
10
- language?: string;
11
8
  }
12
9
  interface SearchResult {
13
10
  query: string;
@@ -151,7 +148,7 @@ export declare class FilesystemMCPService {
151
148
  * @param maxResults - Maximum number of results to return (default: 100)
152
149
  * @returns Search results with file paths, line numbers, and matched content
153
150
  */
154
- searchCode(query: string, dirPath?: string, fileExtensions?: string[], caseSensitive?: boolean, maxResults?: number, searchMode?: 'text' | 'regex' | 'ast'): Promise<SearchResult>;
151
+ searchCode(query: string, dirPath?: string, fileExtensions?: string[], caseSensitive?: boolean, maxResults?: number, searchMode?: 'text' | 'regex'): Promise<SearchResult>;
155
152
  /**
156
153
  * Resolve path relative to base path and normalize it
157
154
  * @private
@@ -3,7 +3,6 @@ import * as path from 'path';
3
3
  import { execSync } from 'child_process';
4
4
  import { vscodeConnection } from '../utils/vscodeConnection.js';
5
5
  import { incrementalSnapshotManager } from '../utils/incrementalSnapshot.js';
6
- import { multiLanguageASTParser } from './multiLanguageASTParser.js';
7
6
  const { resolve, dirname, isAbsolute } = path;
8
7
  /**
9
8
  * Filesystem MCP Service
@@ -660,37 +659,8 @@ export class FilesystemMCPService {
660
659
  searchedFiles++;
661
660
  try {
662
661
  const content = await fs.readFile(fullPath, 'utf-8');
663
- // AST search mode - supports multiple languages via tree-sitter
664
- if (searchMode === 'ast') {
665
- // Check if file is supported for AST parsing
666
- if (multiLanguageASTParser.isSupported(fullPath)) {
667
- try {
668
- const astResults = multiLanguageASTParser.searchAST(content, fullPath, query, caseSensitive);
669
- for (const result of astResults) {
670
- if (matches.length >= maxResults) {
671
- break;
672
- }
673
- const lineContent = content.split('\n')[result.startPosition.line - 1] ||
674
- '';
675
- matches.push({
676
- filePath: path.relative(this.basePath, fullPath),
677
- lineNumber: result.startPosition.line,
678
- lineContent: lineContent.trim(),
679
- column: result.startPosition.column,
680
- matchedText: result.name,
681
- nodeType: result.type,
682
- nodeName: result.name,
683
- language: result.language,
684
- });
685
- }
686
- }
687
- catch (error) {
688
- // Skip files with AST parsing errors
689
- }
690
- }
691
- }
692
- else if (searchRegex) {
693
- // Text or Regex search mode
662
+ // Text or Regex search mode
663
+ if (searchRegex) {
694
664
  const lines = content.split('\n');
695
665
  lines.forEach((line, index) => {
696
666
  if (matches.length >= maxResults) {
@@ -900,8 +870,8 @@ export const mcpTools = [
900
870
  },
901
871
  searchMode: {
902
872
  type: 'string',
903
- enum: ['text', 'regex', 'ast'],
904
- description: 'Search mode: "text" for literal text search (default), "regex" for regular expression search, "ast" for AST-based semantic search (supports function/class/variable names)',
873
+ enum: ['text', 'regex'],
874
+ description: 'Search mode: "text" for literal text search (default), "regex" for regular expression search',
905
875
  default: 'text',
906
876
  },
907
877
  },
@@ -392,8 +392,8 @@ export async function executeMCPTool(toolName, args) {
392
392
  case 'edit':
393
393
  return await filesystemService.editFile(args.filePath, args.startLine, args.endLine, args.newContent, args.contextLines);
394
394
  case 'search': {
395
- // 兼容性处理:如果 searchMode 不存在或无效,默认使用 'text'
396
- const validSearchModes = ['text', 'regex', 'ast'];
395
+ // 兼容性处理:如果 searchMode 不存在或无效,默认使用 'text'
396
+ const validSearchModes = ['text', 'regex'];
397
397
  let searchMode = 'text';
398
398
  if (args.searchMode && validSearchModes.includes(args.searchMode)) {
399
399
  searchMode = args.searchMode;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snow-ai",
3
- "version": "0.2.14",
3
+ "version": "0.2.15",
4
4
  "description": "Intelligent Command Line Assistant powered by AI",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -59,18 +59,6 @@
59
59
  "react": "^18.2.0",
60
60
  "string-width": "^7.2.0",
61
61
  "tiktoken": "^1.0.22",
62
- "tree-sitter": "^0.25.0",
63
- "tree-sitter-c": "^0.24.1",
64
- "tree-sitter-c-sharp": "^0.23.1",
65
- "tree-sitter-cpp": "^0.23.4",
66
- "tree-sitter-go": "^0.25.0",
67
- "tree-sitter-java": "^0.23.5",
68
- "tree-sitter-javascript": "^0.25.0",
69
- "tree-sitter-php": "^0.24.2",
70
- "tree-sitter-python": "^0.25.0",
71
- "tree-sitter-ruby": "^0.23.1",
72
- "tree-sitter-rust": "^0.24.0",
73
- "tree-sitter-typescript": "^0.23.2",
74
62
  "ws": "^8.14.2"
75
63
  },
76
64
  "devDependencies": {
package/readme.md CHANGED
@@ -57,9 +57,9 @@ $ npm uninstall --global snow-ai
57
57
 
58
58
  ## Install VSCode Extension
59
59
 
60
- * download [VSIX/snow-cli-0.2.5.vsix](https://github.com/MayDay-wpf/snow-cli/blob/main/VSIX/snow-cli-0.2.5.vsix)
60
+ * download [VSIX/snow-cli-0.2.6.vsix](https://github.com/MayDay-wpf/snow-cli/blob/main/VSIX/snow-cli-0.2.6.vsix)
61
61
 
62
- * open VSCode, click `Extensions` -> `Install from VSIX...` -> select `snow-cli-0.2.5.vsix`
62
+ * open VSCode, click `Extensions` -> `Install from VSIX...` -> select `snow-cli-0.2.6.vsix`
63
63
 
64
64
  ## Live View
65
65
  * **Welcome & Settings**
@@ -73,6 +73,8 @@ $ npm uninstall --global snow-ai
73
73
 
74
74
  * When mounting: double-click ESC, view the dialogue recorder, select rollback, including file checkpoints
75
75
 
76
+ * Windows & MacOS:`ctrl + v` Paste image
77
+
76
78
  * **Commands**
77
79
 
78
80
  ![alt text](image-2.png)
@@ -1,67 +0,0 @@
1
- /**
2
- * Supported programming languages for AST parsing
3
- */
4
- export type SupportedLanguage = 'javascript' | 'typescript' | 'tsx' | 'python' | 'java' | 'go' | 'cpp' | 'c' | 'csharp' | 'rust' | 'ruby' | 'php';
5
- /**
6
- * AST node result with metadata
7
- */
8
- export interface ASTNodeResult {
9
- name: string;
10
- type: string;
11
- startPosition: {
12
- line: number;
13
- column: number;
14
- };
15
- endPosition: {
16
- line: number;
17
- column: number;
18
- };
19
- text: string;
20
- language: SupportedLanguage;
21
- }
22
- /**
23
- * Multi-language AST parser using tree-sitter
24
- * Supports JavaScript, TypeScript, Python, Java, Go, C/C++, C#, Rust, Ruby, PHP
25
- */
26
- export declare class MultiLanguageASTParser {
27
- private parsers;
28
- private languageConfigs;
29
- constructor();
30
- /**
31
- * Initialize language configurations
32
- */
33
- private initializeLanguageConfigs;
34
- /**
35
- * Initialize parsers for all supported languages
36
- */
37
- private initializeParsers;
38
- /**
39
- * Detect language from file extension
40
- */
41
- detectLanguage(filePath: string): SupportedLanguage | null;
42
- /**
43
- * Parse source code and search for nodes matching the query
44
- */
45
- searchAST(sourceCode: string, filePath: string, query: string, caseSensitive?: boolean): ASTNodeResult[];
46
- /**
47
- * Extract the name/identifier from an AST node based on language
48
- */
49
- private extractNodeName;
50
- /**
51
- * Recursively find the first identifier node
52
- */
53
- private findIdentifier;
54
- /**
55
- * Get supported file extensions
56
- */
57
- getSupportedExtensions(): string[];
58
- /**
59
- * Check if a file is supported for AST parsing
60
- */
61
- isSupported(filePath: string): boolean;
62
- /**
63
- * Get node types for a specific language
64
- */
65
- getNodeTypes(language: SupportedLanguage): string[];
66
- }
67
- export declare const multiLanguageASTParser: MultiLanguageASTParser;
@@ -1,360 +0,0 @@
1
- import Parser from 'tree-sitter';
2
- import JavaScript from 'tree-sitter-javascript';
3
- import TypeScript from 'tree-sitter-typescript';
4
- import Python from 'tree-sitter-python';
5
- import Java from 'tree-sitter-java';
6
- import Go from 'tree-sitter-go';
7
- import Cpp from 'tree-sitter-cpp';
8
- import C from 'tree-sitter-c';
9
- import CSharp from 'tree-sitter-c-sharp';
10
- import Rust from 'tree-sitter-rust';
11
- import Ruby from 'tree-sitter-ruby';
12
- import PHP from 'tree-sitter-php';
13
- /**
14
- * Multi-language AST parser using tree-sitter
15
- * Supports JavaScript, TypeScript, Python, Java, Go, C/C++, C#, Rust, Ruby, PHP
16
- */
17
- export class MultiLanguageASTParser {
18
- constructor() {
19
- Object.defineProperty(this, "parsers", {
20
- enumerable: true,
21
- configurable: true,
22
- writable: true,
23
- value: new Map()
24
- });
25
- Object.defineProperty(this, "languageConfigs", {
26
- enumerable: true,
27
- configurable: true,
28
- writable: true,
29
- value: new Map()
30
- });
31
- this.initializeLanguageConfigs();
32
- this.initializeParsers();
33
- }
34
- /**
35
- * Initialize language configurations
36
- */
37
- initializeLanguageConfigs() {
38
- // JavaScript
39
- this.languageConfigs.set('javascript', {
40
- extensions: ['.js', '.jsx', '.mjs', '.cjs'],
41
- parser: JavaScript,
42
- nodeTypes: [
43
- 'function_declaration',
44
- 'arrow_function',
45
- 'function_expression',
46
- 'class_declaration',
47
- 'method_definition',
48
- 'variable_declarator',
49
- 'lexical_declaration',
50
- ],
51
- });
52
- // TypeScript
53
- this.languageConfigs.set('typescript', {
54
- extensions: ['.ts'],
55
- parser: TypeScript.typescript,
56
- nodeTypes: [
57
- 'function_declaration',
58
- 'arrow_function',
59
- 'function_expression',
60
- 'class_declaration',
61
- 'method_definition',
62
- 'interface_declaration',
63
- 'type_alias_declaration',
64
- 'enum_declaration',
65
- 'variable_declarator',
66
- 'lexical_declaration',
67
- ],
68
- });
69
- // TSX
70
- this.languageConfigs.set('tsx', {
71
- extensions: ['.tsx'],
72
- parser: TypeScript.tsx,
73
- nodeTypes: [
74
- 'function_declaration',
75
- 'arrow_function',
76
- 'function_expression',
77
- 'class_declaration',
78
- 'method_definition',
79
- 'interface_declaration',
80
- 'type_alias_declaration',
81
- 'enum_declaration',
82
- 'variable_declarator',
83
- 'lexical_declaration',
84
- ],
85
- });
86
- // Python
87
- this.languageConfigs.set('python', {
88
- extensions: ['.py', '.pyw'],
89
- parser: Python,
90
- nodeTypes: [
91
- 'function_definition',
92
- 'class_definition',
93
- 'decorated_definition',
94
- 'assignment',
95
- ],
96
- });
97
- // Java
98
- this.languageConfigs.set('java', {
99
- extensions: ['.java'],
100
- parser: Java,
101
- nodeTypes: [
102
- 'method_declaration',
103
- 'class_declaration',
104
- 'interface_declaration',
105
- 'enum_declaration',
106
- 'constructor_declaration',
107
- 'field_declaration',
108
- ],
109
- });
110
- // Go
111
- this.languageConfigs.set('go', {
112
- extensions: ['.go'],
113
- parser: Go,
114
- nodeTypes: [
115
- 'function_declaration',
116
- 'method_declaration',
117
- 'type_declaration',
118
- 'type_spec',
119
- 'var_declaration',
120
- 'const_declaration',
121
- ],
122
- });
123
- // C++
124
- this.languageConfigs.set('cpp', {
125
- extensions: ['.cpp', '.cc', '.cxx', '.hpp', '.hxx', '.h'],
126
- parser: Cpp,
127
- nodeTypes: [
128
- 'function_definition',
129
- 'function_declarator',
130
- 'class_specifier',
131
- 'struct_specifier',
132
- 'enum_specifier',
133
- 'namespace_definition',
134
- 'declaration',
135
- ],
136
- });
137
- // C
138
- this.languageConfigs.set('c', {
139
- extensions: ['.c', '.h'],
140
- parser: C,
141
- nodeTypes: [
142
- 'function_definition',
143
- 'function_declarator',
144
- 'struct_specifier',
145
- 'enum_specifier',
146
- 'declaration',
147
- ],
148
- });
149
- // C#
150
- this.languageConfigs.set('csharp', {
151
- extensions: ['.cs'],
152
- parser: CSharp,
153
- nodeTypes: [
154
- 'method_declaration',
155
- 'class_declaration',
156
- 'interface_declaration',
157
- 'struct_declaration',
158
- 'enum_declaration',
159
- 'property_declaration',
160
- 'field_declaration',
161
- 'constructor_declaration',
162
- ],
163
- });
164
- // Rust
165
- this.languageConfigs.set('rust', {
166
- extensions: ['.rs'],
167
- parser: Rust,
168
- nodeTypes: [
169
- 'function_item',
170
- 'struct_item',
171
- 'enum_item',
172
- 'trait_item',
173
- 'impl_item',
174
- 'mod_item',
175
- 'const_item',
176
- 'static_item',
177
- ],
178
- });
179
- // Ruby
180
- this.languageConfigs.set('ruby', {
181
- extensions: ['.rb'],
182
- parser: Ruby,
183
- nodeTypes: [
184
- 'method',
185
- 'singleton_method',
186
- 'class',
187
- 'module',
188
- 'assignment',
189
- ],
190
- });
191
- // PHP
192
- this.languageConfigs.set('php', {
193
- extensions: ['.php'],
194
- parser: PHP.php,
195
- nodeTypes: [
196
- 'function_definition',
197
- 'method_declaration',
198
- 'class_declaration',
199
- 'interface_declaration',
200
- 'trait_declaration',
201
- 'property_declaration',
202
- ],
203
- });
204
- }
205
- /**
206
- * Initialize parsers for all supported languages
207
- */
208
- initializeParsers() {
209
- for (const [language, config] of this.languageConfigs.entries()) {
210
- try {
211
- const parser = new Parser();
212
- parser.setLanguage(config.parser);
213
- this.parsers.set(language, parser);
214
- }
215
- catch (error) {
216
- console.error(`Failed to initialize parser for ${language}:`, error instanceof Error ? error.message : 'Unknown error');
217
- }
218
- }
219
- }
220
- /**
221
- * Detect language from file extension
222
- */
223
- detectLanguage(filePath) {
224
- const ext = filePath.substring(filePath.lastIndexOf('.')).toLowerCase();
225
- for (const [language, config] of this.languageConfigs.entries()) {
226
- if (config.extensions.includes(ext)) {
227
- return language;
228
- }
229
- }
230
- return null;
231
- }
232
- /**
233
- * Parse source code and search for nodes matching the query
234
- */
235
- searchAST(sourceCode, filePath, query, caseSensitive = false) {
236
- const language = this.detectLanguage(filePath);
237
- if (!language) {
238
- return [];
239
- }
240
- const parser = this.parsers.get(language);
241
- if (!parser) {
242
- return [];
243
- }
244
- try {
245
- const tree = parser.parse(sourceCode);
246
- const results = [];
247
- const searchQuery = caseSensitive ? query : query.toLowerCase();
248
- // Traverse the AST
249
- const traverse = (node) => {
250
- const nodeType = node.type;
251
- const config = this.languageConfigs.get(language);
252
- // Check if this is a node type we're interested in
253
- if (config && config.nodeTypes.includes(nodeType)) {
254
- const nodeName = this.extractNodeName(node, language);
255
- if (nodeName) {
256
- const nameToCheck = caseSensitive
257
- ? nodeName
258
- : nodeName.toLowerCase();
259
- if (nameToCheck.includes(searchQuery)) {
260
- results.push({
261
- name: nodeName,
262
- type: nodeType,
263
- startPosition: {
264
- line: node.startPosition.row + 1,
265
- column: node.startPosition.column + 1,
266
- },
267
- endPosition: {
268
- line: node.endPosition.row + 1,
269
- column: node.endPosition.column + 1,
270
- },
271
- text: node.text,
272
- language,
273
- });
274
- }
275
- }
276
- }
277
- // Recursively traverse children
278
- for (let i = 0; i < node.childCount; i++) {
279
- const child = node.child(i);
280
- if (child) {
281
- traverse(child);
282
- }
283
- }
284
- };
285
- traverse(tree.rootNode);
286
- return results;
287
- }
288
- catch (error) {
289
- console.error(`AST parsing error for ${filePath}:`, error instanceof Error ? error.message : 'Unknown error');
290
- return [];
291
- }
292
- }
293
- /**
294
- * Extract the name/identifier from an AST node based on language
295
- */
296
- extractNodeName(node, _language) {
297
- // Common patterns for extracting names from different node types
298
- const nameFields = ['name', 'identifier', 'declarator', 'property'];
299
- for (const field of nameFields) {
300
- const nameNode = node.childForFieldName(field);
301
- if (nameNode) {
302
- // For some languages, we need to go deeper
303
- if (nameNode.type === 'identifier') {
304
- return nameNode.text;
305
- }
306
- // Try to find identifier in children
307
- const identifierChild = this.findIdentifier(nameNode);
308
- if (identifierChild) {
309
- return identifierChild.text;
310
- }
311
- }
312
- }
313
- // Fallback: try to find any identifier child
314
- const identifier = this.findIdentifier(node);
315
- return identifier ? identifier.text : null;
316
- }
317
- /**
318
- * Recursively find the first identifier node
319
- */
320
- findIdentifier(node) {
321
- if (node.type === 'identifier') {
322
- return node;
323
- }
324
- for (let i = 0; i < node.childCount; i++) {
325
- const child = node.child(i);
326
- if (child) {
327
- const identifier = this.findIdentifier(child);
328
- if (identifier) {
329
- return identifier;
330
- }
331
- }
332
- }
333
- return null;
334
- }
335
- /**
336
- * Get supported file extensions
337
- */
338
- getSupportedExtensions() {
339
- const extensions = [];
340
- for (const config of this.languageConfigs.values()) {
341
- extensions.push(...config.extensions);
342
- }
343
- return [...new Set(extensions)];
344
- }
345
- /**
346
- * Check if a file is supported for AST parsing
347
- */
348
- isSupported(filePath) {
349
- return this.detectLanguage(filePath) !== null;
350
- }
351
- /**
352
- * Get node types for a specific language
353
- */
354
- getNodeTypes(language) {
355
- const config = this.languageConfigs.get(language);
356
- return config ? config.nodeTypes : [];
357
- }
358
- }
359
- // Export singleton instance
360
- export const multiLanguageASTParser = new MultiLanguageASTParser();