snow-flow 2.0.5 → 2.0.7
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/config/snow-flow-config.d.ts +1492 -0
- package/dist/config/snow-flow-config.js +938 -0
- package/dist/coordination/coordination-engine.d.ts +41 -0
- package/dist/coordination/coordination-engine.js +324 -0
- package/dist/coordination/coordination.test.d.ts +6 -0
- package/dist/coordination/example.d.ts +31 -0
- package/dist/coordination/example.js +394 -0
- package/dist/coordination/execution-patterns.d.ts +43 -0
- package/dist/coordination/execution-patterns.js +507 -0
- package/dist/coordination/factory.d.ts +94 -0
- package/dist/coordination/factory.js +433 -0
- package/dist/coordination/index.d.ts +71 -0
- package/dist/coordination/index.js +135 -0
- package/dist/coordination/progress-monitor.d.ts +71 -0
- package/dist/coordination/progress-monitor.js +505 -0
- package/dist/coordination/quality-gates.d.ts +124 -0
- package/dist/coordination/quality-gates.js +577 -0
- package/dist/coordination/shared-memory.d.ts +39 -0
- package/dist/coordination/shared-memory.js +289 -0
- package/dist/coordination/task-dependencies.d.ts +50 -0
- package/dist/coordination/task-dependencies.js +407 -0
- package/dist/coordination/team-coordinator.d.ts +59 -0
- package/dist/coordination/team-coordinator.js +550 -0
- package/dist/coordination/types.d.ts +152 -0
- package/dist/coordination/types.js +3 -0
- package/dist/memory/memory-system.d.ts +1 -0
- package/dist/memory/memory-system.js +21 -2
- package/memory/claude-flow-data.json +5 -0
- package/memory/servicenow_artifacts/000d9224c895221055906c7518aa2d3d.json +30 -0
- package/memory/servicenow_artifacts/0196b66173303010e46b4a2214f6a7a2.json +36 -0
- package/memory/servicenow_artifacts/125e5d1d837e2a102a7ea130ceaad397.json +30 -0
- package/memory/servicenow_artifacts/7637c1f2b7112210a5e5911cde11a972.json +30 -0
- package/memory/servicenow_artifacts/default_documentation_tables_1754056582292.json +55 -0
- package/memory/servicenow_artifacts/default_documentation_tables_1754057477189.json +55 -0
- package/memory/sessions/README.md +32 -0
- package/memory/update-set-sessions/01f82af583faea102a7ea130ceaad3d4.json +9 -0
- package/memory/update-set-sessions/27718fb983faea102a7ea130ceaad34b.json +9 -0
- package/memory/update-set-sessions/412e9bf6833e22502a7ea130ceaad30a.json +8 -0
- package/memory/update-set-sessions/66fc5a79837aea102a7ea130ceaad3ab.json +9 -0
- package/memory/update-set-sessions/71a30ff5837eea102a7ea130ceaad37f.json +9 -0
- package/memory/update-set-sessions/74fba27983faea102a7ea130ceaad3bd.json +9 -0
- package/memory/update-set-sessions/a0b147b5837eea102a7ea130ceaad344.json +58 -0
- package/memory/update-set-sessions/b13f5eb983baea102a7ea130ceaad33e.json +9 -0
- package/package.json +1 -1
- package/reports/swarm-auto-centralized-1752649029776.json +13 -0
- package/servicenow/widgets/openai_incident_classifier/client_controller.js +284 -0
- package/servicenow/widgets/openai_incident_classifier/server_script.js +314 -0
- package/servicenow/widgets/openai_incident_classifier/style.css +354 -0
- package/servicenow/widgets/openai_incident_classifier/template.html +167 -0
- package/servicenow/widgets/openai_incident_classifier/widget.json +86 -0
- package/intelligent-mcp.db-shm +0 -0
- package/intelligent-mcp.db-wal +0 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
function OpenAIIncidentClassifierController($scope, $http, spUtil) {
|
|
2
|
+
var c = this;
|
|
3
|
+
|
|
4
|
+
// Initialize variables
|
|
5
|
+
c.incidents = [];
|
|
6
|
+
c.statistics = {
|
|
7
|
+
totalIncidents: 0,
|
|
8
|
+
classifiedIncidents: 0,
|
|
9
|
+
averageConfidence: 0,
|
|
10
|
+
processingTime: 0
|
|
11
|
+
};
|
|
12
|
+
c.isLoading = false;
|
|
13
|
+
c.error = null;
|
|
14
|
+
c.charts = {};
|
|
15
|
+
|
|
16
|
+
// Date range and filtering
|
|
17
|
+
c.dateRange = {
|
|
18
|
+
start: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
|
|
19
|
+
end: new Date().toISOString().split('T')[0]
|
|
20
|
+
};
|
|
21
|
+
c.selectedPriority = '';
|
|
22
|
+
|
|
23
|
+
// Pagination
|
|
24
|
+
c.pagination = {
|
|
25
|
+
currentPage: 1,
|
|
26
|
+
pageSize: 10,
|
|
27
|
+
totalPages: 1,
|
|
28
|
+
totalRecords: 0,
|
|
29
|
+
pages: []
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// Initialize widget
|
|
33
|
+
c.initialize = function() {
|
|
34
|
+
c.loadData();
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Load data from server
|
|
38
|
+
c.loadData = function() {
|
|
39
|
+
c.isLoading = true;
|
|
40
|
+
c.error = null;
|
|
41
|
+
|
|
42
|
+
var params = {
|
|
43
|
+
start_date: c.dateRange.start,
|
|
44
|
+
end_date: c.dateRange.end,
|
|
45
|
+
priority: c.selectedPriority,
|
|
46
|
+
page: c.pagination.currentPage,
|
|
47
|
+
page_size: c.pagination.pageSize
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
$http.post('/api/now/sp/widget/' + c.widget.id, {
|
|
51
|
+
action: 'get_incidents',
|
|
52
|
+
params: params
|
|
53
|
+
}).then(function(response) {
|
|
54
|
+
if (response.data.result.success) {
|
|
55
|
+
c.incidents = response.data.result.incidents;
|
|
56
|
+
c.statistics = response.data.result.statistics;
|
|
57
|
+
c.pagination.totalRecords = response.data.result.total_records;
|
|
58
|
+
c.pagination.totalPages = Math.ceil(c.pagination.totalRecords / c.pagination.pageSize);
|
|
59
|
+
c.updatePaginationPages();
|
|
60
|
+
c.updateCharts();
|
|
61
|
+
} else {
|
|
62
|
+
c.error = response.data.result.error || 'Failed to load incidents';
|
|
63
|
+
}
|
|
64
|
+
}).catch(function(error) {
|
|
65
|
+
c.error = 'Error loading data: ' + (error.data && error.data.error ? error.data.error : error.message);
|
|
66
|
+
}).finally(function() {
|
|
67
|
+
c.isLoading = false;
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// Update pagination pages array
|
|
72
|
+
c.updatePaginationPages = function() {
|
|
73
|
+
c.pagination.pages = [];
|
|
74
|
+
var startPage = Math.max(1, c.pagination.currentPage - 2);
|
|
75
|
+
var endPage = Math.min(c.pagination.totalPages, c.pagination.currentPage + 2);
|
|
76
|
+
|
|
77
|
+
for (var i = startPage; i <= endPage; i++) {
|
|
78
|
+
c.pagination.pages.push(i);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// Go to specific page
|
|
83
|
+
c.goToPage = function(page) {
|
|
84
|
+
if (page >= 1 && page <= c.pagination.totalPages && page !== c.pagination.currentPage) {
|
|
85
|
+
c.pagination.currentPage = page;
|
|
86
|
+
c.loadData();
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// Date range change handler
|
|
91
|
+
c.onDateRangeChange = function() {
|
|
92
|
+
c.pagination.currentPage = 1;
|
|
93
|
+
c.loadData();
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// Priority change handler
|
|
97
|
+
c.onPriorityChange = function() {
|
|
98
|
+
c.pagination.currentPage = 1;
|
|
99
|
+
c.loadData();
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// Refresh data
|
|
103
|
+
c.refreshData = function() {
|
|
104
|
+
c.loadData();
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// Reclassify incident
|
|
108
|
+
c.reclassifyIncident = function(incident) {
|
|
109
|
+
c.isLoading = true;
|
|
110
|
+
|
|
111
|
+
$http.post('/api/now/sp/widget/' + c.widget.id, {
|
|
112
|
+
action: 'reclassify_incident',
|
|
113
|
+
incident_id: incident.sys_id
|
|
114
|
+
}).then(function(response) {
|
|
115
|
+
if (response.data.result.success) {
|
|
116
|
+
spUtil.addInfoMessage('Incident reclassified successfully');
|
|
117
|
+
c.loadData();
|
|
118
|
+
} else {
|
|
119
|
+
c.error = response.data.result.error || 'Failed to reclassify incident';
|
|
120
|
+
}
|
|
121
|
+
}).catch(function(error) {
|
|
122
|
+
c.error = 'Error reclassifying incident: ' + (error.data && error.data.error ? error.data.error : error.message);
|
|
123
|
+
}).finally(function() {
|
|
124
|
+
c.isLoading = false;
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// Update charts
|
|
129
|
+
c.updateCharts = function() {
|
|
130
|
+
c.createClassificationChart();
|
|
131
|
+
c.createPriorityChart();
|
|
132
|
+
c.createTrendChart();
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
// Create classification distribution chart
|
|
136
|
+
c.createClassificationChart = function() {
|
|
137
|
+
var ctx = document.getElementById('classificationChart');
|
|
138
|
+
if (!ctx) return;
|
|
139
|
+
|
|
140
|
+
// Destroy existing chart
|
|
141
|
+
if (c.charts.classification) {
|
|
142
|
+
c.charts.classification.destroy();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Aggregate classification data
|
|
146
|
+
var classificationData = {};
|
|
147
|
+
c.incidents.forEach(function(incident) {
|
|
148
|
+
var classification = incident.ai_classification || 'Unclassified';
|
|
149
|
+
classificationData[classification] = (classificationData[classification] || 0) + 1;
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
var labels = Object.keys(classificationData);
|
|
153
|
+
var data = Object.values(classificationData);
|
|
154
|
+
var colors = ['#dc3545', '#007bff', '#28a745', '#fd7e14', '#6f42c1', '#6c757d'];
|
|
155
|
+
|
|
156
|
+
c.charts.classification = new Chart(ctx, {
|
|
157
|
+
type: 'doughnut',
|
|
158
|
+
data: {
|
|
159
|
+
labels: labels,
|
|
160
|
+
datasets: [{
|
|
161
|
+
data: data,
|
|
162
|
+
backgroundColor: colors.slice(0, labels.length),
|
|
163
|
+
borderWidth: 2,
|
|
164
|
+
borderColor: '#fff'
|
|
165
|
+
}]
|
|
166
|
+
},
|
|
167
|
+
options: {
|
|
168
|
+
responsive: true,
|
|
169
|
+
maintainAspectRatio: false,
|
|
170
|
+
plugins: {
|
|
171
|
+
legend: {
|
|
172
|
+
position: 'bottom'
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// Create priority distribution chart
|
|
180
|
+
c.createPriorityChart = function() {
|
|
181
|
+
var ctx = document.getElementById('priorityChart');
|
|
182
|
+
if (!ctx) return;
|
|
183
|
+
|
|
184
|
+
// Destroy existing chart
|
|
185
|
+
if (c.charts.priority) {
|
|
186
|
+
c.charts.priority.destroy();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Aggregate priority data
|
|
190
|
+
var priorityData = {};
|
|
191
|
+
var priorityLabels = {'1': 'Critical', '2': 'High', '3': 'Moderate', '4': 'Low'};
|
|
192
|
+
|
|
193
|
+
c.incidents.forEach(function(incident) {
|
|
194
|
+
var priority = incident.priority || '4';
|
|
195
|
+
var label = priorityLabels[priority] || 'Unknown';
|
|
196
|
+
priorityData[label] = (priorityData[label] || 0) + 1;
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
var labels = Object.keys(priorityData);
|
|
200
|
+
var data = Object.values(priorityData);
|
|
201
|
+
var colors = ['#dc3545', '#fd7e14', '#ffc107', '#28a745'];
|
|
202
|
+
|
|
203
|
+
c.charts.priority = new Chart(ctx, {
|
|
204
|
+
type: 'bar',
|
|
205
|
+
data: {
|
|
206
|
+
labels: labels,
|
|
207
|
+
datasets: [{
|
|
208
|
+
label: 'Number of Incidents',
|
|
209
|
+
data: data,
|
|
210
|
+
backgroundColor: colors.slice(0, labels.length),
|
|
211
|
+
borderWidth: 1
|
|
212
|
+
}]
|
|
213
|
+
},
|
|
214
|
+
options: {
|
|
215
|
+
responsive: true,
|
|
216
|
+
maintainAspectRatio: false,
|
|
217
|
+
scales: {
|
|
218
|
+
y: {
|
|
219
|
+
beginAtZero: true
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
// Create trend chart
|
|
227
|
+
c.createTrendChart = function() {
|
|
228
|
+
var ctx = document.getElementById('trendChart');
|
|
229
|
+
if (!ctx) return;
|
|
230
|
+
|
|
231
|
+
// Destroy existing chart
|
|
232
|
+
if (c.charts.trend) {
|
|
233
|
+
c.charts.trend.destroy();
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Aggregate trend data by date
|
|
237
|
+
var trendData = {};
|
|
238
|
+
c.incidents.forEach(function(incident) {
|
|
239
|
+
var date = new Date(incident.created_date).toISOString().split('T')[0];
|
|
240
|
+
trendData[date] = (trendData[date] || 0) + 1;
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
var labels = Object.keys(trendData).sort();
|
|
244
|
+
var data = labels.map(function(date) {
|
|
245
|
+
return trendData[date];
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
c.charts.trend = new Chart(ctx, {
|
|
249
|
+
type: 'line',
|
|
250
|
+
data: {
|
|
251
|
+
labels: labels,
|
|
252
|
+
datasets: [{
|
|
253
|
+
label: 'Incidents per Day',
|
|
254
|
+
data: data,
|
|
255
|
+
borderColor: '#007bff',
|
|
256
|
+
backgroundColor: 'rgba(0, 123, 255, 0.1)',
|
|
257
|
+
borderWidth: 2,
|
|
258
|
+
fill: true
|
|
259
|
+
}]
|
|
260
|
+
},
|
|
261
|
+
options: {
|
|
262
|
+
responsive: true,
|
|
263
|
+
maintainAspectRatio: false,
|
|
264
|
+
scales: {
|
|
265
|
+
y: {
|
|
266
|
+
beginAtZero: true
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
// Cleanup function
|
|
274
|
+
c.$onDestroy = function() {
|
|
275
|
+
Object.values(c.charts).forEach(function(chart) {
|
|
276
|
+
if (chart) {
|
|
277
|
+
chart.destroy();
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
// Initialize widget when loaded
|
|
283
|
+
c.initialize();
|
|
284
|
+
}
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
(function() {
|
|
2
|
+
// Server-side script for OpenAI Incident Classification Widget
|
|
3
|
+
|
|
4
|
+
var OpenAIIncidentClassifier = {
|
|
5
|
+
|
|
6
|
+
// Main data processing function
|
|
7
|
+
processRequest: function(action, params) {
|
|
8
|
+
try {
|
|
9
|
+
switch (action) {
|
|
10
|
+
case 'get_incidents':
|
|
11
|
+
return this.getIncidents(params);
|
|
12
|
+
case 'reclassify_incident':
|
|
13
|
+
return this.reclassifyIncident(params.incident_id);
|
|
14
|
+
default:
|
|
15
|
+
return { success: false, error: 'Invalid action' };
|
|
16
|
+
}
|
|
17
|
+
} catch (error) {
|
|
18
|
+
gs.error('OpenAI Incident Classifier Error: ' + error.message);
|
|
19
|
+
return { success: false, error: error.message };
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
// Get incidents with classification data
|
|
24
|
+
getIncidents: function(params) {
|
|
25
|
+
var startTime = new Date().getTime();
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
// Parse parameters
|
|
29
|
+
var startDate = params.start_date || this.getDateDaysAgo(7);
|
|
30
|
+
var endDate = params.end_date || this.getDateToday();
|
|
31
|
+
var priority = params.priority || '';
|
|
32
|
+
var page = parseInt(params.page) || 1;
|
|
33
|
+
var pageSize = parseInt(params.page_size) || 10;
|
|
34
|
+
|
|
35
|
+
gs.log('Getting incidents: startDate=' + startDate + ', endDate=' + endDate + ', priority=' + priority, 'OpenAIIncidentClassifier');
|
|
36
|
+
|
|
37
|
+
// Build query for incidents
|
|
38
|
+
var incidentGR = new GlideRecord('incident');
|
|
39
|
+
incidentGR.addQuery('sys_created_on', '>=', startDate);
|
|
40
|
+
incidentGR.addQuery('sys_created_on', '<=', endDate + ' 23:59:59');
|
|
41
|
+
|
|
42
|
+
if (priority) {
|
|
43
|
+
incidentGR.addQuery('priority', priority);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
incidentGR.orderByDesc('sys_created_on');
|
|
47
|
+
incidentGR.query();
|
|
48
|
+
|
|
49
|
+
var totalRecords = incidentGR.getRowCount();
|
|
50
|
+
var incidents = [];
|
|
51
|
+
var skip = (page - 1) * pageSize;
|
|
52
|
+
var count = 0;
|
|
53
|
+
|
|
54
|
+
gs.log('Processing ' + totalRecords + ' total records, skip=' + skip + ', pageSize=' + pageSize, 'OpenAIIncidentClassifier');
|
|
55
|
+
|
|
56
|
+
while (incidentGR.next()) {
|
|
57
|
+
if (count < skip) {
|
|
58
|
+
count++;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (incidents.length >= pageSize) {
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
var incident = this.processIncident(incidentGR);
|
|
67
|
+
incidents.push(incident);
|
|
68
|
+
count++;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Calculate statistics
|
|
72
|
+
var statistics = this.calculateStatistics(incidents);
|
|
73
|
+
statistics.processingTime = ((new Date().getTime() - startTime) / 1000).toFixed(2);
|
|
74
|
+
|
|
75
|
+
gs.log('Successfully processed ' + incidents.length + ' incidents in ' + statistics.processingTime + 's', 'OpenAIIncidentClassifier');
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
success: true,
|
|
79
|
+
incidents: incidents,
|
|
80
|
+
statistics: statistics,
|
|
81
|
+
total_records: totalRecords
|
|
82
|
+
};
|
|
83
|
+
} catch (error) {
|
|
84
|
+
gs.error('Error getting incidents: ' + error.message, 'OpenAIIncidentClassifier');
|
|
85
|
+
return {
|
|
86
|
+
success: false,
|
|
87
|
+
error: 'Failed to get incidents: ' + error.message,
|
|
88
|
+
incidents: [],
|
|
89
|
+
statistics: { totalIncidents: 0, processingTime: 0 },
|
|
90
|
+
total_records: 0
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
// Process individual incident
|
|
96
|
+
processIncident: function(incidentGR) {
|
|
97
|
+
var incident = {
|
|
98
|
+
sys_id: incidentGR.getUniqueValue(),
|
|
99
|
+
number: incidentGR.getDisplayValue('number'),
|
|
100
|
+
short_description: incidentGR.getDisplayValue('short_description'),
|
|
101
|
+
description: incidentGR.getDisplayValue('description'),
|
|
102
|
+
priority: incidentGR.getValue('priority'),
|
|
103
|
+
priority_label: incidentGR.getDisplayValue('priority'),
|
|
104
|
+
created_date: incidentGR.getDisplayValue('sys_created_on'),
|
|
105
|
+
ai_classification: incidentGR.getValue('u_ai_classification'),
|
|
106
|
+
ai_confidence: parseFloat(incidentGR.getValue('u_ai_confidence')) || 0,
|
|
107
|
+
ai_classification_date: incidentGR.getDisplayValue('u_ai_classification_date')
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
// Classify if not already classified
|
|
111
|
+
if (!incident.ai_classification) {
|
|
112
|
+
var classification = this.classifyIncident(incident);
|
|
113
|
+
if (classification.success) {
|
|
114
|
+
incident.ai_classification = classification.category;
|
|
115
|
+
incident.ai_confidence = classification.confidence;
|
|
116
|
+
|
|
117
|
+
// Update the incident record
|
|
118
|
+
this.updateIncidentClassification(incident.sys_id, classification);
|
|
119
|
+
} else {
|
|
120
|
+
incident.ai_classification = 'Other';
|
|
121
|
+
incident.ai_confidence = 50;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return incident;
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
// Classify incident using OpenAI or fallback logic
|
|
129
|
+
classifyIncident: function(incident) {
|
|
130
|
+
// Try OpenAI classification first
|
|
131
|
+
var openaiResult = this.classifyWithOpenAI(incident);
|
|
132
|
+
if (openaiResult.success) {
|
|
133
|
+
return openaiResult;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Fallback to rule-based classification
|
|
137
|
+
return this.classifyWithRules(incident);
|
|
138
|
+
},
|
|
139
|
+
|
|
140
|
+
// Classify incident using OpenAI API
|
|
141
|
+
classifyWithOpenAI: function(incident) {
|
|
142
|
+
try {
|
|
143
|
+
var apiKey = gs.getProperty('x_openai.api_key');
|
|
144
|
+
if (!apiKey) {
|
|
145
|
+
return { success: false, error: 'OpenAI API key not configured' };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
var requestBody = {
|
|
149
|
+
model: 'gpt-3.5-turbo',
|
|
150
|
+
messages: [
|
|
151
|
+
{
|
|
152
|
+
role: 'system',
|
|
153
|
+
content: 'You are an IT incident classification expert. Classify incidents into these categories: Hardware, Software, Network, Security, Access, Other. Respond with JSON format: {"category": "category_name", "confidence": confidence_score_0_to_100, "reasoning": "brief_explanation"}'
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
role: 'user',
|
|
157
|
+
content: 'Classify this incident:\nTitle: ' + incident.short_description + '\nDescription: ' + incident.description
|
|
158
|
+
}
|
|
159
|
+
],
|
|
160
|
+
max_tokens: 150,
|
|
161
|
+
temperature: 0.3
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
var request = new sn_ws.RESTMessageV2();
|
|
165
|
+
request.setEndpoint('https://api.openai.com/v1/chat/completions');
|
|
166
|
+
request.setHttpMethod('POST');
|
|
167
|
+
request.setRequestHeader('Authorization', 'Bearer ' + apiKey);
|
|
168
|
+
request.setRequestHeader('Content-Type', 'application/json');
|
|
169
|
+
request.setRequestBody(JSON.stringify(requestBody));
|
|
170
|
+
|
|
171
|
+
var response = request.execute();
|
|
172
|
+
var responseCode = response.getStatusCode();
|
|
173
|
+
|
|
174
|
+
if (responseCode === 200) {
|
|
175
|
+
var responseBody = JSON.parse(response.getBody());
|
|
176
|
+
var content = responseBody.choices[0].message.content;
|
|
177
|
+
|
|
178
|
+
try {
|
|
179
|
+
var result = JSON.parse(content);
|
|
180
|
+
return {
|
|
181
|
+
success: true,
|
|
182
|
+
category: result.category,
|
|
183
|
+
confidence: result.confidence,
|
|
184
|
+
reasoning: result.reasoning
|
|
185
|
+
};
|
|
186
|
+
} catch (parseError) {
|
|
187
|
+
return { success: false, error: 'Failed to parse OpenAI response' };
|
|
188
|
+
}
|
|
189
|
+
} else {
|
|
190
|
+
return { success: false, error: 'OpenAI API error: ' + responseCode };
|
|
191
|
+
}
|
|
192
|
+
} catch (error) {
|
|
193
|
+
return { success: false, error: 'OpenAI classification failed: ' + error.message };
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
|
|
197
|
+
// Fallback rule-based classification
|
|
198
|
+
classifyWithRules: function(incident) {
|
|
199
|
+
var text = (incident.short_description + ' ' + incident.description).toLowerCase();
|
|
200
|
+
|
|
201
|
+
// Hardware keywords
|
|
202
|
+
if (text.match(/hardware|computer|laptop|desktop|monitor|printer|mouse|keyboard|server|disk|memory|cpu/)) {
|
|
203
|
+
return { success: true, category: 'Hardware', confidence: 70, reasoning: 'Keyword-based classification' };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Software keywords
|
|
207
|
+
if (text.match(/software|application|program|system|error|bug|crash|install|update|patch/)) {
|
|
208
|
+
return { success: true, category: 'Software', confidence: 70, reasoning: 'Keyword-based classification' };
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Network keywords
|
|
212
|
+
if (text.match(/network|internet|connection|wifi|ethernet|vpn|firewall|router|switch|bandwidth/)) {
|
|
213
|
+
return { success: true, category: 'Network', confidence: 70, reasoning: 'Keyword-based classification' };
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Security keywords
|
|
217
|
+
if (text.match(/security|virus|malware|phishing|breach|unauthorized|password|access|permissions/)) {
|
|
218
|
+
return { success: true, category: 'Security', confidence: 70, reasoning: 'Keyword-based classification' };
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Access keywords
|
|
222
|
+
if (text.match(/access|login|password|account|user|authentication|authorization|permission/)) {
|
|
223
|
+
return { success: true, category: 'Access', confidence: 70, reasoning: 'Keyword-based classification' };
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Default to Other
|
|
227
|
+
return { success: true, category: 'Other', confidence: 50, reasoning: 'No specific keywords found' };
|
|
228
|
+
},
|
|
229
|
+
|
|
230
|
+
// Update incident classification in database
|
|
231
|
+
updateIncidentClassification: function(incidentId, classification) {
|
|
232
|
+
var incidentGR = new GlideRecord('incident');
|
|
233
|
+
if (incidentGR.get(incidentId)) {
|
|
234
|
+
incidentGR.setValue('u_ai_classification', classification.category);
|
|
235
|
+
incidentGR.setValue('u_ai_confidence', classification.confidence);
|
|
236
|
+
incidentGR.setValue('u_ai_classification_date', new GlideDateTime());
|
|
237
|
+
incidentGR.update();
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
|
|
241
|
+
// Reclassify incident
|
|
242
|
+
reclassifyIncident: function(incidentId) {
|
|
243
|
+
var incidentGR = new GlideRecord('incident');
|
|
244
|
+
if (!incidentGR.get(incidentId)) {
|
|
245
|
+
return { success: false, error: 'Incident not found' };
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
var incident = {
|
|
249
|
+
sys_id: incidentGR.getUniqueValue(),
|
|
250
|
+
short_description: incidentGR.getDisplayValue('short_description'),
|
|
251
|
+
description: incidentGR.getDisplayValue('description')
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
var classification = this.classifyIncident(incident);
|
|
255
|
+
if (classification.success) {
|
|
256
|
+
this.updateIncidentClassification(incidentId, classification);
|
|
257
|
+
return { success: true, message: 'Incident reclassified successfully' };
|
|
258
|
+
} else {
|
|
259
|
+
return { success: false, error: 'Failed to reclassify incident' };
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
|
|
263
|
+
// Calculate statistics
|
|
264
|
+
calculateStatistics: function(incidents) {
|
|
265
|
+
var stats = {
|
|
266
|
+
totalIncidents: incidents.length,
|
|
267
|
+
classifiedIncidents: 0,
|
|
268
|
+
averageConfidence: 0,
|
|
269
|
+
processingTime: 0
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
var totalConfidence = 0;
|
|
273
|
+
incidents.forEach(function(incident) {
|
|
274
|
+
if (incident.ai_classification && incident.ai_classification !== 'Other') {
|
|
275
|
+
stats.classifiedIncidents++;
|
|
276
|
+
}
|
|
277
|
+
totalConfidence += incident.ai_confidence;
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
if (incidents.length > 0) {
|
|
281
|
+
stats.averageConfidence = Math.round(totalConfidence / incidents.length);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
return stats;
|
|
285
|
+
},
|
|
286
|
+
|
|
287
|
+
// Utility functions
|
|
288
|
+
getDateDaysAgo: function(days) {
|
|
289
|
+
var date = new Date();
|
|
290
|
+
date.setDate(date.getDate() - days);
|
|
291
|
+
return date.toISOString().split('T')[0];
|
|
292
|
+
},
|
|
293
|
+
|
|
294
|
+
getDateToday: function() {
|
|
295
|
+
return new Date().toISOString().split('T')[0];
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
// Main execution based on input
|
|
300
|
+
if (input && input.action) {
|
|
301
|
+
data.result = OpenAIIncidentClassifier.processRequest(input.action, input.params || {});
|
|
302
|
+
} else {
|
|
303
|
+
// Default initialization
|
|
304
|
+
data.result = {
|
|
305
|
+
success: true,
|
|
306
|
+
message: 'Widget initialized successfully',
|
|
307
|
+
config: {
|
|
308
|
+
supports_openai: !!gs.getProperty('x_openai.api_key'),
|
|
309
|
+
fallback_enabled: true
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
})();
|