snow-flow 2.10.0 → 3.0.1

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 (65) hide show
  1. package/.mcp.json +13 -141
  2. package/.mcp.json.template +11 -25
  3. package/README.md +23 -0
  4. package/claude-flow +81 -0
  5. package/claude-flow.bat +18 -0
  6. package/claude-flow.config.json +20 -0
  7. package/claude-flow.ps1 +24 -0
  8. package/dist/agents/index.d.ts +3 -10
  9. package/dist/agents/index.js +10 -50
  10. package/dist/agents/queen-agent.d.ts +0 -2
  11. package/dist/agents/queen-agent.js +25 -42
  12. package/dist/cli.js +1 -1
  13. package/dist/mcp/servicenow-automation-mcp.js +10 -10
  14. package/dist/mcp/servicenow-deployment-mcp.js +1050 -169
  15. package/dist/mcp/servicenow-development-assistant-mcp.js +13 -65
  16. package/dist/mcp/servicenow-integration-mcp.js +10 -10
  17. package/dist/mcp/servicenow-machine-learning-mcp.js +15 -15
  18. package/dist/mcp/servicenow-operations-mcp.js +23 -23
  19. package/dist/mcp/servicenow-platform-development-mcp.js +9 -9
  20. package/dist/mcp/servicenow-reporting-analytics-mcp.js +11 -11
  21. package/dist/mcp/servicenow-security-compliance-mcp.js +11 -11
  22. package/dist/mcp/servicenow-update-set-mcp.js +9 -9
  23. package/dist/mcp/shared/reliable-memory-manager.d.ts +78 -0
  24. package/dist/mcp/shared/reliable-memory-manager.js +268 -0
  25. package/dist/mcp/snow-flow-mcp.js +348 -87
  26. package/dist/queen/agent-factory.d.ts +4 -2
  27. package/dist/queen/agent-factory.js +72 -25
  28. package/dist/services/tensorflow-ml-service.d.ts +105 -0
  29. package/dist/services/tensorflow-ml-service.js +456 -0
  30. package/dist/services/widget-deployment-service.d.ts +107 -0
  31. package/dist/services/widget-deployment-service.js +332 -0
  32. package/dist/utils/file-storage-fallback.d.ts +62 -0
  33. package/dist/utils/file-storage-fallback.js +289 -0
  34. package/dist/utils/mcp-server-manager.js +4 -7
  35. package/dist/utils/mcp-singleton-enforcer.d.ts +7 -1
  36. package/dist/utils/mcp-singleton-enforcer.js +28 -4
  37. package/dist/utils/mcp-timeout-fix.d.ts +10 -1
  38. package/dist/utils/mcp-timeout-fix.js +80 -6
  39. package/memory/agents/README.md +31 -0
  40. package/memory/claude-flow-data.json +1 -1
  41. package/memory/sessions/README.md +1 -1
  42. package/package.json +4 -2
  43. package/src/agents/README.md +192 -0
  44. package/src/health/README.md +161 -0
  45. package/src/memory/README.md +240 -0
  46. package/src/queen/README.md +403 -0
  47. package/src/schemas/deployment.schema.json +58 -0
  48. package/src/schemas/flow.schema.json +79 -0
  49. package/src/schemas/widget.schema.json +72 -0
  50. package/src/templates/base/application.template.json +45 -0
  51. package/src/templates/base/business_rule.template.json +33 -0
  52. package/src/templates/base/script_include.template.json +18 -0
  53. package/src/templates/base/table.template.json +64 -0
  54. package/src/templates/base/widget.template.json +25 -0
  55. package/src/templates/patterns/composite.incident-management.template.json +140 -0
  56. package/src/templates/patterns/widget.dashboard.template.json +238 -0
  57. package/src/templates/patterns/widget.datatable.template.json +292 -0
  58. package/.env.example +0 -64
  59. package/dist/mcp/servicenow-graph-memory-mcp.js +0 -728
  60. package/servicenow/widgets/openai_incident_classifier/client_controller.js +0 -284
  61. package/servicenow/widgets/openai_incident_classifier/server_script.js +0 -314
  62. package/servicenow/widgets/openai_incident_classifier/style.css +0 -354
  63. package/servicenow/widgets/openai_incident_classifier/template.html +0 -167
  64. package/servicenow/widgets/openai_incident_classifier/widget.json +0 -86
  65. package/test-ml-improvements.sh +0 -76
