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.
@@ -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();
@@ -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' | 'in_progress' | 'completed';
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 SPARINGLY, focus on actual work instead.
193
+ description: `Update TODO status or content - USE ONLY WHEN COMPLETING TASKS.
194
194
 
195
- ## CORE PRINCIPLE - WORK FIRST, UPDATES SECOND:
196
- Prioritize COMPLETING TASKS over updating TODO status. Update TODO only at natural breakpoints, not constantly. It's better to finish 3 tasks and update once than to update TODO 10 times while making slow progress.
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
- ## WHEN TO UPDATE (Sparingly):
199
- 1. **Starting a major task**: Mark "in_progress" when beginning significant work (not for every micro-step)
200
- 2. **Completing a major task**: Mark "completed" ONLY when task is 100% done and verified
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 NOT TO UPDATE:
204
- - Every few minutes during work (you're wasting time on bookkeeping)
205
- - Multiple updates for sub-steps of one task (just finish the task first)
206
- - Immediately after starting (start working first, update later if it's a long task)
207
- - Before verifying the work is actually complete
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
- ## HONEST COMPLETION CRITERIA:
215
- Only mark complete if:
216
- - Task is 100% finished (no partial work)
217
- - Tests/builds passed (if applicable)
218
- - No errors or blockers
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
- If blocked, keep as "in_progress" and report the blocker (don't create elaborate sub-TODO structures).`,
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', 'in_progress', 'completed'],
232
- description: 'New status - follow strict rules: "in_progress" when starting, "completed" when 100% done and verified, "pending" if not started',
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 {};