snow-ai 0.2.12 → 0.2.13
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/api/anthropic.js +15 -4
- package/dist/api/systemPrompt.d.ts +1 -1
- package/dist/api/systemPrompt.js +149 -40
- package/dist/hooks/useConversation.d.ts +1 -1
- package/dist/hooks/useConversation.js +5 -3
- package/dist/hooks/useGlobalNavigation.js +2 -0
- package/dist/hooks/useToolConfirmation.d.ts +2 -1
- package/dist/hooks/useToolConfirmation.js +2 -1
- package/dist/mcp/filesystem.d.ts +16 -1
- package/dist/mcp/filesystem.js +193 -89
- package/dist/mcp/multiLanguageASTParser.d.ts +67 -0
- package/dist/mcp/multiLanguageASTParser.js +360 -0
- package/dist/mcp/todo.d.ts +1 -1
- package/dist/mcp/todo.js +21 -26
- package/dist/ui/components/ChatInput.d.ts +1 -1
- package/dist/ui/components/ChatInput.js +84 -45
- package/dist/ui/components/DiffViewer.d.ts +1 -2
- package/dist/ui/components/DiffViewer.js +65 -65
- package/dist/ui/components/MCPInfoPanel.js +1 -2
- package/dist/ui/components/TodoTree.js +1 -1
- package/dist/ui/components/ToolConfirmation.d.ts +11 -1
- package/dist/ui/components/ToolConfirmation.js +86 -6
- package/dist/ui/pages/ChatScreen.js +223 -111
- package/dist/utils/commands/ide.js +18 -1
- package/dist/utils/mcpToolsManager.d.ts +1 -1
- package/dist/utils/mcpToolsManager.js +45 -36
- package/dist/utils/textBuffer.d.ts +5 -0
- package/dist/utils/textBuffer.js +23 -2
- package/dist/utils/vscodeConnection.js +10 -1
- package/package.json +13 -1
- package/readme.md +12 -2
|
@@ -0,0 +1,360 @@
|
|
|
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();
|
package/dist/mcp/todo.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Tool, type CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
|
2
2
|
interface TodoItem {
|
|
3
3
|
id: string;
|
|
4
4
|
content: string;
|
|
5
|
-
status: 'pending' | '
|
|
5
|
+
status: 'pending' | 'completed';
|
|
6
6
|
createdAt: string;
|
|
7
7
|
updatedAt: string;
|
|
8
8
|
parentId?: string;
|
package/dist/mcp/todo.js
CHANGED
|
@@ -190,35 +190,30 @@ Complete TODO list with all task IDs, content, status, and hierarchy.`,
|
|
|
190
190
|
},
|
|
191
191
|
{
|
|
192
192
|
name: 'todo-update',
|
|
193
|
-
description: `Update TODO status - USE
|
|
193
|
+
description: `Update TODO status or content - USE ONLY WHEN COMPLETING TASKS.
|
|
194
194
|
|
|
195
|
-
## CORE PRINCIPLE - WORK FIRST, UPDATES
|
|
196
|
-
|
|
195
|
+
## CORE PRINCIPLE - WORK FIRST, UPDATES LAST:
|
|
196
|
+
Focus on COMPLETING TASKS, not updating status. Only update TODO when a task is 100% finished and verified.
|
|
197
197
|
|
|
198
|
-
##
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
3. **Natural breakpoints**: When you finish a logical chunk of work
|
|
198
|
+
## SIMPLIFIED STATUS MODEL:
|
|
199
|
+
- **pending**: Task not yet completed (default)
|
|
200
|
+
- **completed**: Task is 100% finished and verified
|
|
202
201
|
|
|
203
|
-
## WHEN
|
|
204
|
-
|
|
205
|
-
-
|
|
206
|
-
-
|
|
207
|
-
-
|
|
208
|
-
|
|
209
|
-
## SIMPLE RULES:
|
|
210
|
-
- Keep MAXIMUM one task as "in_progress" (don't over-track)
|
|
211
|
-
- Mark "completed" only when 100% done (no partial credit)
|
|
212
|
-
- If you're spending more time updating TODO than working, you're doing it wrong
|
|
202
|
+
## WHEN TO UPDATE:
|
|
203
|
+
✅ **Mark "completed"** ONLY when:
|
|
204
|
+
- Task is 100% finished (no partial work)
|
|
205
|
+
- Tests/builds passed (if applicable)
|
|
206
|
+
- No errors or blockers
|
|
207
|
+
- You've actually verified it works
|
|
213
208
|
|
|
214
|
-
##
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
- You've actually verified it works
|
|
209
|
+
## WHEN NOT TO UPDATE:
|
|
210
|
+
❌ Don't update status to track "in progress" - just do the work
|
|
211
|
+
❌ Don't update multiple times per task - once when done is enough
|
|
212
|
+
❌ Don't update before verifying the work is complete
|
|
213
|
+
❌ Don't update content unless there's a genuine error in the description
|
|
220
214
|
|
|
221
|
-
|
|
215
|
+
## BEST PRACTICE:
|
|
216
|
+
Complete 3-5 tasks, then batch update them all to "completed" at once. This is more efficient than constant status updates.`,
|
|
222
217
|
inputSchema: {
|
|
223
218
|
type: 'object',
|
|
224
219
|
properties: {
|
|
@@ -228,8 +223,8 @@ If blocked, keep as "in_progress" and report the blocker (don't create elaborate
|
|
|
228
223
|
},
|
|
229
224
|
status: {
|
|
230
225
|
type: 'string',
|
|
231
|
-
enum: ['pending', '
|
|
232
|
-
description: 'New status -
|
|
226
|
+
enum: ['pending', 'completed'],
|
|
227
|
+
description: 'New status - "pending" (not done) or "completed" (100% finished and verified)',
|
|
233
228
|
},
|
|
234
229
|
content: {
|
|
235
230
|
type: 'string',
|
|
@@ -22,5 +22,5 @@ type Props = {
|
|
|
22
22
|
};
|
|
23
23
|
snapshotFileCount?: Map<number, number>;
|
|
24
24
|
};
|
|
25
|
-
export default function ChatInput({ onSubmit, onCommand, placeholder, disabled, chatHistory, onHistorySelect, yoloMode, contextUsage, snapshotFileCount }: Props): React.JSX.Element;
|
|
25
|
+
export default function ChatInput({ onSubmit, onCommand, placeholder, disabled, chatHistory, onHistorySelect, yoloMode, contextUsage, snapshotFileCount, }: Props): React.JSX.Element;
|
|
26
26
|
export {};
|