@@ -0,0 +1,238 @@
1
+ {
2
+ "type": "widget",
3
+ "name": "Dashboard Widget Template",
4
+ "description": "Template for creating dashboard widgets with charts and metrics",
5
+ "category": "patterns/dashboard",
6
+ "config": {
7
+ "name": "{{WIDGET_NAME|custom_dashboard}}",
8
+ "id": "{{WIDGET_ID|custom_dashboard}}",
9
+ "instance_id": "{{INSTANCE_ID|dashboard_}}",
10
+ "data": {
11
+ "title": "{{WIDGET_TITLE|Dashboard}}",
12
+ "short_description": "{{WIDGET_DESCRIPTION|Real-time dashboard with key metrics}}",
13
+ "roles": "{{WIDGET_ROLES|}}"
14
+ },
15
+ "options": [
16
+ {
17
+ "name": "refresh_interval",
18
+ "section": "Behavior",
19
+ "label": "Refresh Interval (seconds)",
20
+ "type": "integer",
21
+ "value": "30",
22
+ "help": "How often to refresh the dashboard data"
23
+ },
24
+ {
25
+ "name": "color_scheme",
26
+ "section": "Appearance",
27
+ "label": "Color Scheme",
28
+ "type": "choice",
29
+ "value": "default",
30
+ "choices": [
31
+ {"label": "Default", "value": "default"},
32
+ {"label": "Dark", "value": "dark"},
33
+ {"label": "High Contrast", "value": "high-contrast"}
34
+ ]
35
+ },
36
+ {
37
+ "name": "chart_type",
38
+ "section": "Appearance",
39
+ "label": "Default Chart Type",
40
+ "type": "choice",
41
+ "value": "bar",
42
+ "choices": [
43
+ {"label": "Bar Chart", "value": "bar"},
44
+ {"label": "Line Chart", "value": "line"},
45
+ {"label": "Pie Chart", "value": "pie"},
46
+ {"label": "Donut Chart", "value": "donut"}
47
+ ]
48
+ }
49
+ ],
50
+ "html": [
51
+ "<div class=\"dashboard-widget\" ng-class=\"{'dark-theme': options.color_scheme === 'dark', 'high-contrast': options.color_scheme === 'high-contrast'}\">",
52
+ " <div class=\"dashboard-header\">",
53
+ " <h2 class=\"dashboard-title\">{{data.title}}</h2>",
54
+ " <div class=\"dashboard-controls\">",
55
+ " <button class=\"btn btn-sm\" ng-click=\"c.refresh()\" title=\"Refresh\">",
56
+ " <i class=\"fa fa-refresh\" ng-class=\"{'fa-spin': c.loading}\"></i>",
57
+ " </button>",
58
+ " <button class=\"btn btn-sm\" ng-click=\"c.toggleFullscreen()\" title=\"Fullscreen\">",
59
+ " <i class=\"fa\" ng-class=\"c.fullscreen ? 'fa-compress' : 'fa-expand'\"></i>",
60
+ " </button>",
61
+ " </div>",
62
+ " </div>",
63
+ " ",
64
+ " <div class=\"dashboard-metrics\" ng-if=\"!c.loading\">",
65
+ " <div class=\"metric-card\" ng-repeat=\"metric in c.metrics\">",
66
+ " <div class=\"metric-value\" ng-style=\"{'color': metric.color}\">{{metric.value}}</div>",
67
+ " <div class=\"metric-label\">{{metric.label}}</div>",
68
+ " <div class=\"metric-trend\" ng-if=\"metric.trend\">",
69
+ " <i class=\"fa\" ng-class=\"metric.trend > 0 ? 'fa-arrow-up text-success' : 'fa-arrow-down text-danger'\"></i>",
70
+ " <span>{{metric.trend}}%</span>",
71
+ " </div>",
72
+ " </div>",
73
+ " </div>",
74
+ " ",
75
+ " <div class=\"dashboard-charts\" ng-if=\"!c.loading\">",
76
+ " <div class=\"chart-container\" ng-repeat=\"chart in c.charts\">",
77
+ " <h3>{{chart.title}}</h3>",
78
+ " <canvas id=\"chart-{{$index}}\" width=\"400\" height=\"200\"></canvas>",
79
+ " </div>",
80
+ " </div>",
81
+ " ",
82
+ " <div class=\"dashboard-loading\" ng-if=\"c.loading\">",
83
+ " <i class=\"fa fa-spinner fa-spin fa-3x\"></i>",
84
+ " <p>Loading dashboard data...</p>",
85
+ " </div>",
86
+ "</div>"
87
+ ],
88
+ "css": [
89
+ ".dashboard-widget {",
90
+ " padding: 20px;",
91
+ " background: #fff;",
92
+ " border-radius: 8px;",
93
+ " box-shadow: 0 2px 4px rgba(0,0,0,0.1);",
94
+ "}",
95
+ "",
96
+ ".dashboard-widget.dark-theme {",
97
+ " background: #1a1a1a;",
98
+ " color: #fff;",
99
+ "}",
100
+ "",
101
+ ".dashboard-widget.high-contrast {",
102
+ " border: 2px solid #000;",
103
+ "}",
104
+ "",
105
+ ".dashboard-header {",
106
+ " display: flex;",
107
+ " justify-content: space-between;",
108
+ " align-items: center;",
109
+ " margin-bottom: 20px;",
110
+ "}",
111
+ "",
112
+ ".dashboard-title {",
113
+ " margin: 0;",
114
+ " font-size: 24px;",
115
+ " font-weight: 600;",
116
+ "}",
117
+ "",
118
+ ".dashboard-controls button {",
119
+ " margin-left: 10px;",
120
+ "}",
121
+ "",
122
+ ".dashboard-metrics {",
123
+ " display: grid;",
124
+ " grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));",
125
+ " gap: 20px;",
126
+ " margin-bottom: 30px;",
127
+ "}",
128
+ "",
129
+ ".metric-card {",
130
+ " background: #f5f5f5;",
131
+ " padding: 20px;",
132
+ " border-radius: 8px;",
133
+ " text-align: center;",
134
+ " transition: transform 0.2s;",
135
+ "}",
136
+ "",
137
+ ".dark-theme .metric-card {",
138
+ " background: #2a2a2a;",
139
+ "}",
140
+ "",
141
+ ".metric-card:hover {",
142
+ " transform: translateY(-2px);",
143
+ " box-shadow: 0 4px 8px rgba(0,0,0,0.1);",
144
+ "}",
145
+ "",
146
+ ".metric-value {",
147
+ " font-size: 36px;",
148
+ " font-weight: bold;",
149
+ " margin-bottom: 5px;",
150
+ "}",
151
+ "",
152
+ ".metric-label {",
153
+ " font-size: 14px;",
154
+ " color: #666;",
155
+ " text-transform: uppercase;",
156
+ "}",
157
+ "",
158
+ ".dark-theme .metric-label {",
159
+ " color: #999;",
160
+ "}",
161
+ "",
162
+ ".metric-trend {",
163
+ " margin-top: 10px;",
164
+ " font-size: 14px;",
165
+ "}",
166
+ "",
167
+ ".dashboard-charts {",
168
+ " display: grid;",
169
+ " grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));",
170
+ " gap: 30px;",
171
+ "}",
172
+ "",
173
+ ".chart-container {",
174
+ " background: #f9f9f9;",
175
+ " padding: 20px;",
176
+ " border-radius: 8px;",
177
+ "}",
178
+ "",
179
+ ".dark-theme .chart-container {",
180
+ " background: #2a2a2a;",
181
+ "}",
182
+ "",
183
+ ".dashboard-loading {",
184
+ " text-align: center;",
185
+ " padding: 60px 20px;",
186
+ " color: #666;",
187
+ "}",
188
+ "",
189
+ ".dark-theme .dashboard-loading {",
190
+ " color: #999;",
191
+ "}",
192
+ "",
193
+ "@media (max-width: 768px) {",
194
+ " .dashboard-metrics {",
195
+ " grid-template-columns: 1fr;",
196
+ " }",
197
+ " .dashboard-charts {",
198
+ " grid-template-columns: 1fr;",
199
+ " }",
200
+ "}"
201
+ ],
202
+ "client_controller": "{{CLIENT_CONTROLLER|dashboard_controller}}",
203
+ "script": "{{SERVER_SCRIPT|dashboard_server_script}}",
204
+ "link_function": "{{LINK_FUNCTION|}}",
205
+ "demo_data": {
206
+ "metrics": [
207
+ {"label": "Total Items", "value": "1,234", "color": "#007bff", "trend": 12},
208
+ {"label": "Active Users", "value": "456", "color": "#28a745", "trend": 5},
209
+ {"label": "Pending Tasks", "value": "78", "color": "#ffc107", "trend": -3},
210
+ {"label": "Completed", "value": "89%", "color": "#17a2b8", "trend": 2}
211
+ ],
212
+ "charts": [
213
+ {
214
+ "title": "Weekly Trend",
215
+ "type": "line",
216
+ "data": {
217
+ "labels": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
218
+ "datasets": [{
219
+ "label": "Items",
220
+ "data": [65, 59, 80, 81, 56, 55, 40]
221
+ }]
222
+ }
223
+ }
224
+ ]
225
+ }
226
+ },
227
+ "variables": {
228
+ "WIDGET_NAME": "custom_dashboard",
229
+ "WIDGET_ID": "custom_dashboard",
230
+ "INSTANCE_ID": "dashboard_",
231
+ "WIDGET_TITLE": "Dashboard",
232
+ "WIDGET_DESCRIPTION": "Real-time dashboard with key metrics",
233
+ "WIDGET_ROLES": "",
234
+ "CLIENT_CONTROLLER": "function($scope, $http, $timeout) {\n var c = this;\n \n c.loading = true;\n c.fullscreen = false;\n c.metrics = [];\n c.charts = [];\n \n c.refresh = function() {\n c.loading = true;\n c.server.get({\n action: 'get_dashboard_data'\n }).then(function(response) {\n c.metrics = response.data.metrics || [];\n c.charts = response.data.charts || [];\n c.loading = false;\n \n // Render charts\n $timeout(function() {\n c.renderCharts();\n }, 100);\n });\n };\n \n c.renderCharts = function() {\n c.charts.forEach(function(chart, index) {\n var ctx = document.getElementById('chart-' + index);\n if (ctx) {\n new Chart(ctx.getContext('2d'), {\n type: c.options.chart_type || chart.type || 'bar',\n data: chart.data,\n options: {\n responsive: true,\n maintainAspectRatio: false\n }\n });\n }\n });\n };\n \n c.toggleFullscreen = function() {\n c.fullscreen = !c.fullscreen;\n // Implement fullscreen logic\n };\n \n // Initial load\n c.refresh();\n \n // Auto-refresh\n if (c.options.refresh_interval > 0) {\n var refreshTimer = $timeout(function refresh() {\n c.refresh();\n refreshTimer = $timeout(refresh, c.options.refresh_interval * 1000);\n }, c.options.refresh_interval * 1000);\n \n $scope.$on('$destroy', function() {\n $timeout.cancel(refreshTimer);\n });\n }\n}",
235
+ "SERVER_SCRIPT": "(function() {\n try {\n data.metrics = [];\n data.charts = [];\n gs.log('Dashboard widget server script started', 'dashboard_widget');\n \n if (input && input.action === 'get_dashboard_data') {\n // Example: Fetch incident metrics\n var gr = new GlideRecord('incident');\n gr.addQuery('active', 'true'); // ✅ FIXED: Use string instead of boolean\n gr.query();\n \n var totalCount = gr.getRowCount();\n gs.log('Found ' + totalCount + ' active incidents', 'dashboard_widget');\n \n // Get priority breakdown\n var priorities = {};\n gr = new GlideRecord('incident');\n gr.addQuery('active', 'true'); // ✅ FIXED: Use string instead of boolean\n gr.query();\n \n while (gr.next()) {\n var priority = gr.getValue('priority') || 'undefined';\n priorities[priority] = (priorities[priority] || 0) + 1;\n }\n \n // Build metrics\n data.metrics = [\n {\n label: 'Total Incidents',\n value: totalCount.toString(),\n color: '#007bff',\n trend: 5\n },\n {\n label: 'High Priority',\n value: (priorities['1'] || 0).toString(),\n color: '#dc3545',\n trend: -2\n },\n {\n label: 'Medium Priority',\n value: (priorities['2'] || 0).toString(),\n color: '#ffc107',\n trend: 3\n },\n {\n label: 'Low Priority',\n value: (priorities['3'] || 0).toString(),\n color: '#28a745',\n trend: 1\n }\n ];\n \n // Build chart data\n data.charts = [\n {\n title: 'Incidents by Priority',\n type: 'bar',\n data: {\n labels: ['High', 'Medium', 'Low'],\n datasets: [{\n label: 'Incidents',\n data: [\n priorities['1'] || 0,\n priorities['2'] || 0,\n priorities['3'] || 0\n ],\n backgroundColor: ['#dc3545', '#ffc107', '#28a745']\n }]\n }\n }\n ];\n \n gs.log('Dashboard data prepared successfully', 'dashboard_widget');\n }\n } catch (error) {\n gs.error('Dashboard widget error: ' + error.message, 'dashboard_widget');\n data.error = 'Error loading dashboard: ' + error.message;\n data.success = false;\n }\n})()",
236
+ "LINK_FUNCTION": ""
237
+ }
238
+ }
@@ -0,0 +1,292 @@
1
+ {
2
+ "type": "widget",
3
+ "name": "Data Table Widget Template",
4
+ "description": "Template for creating data table widgets with sorting, filtering, and pagination",
5
+ "category": "patterns/datatable",
6
+ "config": {
7
+ "name": "{{WIDGET_NAME|data_table}}",
8
+ "id": "{{WIDGET_ID|data_table}}",
9
+ "instance_id": "{{INSTANCE_ID|table_}}",
10
+ "data": {
11
+ "title": "{{WIDGET_TITLE|Data Table}}",
12
+ "short_description": "{{WIDGET_DESCRIPTION|Interactive data table with advanced features}}",
13
+ "roles": "{{WIDGET_ROLES|}}"
14
+ },
15
+ "options": [
16
+ {
17
+ "name": "table_name",
18
+ "section": "Data",
19
+ "label": "Table",
20
+ "type": "reference",
21
+ "value": "{{TABLE_NAME|incident}}",
22
+ "ed": "sys_db_object",
23
+ "help": "Select the table to display data from"
24
+ },
25
+ {
26
+ "name": "max_records",
27
+ "section": "Data",
28
+ "label": "Maximum Records",
29
+ "type": "integer",
30
+ "value": "100",
31
+ "help": "Maximum number of records to display"
32
+ },
33
+ {
34
+ "name": "enable_filter",
35
+ "section": "Features",
36
+ "label": "Enable Filtering",
37
+ "type": "boolean",
38
+ "value": "true"
39
+ },
40
+ {
41
+ "name": "enable_export",
42
+ "section": "Features",
43
+ "label": "Enable Export",
44
+ "type": "boolean",
45
+ "value": "true"
46
+ },
47
+ {
48
+ "name": "enable_inline_edit",
49
+ "section": "Features",
50
+ "label": "Enable Inline Editing",
51
+ "type": "boolean",
52
+ "value": "false"
53
+ },
54
+ {
55
+ "name": "row_actions",
56
+ "section": "Features",
57
+ "label": "Row Actions",
58
+ "type": "json",
59
+ "value": "[{\"label\":\"View\",\"action\":\"view\",\"icon\":\"eye\"},{\"label\":\"Edit\",\"action\":\"edit\",\"icon\":\"pencil\"}]"
60
+ }
61
+ ],
62
+ "html": [
63
+ "<div class=\"data-table-widget\">",
64
+ " <div class=\"table-header\">",
65
+ " <h2 class=\"table-title\">{{data.title}}</h2>",
66
+ " <div class=\"table-controls\">",
67
+ " <div class=\"search-box\" ng-if=\"options.enable_filter\">",
68
+ " <i class=\"fa fa-search\"></i>",
69
+ " <input type=\"text\" ng-model=\"c.searchTerm\" ng-change=\"c.filterData()\" placeholder=\"Search...\">",
70
+ " </div>",
71
+ " <button class=\"btn btn-primary\" ng-if=\"options.enable_export\" ng-click=\"c.exportData()\">",
72
+ " <i class=\"fa fa-download\"></i> Export",
73
+ " </button>",
74
+ " </div>",
75
+ " </div>",
76
+ " ",
77
+ " <div class=\"table-container\" ng-if=\"!c.loading\">",
78
+ " <table class=\"table table-striped table-hover\">",
79
+ " <thead>",
80
+ " <tr>",
81
+ " <th ng-repeat=\"column in c.columns\" ng-click=\"c.sort(column.field)\" class=\"sortable\">",
82
+ " {{column.label}}",
83
+ " <i class=\"fa fa-sort\" ng-if=\"c.sortField !== column.field\"></i>",
84
+ " <i class=\"fa fa-sort-asc\" ng-if=\"c.sortField === column.field && c.sortDirection === 'asc'\"></i>",
85
+ " <i class=\"fa fa-sort-desc\" ng-if=\"c.sortField === column.field && c.sortDirection === 'desc'\"></i>",
86
+ " </th>",
87
+ " <th ng-if=\"c.rowActions.length > 0\">Actions</th>",
88
+ " </tr>",
89
+ " </thead>",
90
+ " <tbody>",
91
+ " <tr ng-repeat=\"row in c.displayData\">",
92
+ " <td ng-repeat=\"column in c.columns\">",
93
+ " <span ng-if=\"!c.isEditing(row, column)\" ng-click=\"c.startEdit(row, column)\">",
94
+ " {{c.getCellValue(row, column)}}",
95
+ " </span>",
96
+ " <input ng-if=\"c.isEditing(row, column)\" ",
97
+ " type=\"text\" ",
98
+ " ng-model=\"row[column.field]\" ",
99
+ " ng-blur=\"c.saveEdit(row, column)\"",
100
+ " ng-keypress=\"c.handleEditKeypress($event, row, column)\">",
101
+ " </td>",
102
+ " <td ng-if=\"c.rowActions.length > 0\" class=\"actions-cell\">",
103
+ " <button ng-repeat=\"action in c.rowActions\" ",
104
+ " class=\"btn btn-sm btn-default\" ",
105
+ " ng-click=\"c.performAction(action, row)\"",
106
+ " title=\"{{action.label}}\">",
107
+ " <i class=\"fa fa-{{action.icon}}\"></i>",
108
+ " </button>",
109
+ " </td>",
110
+ " </tr>",
111
+ " </tbody>",
112
+ " </table>",
113
+ " </div>",
114
+ " ",
115
+ " <div class=\"table-pagination\" ng-if=\"c.totalPages > 1\">",
116
+ " <button class=\"btn btn-sm\" ng-click=\"c.previousPage()\" ng-disabled=\"c.currentPage === 1\">",
117
+ " <i class=\"fa fa-chevron-left\"></i>",
118
+ " </button>",
119
+ " <span class=\"page-info\">Page {{c.currentPage}} of {{c.totalPages}}</span>",
120
+ " <button class=\"btn btn-sm\" ng-click=\"c.nextPage()\" ng-disabled=\"c.currentPage === c.totalPages\">",
121
+ " <i class=\"fa fa-chevron-right\"></i>",
122
+ " </button>",
123
+ " </div>",
124
+ " ",
125
+ " <div class=\"table-loading\" ng-if=\"c.loading\">",
126
+ " <i class=\"fa fa-spinner fa-spin fa-3x\"></i>",
127
+ " <p>Loading data...</p>",
128
+ " </div>",
129
+ "</div>"
130
+ ],
131
+ "css": [
132
+ ".data-table-widget {",
133
+ " background: #fff;",
134
+ " border-radius: 8px;",
135
+ " box-shadow: 0 2px 4px rgba(0,0,0,0.1);",
136
+ " overflow: hidden;",
137
+ "}",
138
+ "",
139
+ ".table-header {",
140
+ " display: flex;",
141
+ " justify-content: space-between;",
142
+ " align-items: center;",
143
+ " padding: 20px;",
144
+ " border-bottom: 1px solid #e0e0e0;",
145
+ "}",
146
+ "",
147
+ ".table-title {",
148
+ " margin: 0;",
149
+ " font-size: 20px;",
150
+ " font-weight: 600;",
151
+ "}",
152
+ "",
153
+ ".table-controls {",
154
+ " display: flex;",
155
+ " align-items: center;",
156
+ " gap: 15px;",
157
+ "}",
158
+ "",
159
+ ".search-box {",
160
+ " position: relative;",
161
+ " display: flex;",
162
+ " align-items: center;",
163
+ "}",
164
+ "",
165
+ ".search-box i {",
166
+ " position: absolute;",
167
+ " left: 10px;",
168
+ " color: #666;",
169
+ "}",
170
+ "",
171
+ ".search-box input {",
172
+ " padding: 8px 8px 8px 35px;",
173
+ " border: 1px solid #ddd;",
174
+ " border-radius: 4px;",
175
+ " width: 250px;",
176
+ "}",
177
+ "",
178
+ ".table-container {",
179
+ " overflow-x: auto;",
180
+ "}",
181
+ "",
182
+ "table {",
183
+ " width: 100%;",
184
+ " border-collapse: collapse;",
185
+ "}",
186
+ "",
187
+ "th {",
188
+ " background: #f5f5f5;",
189
+ " padding: 12px;",
190
+ " text-align: left;",
191
+ " font-weight: 600;",
192
+ " color: #333;",
193
+ " white-space: nowrap;",
194
+ "}",
195
+ "",
196
+ "th.sortable {",
197
+ " cursor: pointer;",
198
+ " user-select: none;",
199
+ "}",
200
+ "",
201
+ "th.sortable:hover {",
202
+ " background: #e8e8e8;",
203
+ "}",
204
+ "",
205
+ "th i {",
206
+ " margin-left: 5px;",
207
+ " color: #999;",
208
+ "}",
209
+ "",
210
+ "td {",
211
+ " padding: 12px;",
212
+ " border-bottom: 1px solid #f0f0f0;",
213
+ "}",
214
+ "",
215
+ "td input {",
216
+ " width: 100%;",
217
+ " padding: 4px 8px;",
218
+ " border: 1px solid #007bff;",
219
+ " border-radius: 4px;",
220
+ "}",
221
+ "",
222
+ "tr:hover {",
223
+ " background: #f9f9f9;",
224
+ "}",
225
+ "",
226
+ ".actions-cell {",
227
+ " white-space: nowrap;",
228
+ "}",
229
+ "",
230
+ ".actions-cell button {",
231
+ " margin-right: 5px;",
232
+ "}",
233
+ "",
234
+ ".table-pagination {",
235
+ " display: flex;",
236
+ " justify-content: center;",
237
+ " align-items: center;",
238
+ " padding: 20px;",
239
+ " gap: 15px;",
240
+ " border-top: 1px solid #e0e0e0;",
241
+ "}",
242
+ "",
243
+ ".page-info {",
244
+ " color: #666;",
245
+ "}",
246
+ "",
247
+ ".table-loading {",
248
+ " text-align: center;",
249
+ " padding: 60px 20px;",
250
+ " color: #666;",
251
+ "}",
252
+ "",
253
+ "@media (max-width: 768px) {",
254
+ " .table-header {",
255
+ " flex-direction: column;",
256
+ " align-items: flex-start;",
257
+ " gap: 15px;",
258
+ " }",
259
+ " ",
260
+ " .search-box input {",
261
+ " width: 200px;",
262
+ " }",
263
+ "}"
264
+ ],
265
+ "client_controller": "{{CLIENT_CONTROLLER|datatable_controller}}",
266
+ "script": "{{SERVER_SCRIPT|datatable_server_script}}",
267
+ "link_function": "{{LINK_FUNCTION|}}",
268
+ "demo_data": {
269
+ "columns": [
270
+ {"field": "number", "label": "Number"},
271
+ {"field": "short_description", "label": "Description"},
272
+ {"field": "priority", "label": "Priority"},
273
+ {"field": "state", "label": "State"}
274
+ ],
275
+ "data": [
276
+ {"number": "INC0001", "short_description": "Sample incident", "priority": "High", "state": "Open"}
277
+ ]
278
+ }
279
+ },
280
+ "variables": {
281
+ "WIDGET_NAME": "data_table",
282
+ "WIDGET_ID": "data_table",
283
+ "INSTANCE_ID": "table_",
284
+ "WIDGET_TITLE": "Data Table",
285
+ "WIDGET_DESCRIPTION": "Interactive data table with advanced features",
286
+ "WIDGET_ROLES": "",
287
+ "TABLE_NAME": "incident",
288
+ "CLIENT_CONTROLLER": "function($scope, $http, $timeout) {\n var c = this;\n \n c.loading = true;\n c.data = [];\n c.displayData = [];\n c.columns = [];\n c.searchTerm = '';\n c.sortField = null;\n c.sortDirection = 'asc';\n c.currentPage = 1;\n c.pageSize = 20;\n c.totalPages = 1;\n c.editingCell = null;\n c.rowActions = [];\n \n // Parse row actions from options\n try {\n c.rowActions = JSON.parse(c.options.row_actions || '[]');\n } catch(e) {\n c.rowActions = [];\n }\n \n c.getData = function() {\n c.loading = true;\n c.server.get({\n action: 'get_table_data',\n table: c.options.table_name,\n max_records: c.options.max_records\n }).then(function(response) {\n c.columns = response.data.columns || [];\n c.data = response.data.data || [];\n c.filterData();\n c.loading = false;\n });\n };\n \n c.filterData = function() {\n var filtered = c.data;\n \n if (c.searchTerm) {\n filtered = c.data.filter(function(row) {\n return Object.values(row).some(function(value) {\n return String(value).toLowerCase().includes(c.searchTerm.toLowerCase());\n });\n });\n }\n \n // Apply sorting\n if (c.sortField) {\n filtered.sort(function(a, b) {\n var aVal = a[c.sortField] || '';\n var bVal = b[c.sortField] || '';\n var result = aVal < bVal ? -1 : aVal > bVal ? 1 : 0;\n return c.sortDirection === 'desc' ? -result : result;\n });\n }\n \n // Apply pagination\n c.totalPages = Math.ceil(filtered.length / c.pageSize);\n var start = (c.currentPage - 1) * c.pageSize;\n c.displayData = filtered.slice(start, start + c.pageSize);\n };\n \n c.sort = function(field) {\n if (c.sortField === field) {\n c.sortDirection = c.sortDirection === 'asc' ? 'desc' : 'asc';\n } else {\n c.sortField = field;\n c.sortDirection = 'asc';\n }\n c.filterData();\n };\n \n c.previousPage = function() {\n if (c.currentPage > 1) {\n c.currentPage--;\n c.filterData();\n }\n };\n \n c.nextPage = function() {\n if (c.currentPage < c.totalPages) {\n c.currentPage++;\n c.filterData();\n }\n };\n \n c.getCellValue = function(row, column) {\n var value = row[column.field];\n // Format based on field type\n if (column.type === 'date') {\n return value ? new Date(value).toLocaleDateString() : '';\n }\n return value || '';\n };\n \n c.isEditing = function(row, column) {\n return c.options.enable_inline_edit && \n c.editingCell && \n c.editingCell.row === row && \n c.editingCell.column === column;\n };\n \n c.startEdit = function(row, column) {\n if (c.options.enable_inline_edit) {\n c.editingCell = {row: row, column: column};\n }\n };\n \n c.saveEdit = function(row, column) {\n c.editingCell = null;\n // Save to server\n c.server.get({\n action: 'update_record',\n table: c.options.table_name,\n sys_id: row.sys_id,\n field: column.field,\n value: row[column.field]\n });\n };\n \n c.handleEditKeypress = function(event, row, column) {\n if (event.keyCode === 13) { // Enter key\n c.saveEdit(row, column);\n }\n };\n \n c.performAction = function(action, row) {\n switch(action.action) {\n case 'view':\n window.open('/' + c.options.table_name + '.do?sys_id=' + row.sys_id, '_blank');\n break;\n case 'edit':\n window.open('/' + c.options.table_name + '.do?sys_id=' + row.sys_id + '&sysparm_view=edit', '_blank');\n break;\n default:\n // Custom action\n $scope.$emit('widget-action', {action: action, row: row});\n }\n };\n \n c.exportData = function() {\n var csv = c.columns.map(function(col) { return col.label; }).join(',') + '\\n';\n c.displayData.forEach(function(row) {\n csv += c.columns.map(function(col) {\n var val = row[col.field] || '';\n return '\"' + String(val).replace(/\"/g, '\"\"') + '\"';\n }).join(',') + '\\n';\n });\n \n var blob = new Blob([csv], {type: 'text/csv'});\n var url = window.URL.createObjectURL(blob);\n var a = document.createElement('a');\n a.href = url;\n a.download = c.data.title + '.csv';\n a.click();\n };\n \n // Initial load\n c.getData();\n}",
289
+ "SERVER_SCRIPT": "(function() {\n try {\n data.columns = [];\n data.data = [];\n gs.log('DataTable widget server script started', 'datatable_widget');\n \n if (input && input.action === 'get_table_data') {\n var tableName = input.table || 'incident';\n var maxRecords = parseInt(input.max_records) || 100;\n \n gs.log('Getting table data: table=' + tableName + ', maxRecords=' + maxRecords, 'datatable_widget');\n \n // Get table metadata\n var fields = [];\n var gd = new GlideRecord('sys_dictionary');\n gd.addQuery('name', tableName);\n gd.addQuery('internal_type', '!=', 'collection');\n gd.orderBy('column_label');\n gd.setLimit(10); // Limit columns for performance\n gd.query();\n \n while (gd.next()) {\n if (gd.element && !gd.element.startsWith('sys_')) {\n fields.push({\n field: gd.element.toString(),\n label: gd.column_label.toString() || gd.element.toString(),\n type: gd.internal_type.toString()\n });\n }\n }\n \n // Default fields if none found\n if (fields.length === 0) {\n fields = [\n {field: 'number', label: 'Number', type: 'string'},\n {field: 'short_description', label: 'Short Description', type: 'string'},\n {field: 'sys_created_on', label: 'Created', type: 'glide_date_time'}\n ];\n gs.log('Using default fields for table: ' + tableName, 'datatable_widget');\n }\n \n data.columns = fields;\n gs.log('Found ' + fields.length + ' columns for table', 'datatable_widget');\n \n // Get table data\n var gr = new GlideRecord(tableName);\n gr.orderByDesc('sys_created_on');\n gr.setLimit(maxRecords);\n gr.query();\n \n var recordCount = 0;\n while (gr.next()) {\n var row = {sys_id: gr.getUniqueValue()};\n fields.forEach(function(field) {\n row[field.field] = gr.getDisplayValue(field.field) || '';\n });\n data.data.push(row);\n recordCount++;\n }\n \n gs.log('Retrieved ' + recordCount + ' records from ' + tableName, 'datatable_widget');\n \n } else if (input && input.action === 'update_record') {\n // ✅ FIXED: Enhanced update with validation and error handling\n if (!input.table || !input.sys_id || !input.field) {\n throw new Error('Missing required parameters for update: table, sys_id, field');\n }\n \n gs.log('Updating record: table=' + input.table + ', sys_id=' + input.sys_id + ', field=' + input.field, 'datatable_widget');\n \n var gr = new GlideRecord(input.table);\n if (gr.get(input.sys_id)) {\n gr.setValue(input.field, input.value || '');\n gr.update();\n data.success = true;\n data.message = 'Record updated successfully';\n gs.log('Record updated successfully', 'datatable_widget');\n } else {\n data.success = false;\n data.error = 'Record not found: ' + input.sys_id;\n gs.warn('Record not found for update: ' + input.sys_id, 'datatable_widget');\n }\n }\n } catch (error) {\n gs.error('DataTable widget error: ' + error.message, 'datatable_widget');\n data.error = 'Error processing request: ' + error.message;\n data.success = false;\n }\n})()",
290
+ "LINK_FUNCTION": ""
291
+ }
292
+ }
package/.env.example DELETED
@@ -1,64 +0,0 @@
1
- # ServiceNow OAuth Configuration (recommended)
2
- SNOW_INSTANCE=dev12345.service-now.com
3
- SNOW_CLIENT_ID=your_oauth_client_id
4
- SNOW_CLIENT_SECRET=your_oauth_client_secret
5
-
6
- # OAuth URLs (these are automatically generated)
7
- OAUTH_TOKEN_URL=https://dev12345.service-now.com/oauth_token.do
8
- OAUTH_REDIRECT_URI=http://localhost:3000/callback
9
-
10
- # Basic Auth Configuration (deprecated - use OAuth instead)
11
- # Uncomment these lines ONLY if you need to use basic auth:
12
- # SNOW_USERNAME=your_username
13
- # SNOW_PASSWORD=your_password
14
-
15
- # ===========================================
16
- # Snow-Flow Configuration
17
- # ===========================================
18
-
19
- # Enable debug logging (true/false)
20
- SNOW_FLOW_DEBUG=false
21
-
22
- # Default coordination strategy
23
- SNOW_FLOW_STRATEGY=development
24
-
25
- # Maximum number of agents
26
- SNOW_FLOW_MAX_AGENTS=5
27
-
28
- # Claude Code timeout configuration (in minutes)
29
- # Set to 0 to disable timeout (infinite execution time)
30
- # Default: 60 minutes
31
- SNOW_FLOW_TIMEOUT_MINUTES=0
32
-
33
- # ===========================================
34
- # Deployment Timeout Configuration
35
- # ===========================================
36
-
37
- # ServiceNow API timeout for regular operations (milliseconds)
38
- # Default: 60000 (60 seconds)
39
- SNOW_REQUEST_TIMEOUT=60000
40
-
41
- # ServiceNow API timeout for DEPLOYMENT operations (milliseconds)
42
- # Deployments need more time for complex widgets
43
- # Default: 300000 (5 minutes)
44
- SNOW_DEPLOYMENT_TIMEOUT=300000
45
-
46
- # MCP transport timeout for deployment operations (milliseconds)
47
- # Should be higher than SNOW_DEPLOYMENT_TIMEOUT
48
- # Default: 360000 (6 minutes)
49
- MCP_DEPLOYMENT_TIMEOUT=360000
50
-
51
- # ===========================================
52
- # How to Set Up ServiceNow OAuth
53
- # ===========================================
54
- # 1. Log into your ServiceNow instance as admin
55
- # 2. Navigate to: System OAuth > Application Registry
56
- # 3. Click "New" > "Create an OAuth application"
57
- # 4. Fill in:
58
- # - Name: Snow-Flow Development
59
- # - Client ID: (will be generated)
60
- # - Client Secret: (will be generated)
61
- # - Redirect URL: http://${SNOW_REDIRECT_HOST:-localhost}:${SNOW_REDIRECT_PORT:-3000}/callback
62
- # - Grant Type: Authorization Code
63
- # 5. Copy the Client ID and Client Secret to this file
64
- # 6. Run: snow-flow auth login