snow-flow 8.37.27 → 8.38.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.
Files changed (41) hide show
  1. package/.snow-code/agent/deployment-specialist.md +346 -0
  2. package/.snow-code/agent/orchestrator.md +286 -0
  3. package/.snow-code/agent/risk-assessor.md +454 -0
  4. package/.snow-code/agent/solution-architect.md +582 -0
  5. package/.snow-code/agent/validator.md +503 -0
  6. package/.snow-code/opencode.json +49 -0
  7. package/README.md +16 -0
  8. package/dist/cli.d.ts.map +1 -1
  9. package/dist/cli.js +93 -256
  10. package/dist/cli.js.map +1 -1
  11. package/dist/utils/sync-mcp-configs.d.ts +7 -5
  12. package/dist/utils/sync-mcp-configs.d.ts.map +1 -1
  13. package/dist/utils/sync-mcp-configs.js +19 -74
  14. package/dist/utils/sync-mcp-configs.js.map +1 -1
  15. package/package.json +2 -3
  16. package/scripts/check-binary-updates.js +0 -169
  17. package/scripts/check-npm-version.js +0 -92
  18. package/scripts/classify-all-tools.ts +0 -446
  19. package/scripts/classify-edge-cases.ts +0 -275
  20. package/scripts/classify-operations-tools.sh +0 -96
  21. package/scripts/cleanup-mcp-servers.js +0 -115
  22. package/scripts/diagnose-mcp.js +0 -299
  23. package/scripts/generate-mcp-config.js +0 -45
  24. package/scripts/mcp-server-manager.sh +0 -320
  25. package/scripts/postinstall.js +0 -75
  26. package/scripts/reset-mcp-servers.js +0 -266
  27. package/scripts/safe-mcp-cleanup.js +0 -151
  28. package/scripts/setup-mcp.js +0 -106
  29. package/scripts/start-mcp-proper.js +0 -76
  30. package/scripts/start-snowcode.sh +0 -123
  31. package/scripts/start-sysprops-mcp.js +0 -43
  32. package/scripts/sync-snow-code-version.js +0 -74
  33. package/scripts/test-auth-flow.js +0 -172
  34. package/scripts/test-auth-location-fix.js +0 -84
  35. package/scripts/test-mcp-manual.js +0 -140
  36. package/scripts/test-todowrite-timeout.js +0 -108
  37. package/scripts/update-dependencies.js +0 -90
  38. package/scripts/update-mcp-config.js +0 -96
  39. package/scripts/update-snow-code.js +0 -146
  40. package/scripts/verify-snowcode-fork.sh +0 -141
  41. package/templates/snow-code-package.json +0 -3
