snow-flow 3.3.3 → 3.3.5
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/README.md +83 -6
- package/dist/cli-new-prompt.d.ts +2 -0
- package/dist/cli-new-prompt.js +420 -0
- package/dist/cli.js +119 -887
- package/dist/dynamic-version.js +1 -1
- package/dist/mcp/servicenow-deployment-mcp.js +507 -46
- package/dist/mcp/servicenow-machine-learning-mcp.d.ts +15 -0
- package/dist/mcp/servicenow-machine-learning-mcp.js +499 -73
- package/dist/queen/servicenow-queen.d.ts +1 -45
- package/dist/queen/servicenow-queen.js +615 -566
- package/dist/utils/ml-data-fetcher.d.ts +1 -1
- package/dist/utils/ml-data-fetcher.js +85 -24
- package/package.json +2 -2
- package/src/cli.ts.backup-20250809-125529 +4773 -0
|
@@ -140,12 +140,13 @@ class MLDataFetcher {
|
|
|
140
140
|
*/
|
|
141
141
|
async fetchBatch(table, query, limit, offset, fields, includeContent = true) {
|
|
142
142
|
try {
|
|
143
|
-
//
|
|
144
|
-
|
|
143
|
+
// ServiceNow uses sysparm_offset for pagination, not ORDERBY syntax
|
|
144
|
+
// The query remains unchanged, offset is handled by the tool
|
|
145
145
|
const result = await this.operationsMCP.handleTool('snow_query_table', {
|
|
146
146
|
table,
|
|
147
|
-
query:
|
|
147
|
+
query: query || '',
|
|
148
148
|
limit,
|
|
149
|
+
offset, // Pass offset directly - the tool should handle sysparm_offset
|
|
149
150
|
fields,
|
|
150
151
|
include_content: includeContent
|
|
151
152
|
});
|
|
@@ -153,11 +154,27 @@ class MLDataFetcher {
|
|
|
153
154
|
}
|
|
154
155
|
catch (error) {
|
|
155
156
|
logger.error(`Failed to fetch batch (offset: ${offset}, limit: ${limit}):`, error);
|
|
157
|
+
// If offset isn't supported, try without it for first batch
|
|
158
|
+
if (offset === 0) {
|
|
159
|
+
try {
|
|
160
|
+
const fallbackResult = await this.operationsMCP.handleTool('snow_query_table', {
|
|
161
|
+
table,
|
|
162
|
+
query: query || '',
|
|
163
|
+
limit,
|
|
164
|
+
fields,
|
|
165
|
+
include_content: includeContent
|
|
166
|
+
});
|
|
167
|
+
return this.extractDataFromResult(fallbackResult);
|
|
168
|
+
}
|
|
169
|
+
catch (fallbackError) {
|
|
170
|
+
logger.error('Fallback batch fetch also failed:', fallbackError);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
156
173
|
return [];
|
|
157
174
|
}
|
|
158
175
|
}
|
|
159
176
|
/**
|
|
160
|
-
* Extract data from MCP tool result
|
|
177
|
+
* Extract data from MCP tool result - More robust parsing
|
|
161
178
|
*/
|
|
162
179
|
extractDataFromResult(result) {
|
|
163
180
|
if (!result?.content?.[0]?.text) {
|
|
@@ -165,30 +182,71 @@ class MLDataFetcher {
|
|
|
165
182
|
}
|
|
166
183
|
try {
|
|
167
184
|
const text = result.content[0].text;
|
|
168
|
-
//
|
|
169
|
-
|
|
170
|
-
const
|
|
171
|
-
if (
|
|
172
|
-
return
|
|
185
|
+
// Method 1: Direct JSON parsing
|
|
186
|
+
try {
|
|
187
|
+
const parsed = JSON.parse(text);
|
|
188
|
+
if (Array.isArray(parsed)) {
|
|
189
|
+
return parsed;
|
|
190
|
+
}
|
|
191
|
+
if (parsed.result && Array.isArray(parsed.result)) {
|
|
192
|
+
return parsed.result;
|
|
193
|
+
}
|
|
194
|
+
if (parsed.data && Array.isArray(parsed.data)) {
|
|
195
|
+
return parsed.data;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
catch (jsonError) {
|
|
199
|
+
// Not pure JSON, try other methods
|
|
200
|
+
}
|
|
201
|
+
// Method 2: Extract JSON array from text
|
|
202
|
+
const jsonArrayMatch = text.match(/\[\s*\{[\s\S]*\}\s*\]/);
|
|
203
|
+
if (jsonArrayMatch) {
|
|
204
|
+
try {
|
|
205
|
+
return JSON.parse(jsonArrayMatch[0]);
|
|
206
|
+
}
|
|
207
|
+
catch (e) {
|
|
208
|
+
// Continue to next method
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// Method 3: Extract individual JSON objects
|
|
212
|
+
const jsonObjects = [];
|
|
213
|
+
const objectMatches = text.matchAll(/\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}/g);
|
|
214
|
+
for (const match of objectMatches) {
|
|
215
|
+
try {
|
|
216
|
+
const obj = JSON.parse(match[0]);
|
|
217
|
+
if (obj && typeof obj === 'object') {
|
|
218
|
+
jsonObjects.push(obj);
|
|
219
|
+
}
|
|
173
220
|
}
|
|
221
|
+
catch (e) {
|
|
222
|
+
// Skip invalid JSON
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (jsonObjects.length > 0) {
|
|
226
|
+
return jsonObjects;
|
|
174
227
|
}
|
|
175
|
-
//
|
|
228
|
+
// Method 4: Parse formatted text output (fallback)
|
|
176
229
|
const lines = text.split('\n');
|
|
177
230
|
const data = [];
|
|
178
231
|
let currentRecord = null;
|
|
179
232
|
for (const line of lines) {
|
|
180
|
-
|
|
181
|
-
|
|
233
|
+
// Detect new record
|
|
234
|
+
if (line.match(/^(Record \d+|\d+\.|#{1,3}|-)/) ||
|
|
235
|
+
(line.includes('sys_id:') && currentRecord)) {
|
|
236
|
+
if (currentRecord && Object.keys(currentRecord).length > 0) {
|
|
182
237
|
data.push(currentRecord);
|
|
183
238
|
}
|
|
184
239
|
currentRecord = {};
|
|
185
240
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
241
|
+
// Extract key-value pairs
|
|
242
|
+
if (currentRecord !== null) {
|
|
243
|
+
const kvMatch = line.match(/^\s*[-*]?\s*([\w_]+)\s*[:=]\s*(.+)$/);
|
|
244
|
+
if (kvMatch) {
|
|
245
|
+
const key = kvMatch[1].trim();
|
|
246
|
+
const value = kvMatch[2].trim();
|
|
247
|
+
if (key && value && value !== 'null' && value !== 'undefined') {
|
|
248
|
+
currentRecord[key] = value;
|
|
249
|
+
}
|
|
192
250
|
}
|
|
193
251
|
}
|
|
194
252
|
}
|
|
@@ -206,16 +264,19 @@ class MLDataFetcher {
|
|
|
206
264
|
* Calculate optimal batch size based on data characteristics
|
|
207
265
|
*/
|
|
208
266
|
calculateOptimalBatchSize(totalRecords, requestedBatchSize, numFields) {
|
|
209
|
-
//
|
|
210
|
-
const avgTokensPerField =
|
|
211
|
-
const
|
|
212
|
-
const
|
|
267
|
+
// More conservative token estimation for ServiceNow data
|
|
268
|
+
const avgTokensPerField = 15; // ServiceNow fields can be verbose
|
|
269
|
+
const systemFieldOverhead = 100; // System fields add overhead
|
|
270
|
+
const tokensPerRecord = (numFields * avgTokensPerField) + systemFieldOverhead;
|
|
271
|
+
const maxTokensPerBatch = 15000; // More conservative limit for safety
|
|
213
272
|
// Calculate max records per batch based on token limit
|
|
214
273
|
const maxRecordsPerBatch = Math.floor(maxTokensPerBatch / tokensPerRecord);
|
|
215
274
|
// Use the smaller of requested batch size and calculated max
|
|
216
275
|
const optimalSize = Math.min(requestedBatchSize, maxRecordsPerBatch);
|
|
217
|
-
//
|
|
218
|
-
|
|
276
|
+
// For ML training, we want reasonable batch sizes (20-100 typically)
|
|
277
|
+
const minBatchSize = Math.min(20, totalRecords);
|
|
278
|
+
const maxBatchSize = Math.min(100, totalRecords);
|
|
279
|
+
return Math.max(minBatchSize, Math.min(optimalSize, maxBatchSize));
|
|
219
280
|
}
|
|
220
281
|
/**
|
|
221
282
|
* Select appropriate fields for ML training
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "snow-flow",
|
|
3
|
-
"version": "3.3.
|
|
4
|
-
"description": "Snow-Flow v3.3.
|
|
3
|
+
"version": "3.3.5",
|
|
4
|
+
"description": "Snow-Flow v3.3.5: CRITICAL ML FIX - Machine Learning MCP now fully functional with TensorFlow.js! Fixed pagination, ServiceNow API integration, data parsing, and training workflow. Real progress tracking, intelligent error messages, and automatic fallback when PA/PI not available. Train incident classifiers, predict change risks, forecast volumes, and detect anomalies - all working with real ServiceNow data. Enhanced MCP servers with real-time progress indicators and comprehensive operation logging. 180+ MCP tools across 17 specialized servers.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "commonjs",
|
|
7
7
|
"bin": {
|