@@ -1,446 +0,0 @@
1
- #!/usr/bin/env tsx
2
-
3
- /**
4
- * Bulk Tool Classification Script
5
- *
6
- * Automatically classifies ALL 410+ tools in the unified MCP server
7
- * as READ or WRITE based on intelligent name pattern analysis.
8
- *
9
- * Usage:
10
- * npm install -g tsx # If not installed
11
- * tsx scripts/classify-all-tools.ts
12
- * tsx scripts/classify-all-tools.ts --dry-run # Preview without changes
13
- * tsx scripts/classify-all-tools.ts --review-only # Only show tools needing manual review
14
- */
15
-
16
- import * as fs from 'fs';
17
- import * as path from 'path';
18
- import { glob } from 'glob';
19
-
20
- // Configuration
21
- const TOOLS_BASE_DIR = path.join(__dirname, '../src/mcp/servicenow-mcp-unified/tools');
22
- const DRY_RUN = process.argv.includes('--dry-run');
23
- const REVIEW_ONLY = process.argv.includes('--review-only');
24
-
25
- // Classification patterns
26
- const READ_PATTERNS = [
27
- /^snow_query_/,
28
- /^snow_get_/,
29
- /^snow_search_/,
30
- /^snow_discover_/,
31
- /^snow_find_/,
32
- /^snow_list_/,
33
- /^snow_view_/,
34
- /^snow_show_/,
35
- /^snow_analyze_/,
36
- /^snow_check_/,
37
- /^snow_test_/,
38
- /^snow_validate_/,
39
- /^snow_export_(?!.*import)/, // export is READ unless it's import_export
40
- /^snow_fetch_/,
41
- /^snow_lookup_/,
42
- /^snow_inspect_/,
43
- /^snow_monitor_/,
44
- /_lookup$/,
45
- /_search$/,
46
- /_query$/,
47
- /_details$/,
48
- /_status$/,
49
- /_metrics$/,
50
- /_report$/,
51
- /_analysis$/,
52
- ];
53
-
54
- const WRITE_PATTERNS = [
55
- /^snow_create_/,
56
- /^snow_update_/,
57
- /^snow_delete_/,
58
- /^snow_remove_/,
59
- /^snow_execute_/,
60
- /^snow_deploy_/,
61
- /^snow_manage_/,
62
- /^snow_add_/,
63
- /^snow_set_/,
64
- /^snow_configure_/,
65
- /^snow_trigger_/,
66
- /^snow_schedule_/,
67
- /^snow_enable_/,
68
- /^snow_disable_/,
69
- /^snow_activate_/,
70
- /^snow_deactivate_/,
71
- /^snow_install_/,
72
- /^snow_uninstall_/,
73
- /^snow_import_/,
74
- /^snow_sync_/,
75
- /^snow_push_/,
76
- /^snow_pull_/, // pull modifies local state
77
- /^snow_apply_/,
78
- /^snow_assign_/,
79
- /^snow_approve_/,
80
- /^snow_reject_/,
81
- /^snow_close_/,
82
- /^snow_resolve_/,
83
- /^snow_reopen_/,
84
- /^snow_cancel_/,
85
- /^snow_rollback_/,
86
- /^snow_clone_/,
87
- /^snow_backup_/,
88
- /^snow_restore_/,
89
- /^snow_migrate_/,
90
- /^snow_transfer_/,
91
- /^snow_retire_/,
92
- /^snow_attach_/,
93
- /^snow_upload_/,
94
- /^snow_order_/,
95
- /^snow_request_/,
96
- /^snow_confirm_/,
97
- /^snow_cleanup_/,
98
- /_manage$/,
99
- /_manager$/,
100
- ];
101
-
102
- // Edge cases that need manual review
103
- const AMBIGUOUS_PATTERNS = [
104
- /^snow_record_manage$/, // Can be both READ and WRITE depending on action
105
- /^snow_property_manager$/, // Can be both
106
- /^snow_catalog_item_manager$/, // Can be both
107
- ];
108
-
109
- interface ToolClassification {
110
- filePath: string;
111
- toolName: string;
112
- currentPermission: string | null;
113
- suggestedPermission: 'read' | 'write' | 'NEEDS_REVIEW';
114
- suggestedRoles: string[];
115
- confidence: 'high' | 'medium' | 'low';
116
- reason: string;
117
- alreadyClassified: boolean;
118
- }
119
-
120
- interface ClassificationStats {
121
- total: number;
122
- alreadyClassified: number;
123
- read: number;
124
- write: number;
125
- needsReview: number;
126
- updated: number;
127
- errors: number;
128
- }
129
-
130
- /**
131
- * Classify a tool based on its name
132
- */
133
- function classifyTool(toolName: string): ToolClassification['suggestedPermission'] {
134
- // Check ambiguous patterns first
135
- for (const pattern of AMBIGUOUS_PATTERNS) {
136
- if (pattern.test(toolName)) {
137
- return 'NEEDS_REVIEW';
138
- }
139
- }
140
-
141
- // Check READ patterns
142
- let readMatches = 0;
143
- for (const pattern of READ_PATTERNS) {
144
- if (pattern.test(toolName)) {
145
- readMatches++;
146
- }
147
- }
148
-
149
- // Check WRITE patterns
150
- let writeMatches = 0;
151
- for (const pattern of WRITE_PATTERNS) {
152
- if (pattern.test(toolName)) {
153
- writeMatches++;
154
- }
155
- }
156
-
157
- // If matches both, prefer WRITE (most restrictive)
158
- if (writeMatches > 0) return 'write';
159
- if (readMatches > 0) return 'read';
160
-
161
- // No pattern matches - needs manual review
162
- return 'NEEDS_REVIEW';
163
- }
164
-
165
- /**
166
- * Get classification reason
167
- */
168
- function getClassificationReason(toolName: string, permission: ToolClassification['suggestedPermission']): string {
169
- if (permission === 'NEEDS_REVIEW') {
170
- return 'No clear pattern match - manual review required';
171
- }
172
-
173
- if (permission === 'read') {
174
- if (toolName.includes('query')) return 'Query operation - only reads data';
175
- if (toolName.includes('get')) return 'Get operation - retrieves data';
176
- if (toolName.includes('search')) return 'Search operation - reads data';
177
- if (toolName.includes('discover')) return 'Discovery operation - reads metadata';
178
- if (toolName.includes('analyze')) return 'Analysis operation - reads data';
179
- if (toolName.includes('export')) return 'Export operation - reads data';
180
- return 'Read-only operation based on name pattern';
181
- }
182
-
183
- if (permission === 'write') {
184
- if (toolName.includes('create')) return 'Create operation - modifies data';
185
- if (toolName.includes('update')) return 'Update operation - modifies data';
186
- if (toolName.includes('delete')) return 'Delete operation - modifies data';
187
- if (toolName.includes('execute')) return 'Execution operation - can have side effects';
188
- if (toolName.includes('deploy')) return 'Deployment operation - modifies state';
189
- if (toolName.includes('manage')) return 'Management operation - modifies data';
190
- return 'Write operation based on name pattern';
191
- }
192
-
193
- return 'Unknown';
194
- }
195
-
196
- /**
197
- * Get confidence level
198
- */
199
- function getConfidence(toolName: string, permission: ToolClassification['suggestedPermission']): 'high' | 'medium' | 'low' {
200
- if (permission === 'NEEDS_REVIEW') return 'low';
201
-
202
- // High confidence patterns
203
- const highConfidencePatterns = [
204
- /^snow_query_/,
205
- /^snow_create_/,
206
- /^snow_update_/,
207
- /^snow_delete_/,
208
- /^snow_execute_/,
209
- ];
210
-
211
- for (const pattern of highConfidencePatterns) {
212
- if (pattern.test(toolName)) return 'high';
213
- }
214
-
215
- // Medium confidence for other clear patterns
216
- if (permission === 'read' && (toolName.includes('get') || toolName.includes('search'))) return 'high';
217
- if (permission === 'write' && (toolName.includes('deploy') || toolName.includes('configure'))) return 'high';
218
-
219
- return 'medium';
220
- }
221
-
222
- /**
223
- * Check if tool is already classified
224
- */
225
- function isAlreadyClassified(fileContent: string): boolean {
226
- return fileContent.includes('permission:') && fileContent.includes('allowedRoles:');
227
- }
228
-
229
- /**
230
- * Get current permission from file
231
- */
232
- function getCurrentPermission(fileContent: string): string | null {
233
- const match = fileContent.match(/permission:\s*['"](\w+)['"]/);
234
- return match ? match[1] : null;
235
- }
236
-
237
- /**
238
- * Add permission fields to tool file
239
- */
240
- function addPermissionFields(
241
- filePath: string,
242
- permission: 'read' | 'write',
243
- reason: string
244
- ): boolean {
245
- try {
246
- let content = fs.readFileSync(filePath, 'utf-8');
247
-
248
- // Check if already has permission
249
- if (isAlreadyClassified(content)) {
250
- return false; // Already classified
251
- }
252
-
253
- // Find the insertion point (after frequency field)
254
- const frequencyMatch = content.match(/frequency:\s*['"][\w-]+['"],?/);
255
-
256
- if (!frequencyMatch) {
257
- console.error(` āš ļø Could not find frequency field in ${path.basename(filePath)}`);
258
- return false;
259
- }
260
-
261
- const roles = permission === 'read'
262
- ? "['developer', 'stakeholder', 'admin']"
263
- : "['developer', 'admin']";
264
-
265
- const permissionBlock = `\n\n // šŸ†• Permission enforcement (Q1 2025)\n` +
266
- ` // Classification: ${permission.toUpperCase()} - ${reason}\n` +
267
- ` permission: '${permission}',\n` +
268
- ` allowedRoles: ${roles},`;
269
-
270
- // Insert after frequency field
271
- const insertIndex = frequencyMatch.index! + frequencyMatch[0].length;
272
- content = content.slice(0, insertIndex) + permissionBlock + content.slice(insertIndex);
273
-
274
- if (!DRY_RUN) {
275
- fs.writeFileSync(filePath, content, 'utf-8');
276
- }
277
-
278
- return true;
279
- } catch (error) {
280
- console.error(` āŒ Error updating ${path.basename(filePath)}:`, error);
281
- return false;
282
- }
283
- }
284
-
285
- /**
286
- * Scan and classify all tools
287
- */
288
- async function classifyAllTools(): Promise<void> {
289
- console.log('šŸ” Scanning for tools in unified MCP server...\n');
290
-
291
- // Find all tool files (excluding index.ts)
292
- const toolFiles = await glob(`${TOOLS_BASE_DIR}/**/*.ts`, {
293
- ignore: ['**/index.ts', '**/*.test.ts', '**/*.spec.ts']
294
- });
295
-
296
- console.log(`šŸ“¦ Found ${toolFiles.length} tool files\n`);
297
-
298
- const classifications: ToolClassification[] = [];
299
- const stats: ClassificationStats = {
300
- total: toolFiles.length,
301
- alreadyClassified: 0,
302
- read: 0,
303
- write: 0,
304
- needsReview: 0,
305
- updated: 0,
306
- errors: 0
307
- };
308
-
309
- // Classify each tool
310
- for (const filePath of toolFiles) {
311
- const toolName = path.basename(filePath, '.ts');
312
- const fileContent = fs.readFileSync(filePath, 'utf-8');
313
-
314
- const alreadyClassified = isAlreadyClassified(fileContent);
315
- const currentPermission = getCurrentPermission(fileContent);
316
- const suggestedPermission = classifyTool(toolName);
317
- const confidence = getConfidence(toolName, suggestedPermission);
318
- const reason = getClassificationReason(toolName, suggestedPermission);
319
-
320
- const roles = suggestedPermission === 'read'
321
- ? ['developer', 'stakeholder', 'admin']
322
- : suggestedPermission === 'write'
323
- ? ['developer', 'admin']
324
- : [];
325
-
326
- classifications.push({
327
- filePath,
328
- toolName,
329
- currentPermission,
330
- suggestedPermission,
331
- suggestedRoles: roles,
332
- confidence,
333
- reason,
334
- alreadyClassified
335
- });
336
-
337
- if (alreadyClassified) {
338
- stats.alreadyClassified++;
339
- } else {
340
- if (suggestedPermission === 'read') stats.read++;
341
- else if (suggestedPermission === 'write') stats.write++;
342
- else stats.needsReview++;
343
- }
344
- }
345
-
346
- // Sort by category
347
- const needsReview = classifications.filter(c => !c.alreadyClassified && c.suggestedPermission === 'NEEDS_REVIEW');
348
- const readTools = classifications.filter(c => !c.alreadyClassified && c.suggestedPermission === 'read');
349
- const writeTools = classifications.filter(c => !c.alreadyClassified && c.suggestedPermission === 'write');
350
- const alreadyDone = classifications.filter(c => c.alreadyClassified);
351
-
352
- // Display results
353
- if (REVIEW_ONLY) {
354
- console.log('šŸ” Tools Needing Manual Review:\n');
355
- for (const tool of needsReview) {
356
- console.log(` āš ļø ${tool.toolName}`);
357
- console.log(` Reason: ${tool.reason}`);
358
- console.log(` File: ${path.relative(TOOLS_BASE_DIR, tool.filePath)}\n`);
359
- }
360
- console.log(`\nšŸ“Š ${needsReview.length} tools need manual review\n`);
361
- return;
362
- }
363
-
364
- console.log('šŸ“‹ Classification Summary:\n');
365
- console.log(` āœ… Already classified: ${stats.alreadyClassified}`);
366
- console.log(` šŸ“– READ tools to classify: ${stats.read}`);
367
- console.log(` āœļø WRITE tools to classify: ${stats.write}`);
368
- console.log(` āš ļø Need manual review: ${stats.needsReview}`);
369
- console.log(`\n šŸ“¦ Total: ${stats.total} tools\n`);
370
-
371
- if (needsReview.length > 0) {
372
- console.log('āš ļø Tools Needing Manual Review:\n');
373
- for (const tool of needsReview.slice(0, 10)) {
374
- console.log(` • ${tool.toolName} - ${tool.reason}`);
375
- }
376
- if (needsReview.length > 10) {
377
- console.log(` ... and ${needsReview.length - 10} more\n`);
378
- }
379
- console.log('');
380
- }
381
-
382
- if (DRY_RUN) {
383
- console.log('šŸƒ DRY RUN MODE - No files will be modified\n');
384
- console.log('šŸ“– Sample READ tools that would be classified:\n');
385
- for (const tool of readTools.slice(0, 5)) {
386
- console.log(` āœ… ${tool.toolName} (${tool.confidence} confidence)`);
387
- console.log(` ${tool.reason}\n`);
388
- }
389
-
390
- console.log('āœļø Sample WRITE tools that would be classified:\n');
391
- for (const tool of writeTools.slice(0, 5)) {
392
- console.log(` āœ… ${tool.toolName} (${tool.confidence} confidence)`);
393
- console.log(` ${tool.reason}\n`);
394
- }
395
-
396
- console.log('šŸ’” Run without --dry-run to apply changes\n');
397
- return;
398
- }
399
-
400
- // Apply classifications
401
- console.log('šŸš€ Applying classifications...\n');
402
-
403
- for (const tool of [...readTools, ...writeTools]) {
404
- if (tool.suggestedPermission === 'NEEDS_REVIEW') continue;
405
-
406
- const updated = addPermissionFields(
407
- tool.filePath,
408
- tool.suggestedPermission,
409
- tool.reason
410
- );
411
-
412
- if (updated) {
413
- stats.updated++;
414
- console.log(` āœ… ${tool.toolName} → ${tool.suggestedPermission.toUpperCase()}`);
415
- }
416
- }
417
-
418
- console.log(`\nāœ… Successfully classified ${stats.updated} tools!\n`);
419
-
420
- if (needsReview.length > 0) {
421
- console.log(`āš ļø ${needsReview.length} tools need manual review - see above\n`);
422
- }
423
-
424
- // Generate summary report
425
- const reportPath = path.join(__dirname, '../.snow-flow/classification-report.json');
426
- const report = {
427
- timestamp: new Date().toISOString(),
428
- stats,
429
- needsReview: needsReview.map(t => ({
430
- name: t.toolName,
431
- file: path.relative(TOOLS_BASE_DIR, t.filePath),
432
- reason: t.reason
433
- }))
434
- };
435
-
436
- fs.mkdirSync(path.dirname(reportPath), { recursive: true });
437
- fs.writeFileSync(reportPath, JSON.stringify(report, null, 2));
438
-
439
- console.log(`šŸ“„ Full report saved to: ${reportPath}\n`);
440
- }
441
-
442
- // Run the script
443
- classifyAllTools().catch(error => {
444
- console.error('āŒ Fatal error:', error);
445
- process.exit(1);
446
- });