snow-flow 2.8.9 → 2.9.4
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/check-mcp-resources.sh +85 -0
- package/dist/config/snow-flow-config.js +1 -1
- package/dist/mcp/mcp-on-demand-proxy.d.ts +7 -0
- package/dist/mcp/mcp-on-demand-proxy.js +187 -0
- package/dist/mcp/servicenow-machine-learning-mcp.js +310 -60
- package/dist/mcp/servicenow-operations-mcp.d.ts +71 -1
- package/dist/mcp/servicenow-operations-mcp.js +44 -11
- package/dist/test-smart-limits.d.ts +13 -0
- package/dist/test-smart-limits.js +100 -0
- package/dist/utils/mcp-on-demand-manager.d.ts +69 -0
- package/dist/utils/mcp-on-demand-manager.js +309 -0
- package/dist/utils/mcp-process-manager.d.ts +58 -0
- package/dist/utils/mcp-process-manager.js +220 -0
- package/dist/utils/mcp-server-manager.js +50 -9
- package/dist/utils/mcp-singleton-lock.d.ts +4 -0
- package/dist/utils/mcp-singleton-lock.js +35 -8
- package/dist/utils/ml-data-fetcher.d.ts +66 -0
- package/dist/utils/ml-data-fetcher.js +288 -0
- package/dist/utils/servicenow-client.js +43 -17
- package/dist/utils/timeout-manager.d.ts +62 -0
- package/dist/utils/timeout-manager.js +352 -0
- package/package.json +1 -1
- package/test-ml-improvements.sh +76 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MCP Process Manager
|
|
4
|
+
* Prevents excessive MCP server spawning and manages resource limits
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.MCPProcessManager = void 0;
|
|
8
|
+
const child_process_1 = require("child_process");
|
|
9
|
+
const logger_js_1 = require("./logger.js");
|
|
10
|
+
const logger = new logger_js_1.Logger('MCPProcessManager');
|
|
11
|
+
class MCPProcessManager {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.MAX_MCP_SERVERS = parseInt(process.env.SNOW_MAX_MCP_SERVERS || '10');
|
|
14
|
+
this.MAX_MEMORY_MB = parseInt(process.env.SNOW_MCP_MEMORY_LIMIT || '1500');
|
|
15
|
+
this.CLEANUP_INTERVAL = 60000; // 1 minute
|
|
16
|
+
// Start periodic cleanup
|
|
17
|
+
this.startPeriodicCleanup();
|
|
18
|
+
}
|
|
19
|
+
static getInstance() {
|
|
20
|
+
if (!MCPProcessManager.instance) {
|
|
21
|
+
MCPProcessManager.instance = new MCPProcessManager();
|
|
22
|
+
}
|
|
23
|
+
return MCPProcessManager.instance;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Check if we can spawn a new MCP server
|
|
27
|
+
*/
|
|
28
|
+
canSpawnServer() {
|
|
29
|
+
const status = this.getSystemStatus();
|
|
30
|
+
if (status.processCount >= this.MAX_MCP_SERVERS) {
|
|
31
|
+
logger.warn(`❌ Cannot spawn: Already at max servers (${status.processCount}/${this.MAX_MCP_SERVERS})`);
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
if (status.memoryUsageMB > this.MAX_MEMORY_MB) {
|
|
35
|
+
logger.warn(`❌ Cannot spawn: Memory limit exceeded (${status.memoryUsageMB}MB > ${this.MAX_MEMORY_MB}MB)`);
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get current MCP system status
|
|
42
|
+
*/
|
|
43
|
+
getSystemStatus() {
|
|
44
|
+
try {
|
|
45
|
+
// Count MCP processes
|
|
46
|
+
const psOutput = (0, child_process_1.execSync)('ps aux | grep -E "mcp|servicenow.*mcp" | grep -v grep', {
|
|
47
|
+
encoding: 'utf8'
|
|
48
|
+
}).trim();
|
|
49
|
+
if (!psOutput) {
|
|
50
|
+
return {
|
|
51
|
+
processCount: 0,
|
|
52
|
+
memoryUsageMB: 0,
|
|
53
|
+
processes: []
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const lines = psOutput.split('\n');
|
|
57
|
+
const processes = [];
|
|
58
|
+
let totalMemory = 0;
|
|
59
|
+
for (const line of lines) {
|
|
60
|
+
const parts = line.split(/\s+/);
|
|
61
|
+
if (parts.length > 10) {
|
|
62
|
+
const pid = parseInt(parts[1]);
|
|
63
|
+
const memory = Math.round(parseInt(parts[5]) / 1024); // Convert KB to MB
|
|
64
|
+
const name = parts.slice(10).join(' ');
|
|
65
|
+
processes.push({ pid, memory, name });
|
|
66
|
+
totalMemory += memory;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
processCount: processes.length,
|
|
71
|
+
memoryUsageMB: totalMemory,
|
|
72
|
+
processes
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
// No MCP processes found
|
|
77
|
+
return {
|
|
78
|
+
processCount: 0,
|
|
79
|
+
memoryUsageMB: 0,
|
|
80
|
+
processes: []
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Kill duplicate MCP servers (keep only the newest)
|
|
86
|
+
*/
|
|
87
|
+
killDuplicates() {
|
|
88
|
+
const status = this.getSystemStatus();
|
|
89
|
+
// Group processes by server type
|
|
90
|
+
const serverGroups = new Map();
|
|
91
|
+
for (const proc of status.processes) {
|
|
92
|
+
// Extract server type from process name
|
|
93
|
+
const match = proc.name.match(/servicenow-([^-]+)-mcp\.js/);
|
|
94
|
+
if (match) {
|
|
95
|
+
const serverType = match[1];
|
|
96
|
+
if (!serverGroups.has(serverType)) {
|
|
97
|
+
serverGroups.set(serverType, []);
|
|
98
|
+
}
|
|
99
|
+
serverGroups.get(serverType).push({
|
|
100
|
+
pid: proc.pid,
|
|
101
|
+
memory: proc.memory
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// Kill duplicates (keep the first one)
|
|
106
|
+
for (const [serverType, procs] of serverGroups) {
|
|
107
|
+
if (procs.length > 1) {
|
|
108
|
+
logger.warn(`Found ${procs.length} instances of ${serverType}-mcp, killing duplicates...`);
|
|
109
|
+
// Sort by PID (older PIDs first) and keep the first one
|
|
110
|
+
procs.sort((a, b) => a.pid - b.pid);
|
|
111
|
+
for (let i = 1; i < procs.length; i++) {
|
|
112
|
+
try {
|
|
113
|
+
process.kill(procs[i].pid, 'SIGTERM');
|
|
114
|
+
logger.info(`Killed duplicate ${serverType}-mcp (PID: ${procs[i].pid})`);
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
// Process might already be dead
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Kill all MCP servers
|
|
125
|
+
*/
|
|
126
|
+
killAll() {
|
|
127
|
+
try {
|
|
128
|
+
(0, child_process_1.execSync)('pkill -f mcp', { encoding: 'utf8' });
|
|
129
|
+
logger.info('✅ Killed all MCP processes');
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
// pkill returns non-zero if no processes found
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Clean up excessive resources
|
|
137
|
+
*/
|
|
138
|
+
cleanup() {
|
|
139
|
+
const status = this.getSystemStatus();
|
|
140
|
+
if (status.processCount > this.MAX_MCP_SERVERS) {
|
|
141
|
+
logger.warn(`🧹 Cleaning up excessive MCP servers (${status.processCount} > ${this.MAX_MCP_SERVERS})`);
|
|
142
|
+
this.killDuplicates();
|
|
143
|
+
}
|
|
144
|
+
if (status.memoryUsageMB > this.MAX_MEMORY_MB) {
|
|
145
|
+
logger.warn(`🧹 Memory usage too high (${status.memoryUsageMB}MB), killing oldest processes...`);
|
|
146
|
+
// Sort by memory usage and kill the highest consumers
|
|
147
|
+
const sorted = status.processes.sort((a, b) => b.memory - a.memory);
|
|
148
|
+
let memoryFreed = 0;
|
|
149
|
+
for (const proc of sorted) {
|
|
150
|
+
if (status.memoryUsageMB - memoryFreed <= this.MAX_MEMORY_MB * 0.8) {
|
|
151
|
+
break; // Stop when we're at 80% of limit
|
|
152
|
+
}
|
|
153
|
+
try {
|
|
154
|
+
process.kill(proc.pid, 'SIGTERM');
|
|
155
|
+
memoryFreed += proc.memory;
|
|
156
|
+
logger.info(`Killed high-memory process (PID: ${proc.pid}, ${proc.memory}MB)`);
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
// Process might already be dead
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Start periodic cleanup
|
|
166
|
+
*/
|
|
167
|
+
startPeriodicCleanup() {
|
|
168
|
+
// Clear existing timer
|
|
169
|
+
if (this.cleanupTimer) {
|
|
170
|
+
clearInterval(this.cleanupTimer);
|
|
171
|
+
}
|
|
172
|
+
// Run cleanup periodically
|
|
173
|
+
this.cleanupTimer = setInterval(() => {
|
|
174
|
+
const status = this.getSystemStatus();
|
|
175
|
+
if (status.processCount > this.MAX_MCP_SERVERS * 0.8 ||
|
|
176
|
+
status.memoryUsageMB > this.MAX_MEMORY_MB * 0.8) {
|
|
177
|
+
logger.info('🔄 Running periodic MCP cleanup...');
|
|
178
|
+
this.cleanup();
|
|
179
|
+
}
|
|
180
|
+
}, this.CLEANUP_INTERVAL);
|
|
181
|
+
// Don't block process exit
|
|
182
|
+
this.cleanupTimer.unref();
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Stop periodic cleanup
|
|
186
|
+
*/
|
|
187
|
+
stopPeriodicCleanup() {
|
|
188
|
+
if (this.cleanupTimer) {
|
|
189
|
+
clearInterval(this.cleanupTimer);
|
|
190
|
+
this.cleanupTimer = undefined;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Get resource usage summary
|
|
195
|
+
*/
|
|
196
|
+
getResourceSummary() {
|
|
197
|
+
const status = this.getSystemStatus();
|
|
198
|
+
return `MCP Resources:
|
|
199
|
+
Processes: ${status.processCount}/${this.MAX_MCP_SERVERS} (${Math.round(status.processCount / this.MAX_MCP_SERVERS * 100)}%)
|
|
200
|
+
Memory: ${status.memoryUsageMB}MB/${this.MAX_MEMORY_MB}MB (${Math.round(status.memoryUsageMB / this.MAX_MEMORY_MB * 100)}%)
|
|
201
|
+
Status: ${this.getHealthStatus()}`;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Get health status
|
|
205
|
+
*/
|
|
206
|
+
getHealthStatus() {
|
|
207
|
+
const status = this.getSystemStatus();
|
|
208
|
+
const processPercent = status.processCount / this.MAX_MCP_SERVERS;
|
|
209
|
+
const memoryPercent = status.memoryUsageMB / this.MAX_MEMORY_MB;
|
|
210
|
+
if (processPercent > 0.9 || memoryPercent > 0.9) {
|
|
211
|
+
return 'critical';
|
|
212
|
+
}
|
|
213
|
+
if (processPercent > 0.7 || memoryPercent > 0.7) {
|
|
214
|
+
return 'warning';
|
|
215
|
+
}
|
|
216
|
+
return 'healthy';
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
exports.MCPProcessManager = MCPProcessManager;
|
|
220
|
+
//# sourceMappingURL=mcp-process-manager.js.map
|
|
@@ -14,6 +14,7 @@ const events_1 = require("events");
|
|
|
14
14
|
const os_1 = __importDefault(require("os"));
|
|
15
15
|
const unified_auth_store_js_1 = require("./unified-auth-store.js");
|
|
16
16
|
const mcp_singleton_lock_js_1 = require("./mcp-singleton-lock.js");
|
|
17
|
+
const mcp_process_manager_js_1 = require("./mcp-process-manager.js");
|
|
17
18
|
class MCPServerManager extends events_1.EventEmitter {
|
|
18
19
|
constructor(configPath) {
|
|
19
20
|
super();
|
|
@@ -148,6 +149,16 @@ class MCPServerManager extends events_1.EventEmitter {
|
|
|
148
149
|
if (server.status === 'running') {
|
|
149
150
|
return true; // Already running
|
|
150
151
|
}
|
|
152
|
+
// Check if we can spawn a new server
|
|
153
|
+
const processManager = mcp_process_manager_js_1.MCPProcessManager.getInstance();
|
|
154
|
+
if (!processManager.canSpawnServer()) {
|
|
155
|
+
// Try cleanup first
|
|
156
|
+
processManager.cleanup();
|
|
157
|
+
// Check again after cleanup
|
|
158
|
+
if (!processManager.canSpawnServer()) {
|
|
159
|
+
throw new Error('Cannot spawn server: resource limits exceeded. Too many MCP processes running.');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
151
162
|
server.status = 'starting';
|
|
152
163
|
this.emit('serverStarting', name);
|
|
153
164
|
try {
|
|
@@ -252,15 +263,20 @@ class MCPServerManager extends events_1.EventEmitter {
|
|
|
252
263
|
try {
|
|
253
264
|
// Try graceful shutdown first
|
|
254
265
|
server.process.kill('SIGTERM');
|
|
255
|
-
// Wait for graceful shutdown
|
|
266
|
+
// Wait for graceful shutdown with shorter timeout to prevent hanging
|
|
256
267
|
await new Promise((resolve) => {
|
|
257
268
|
const timeout = setTimeout(() => {
|
|
258
269
|
// Force kill if graceful shutdown fails
|
|
259
270
|
if (server.process) {
|
|
260
|
-
|
|
271
|
+
try {
|
|
272
|
+
server.process.kill('SIGKILL');
|
|
273
|
+
}
|
|
274
|
+
catch (e) {
|
|
275
|
+
// Process might already be dead
|
|
276
|
+
}
|
|
261
277
|
}
|
|
262
278
|
resolve(undefined);
|
|
263
|
-
},
|
|
279
|
+
}, 2000); // Reduced from 5000ms to 2000ms to prevent hanging
|
|
264
280
|
server.process?.on('exit', () => {
|
|
265
281
|
clearTimeout(timeout);
|
|
266
282
|
resolve(undefined);
|
|
@@ -287,12 +303,31 @@ class MCPServerManager extends events_1.EventEmitter {
|
|
|
287
303
|
if (!singletonLock.acquire()) {
|
|
288
304
|
throw new Error('❌ MCP servers already running. Cannot start duplicate instances.');
|
|
289
305
|
}
|
|
290
|
-
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
306
|
+
// Clean up any existing duplicates first
|
|
307
|
+
const processManager = mcp_process_manager_js_1.MCPProcessManager.getInstance();
|
|
308
|
+
processManager.killDuplicates();
|
|
309
|
+
console.log('✅ Starting all MCP servers (singleton protected with resource limits)...');
|
|
310
|
+
console.log(processManager.getResourceSummary());
|
|
311
|
+
// Start servers sequentially with delay to avoid resource spikes
|
|
312
|
+
let started = 0;
|
|
313
|
+
for (const name of Array.from(this.servers.keys())) {
|
|
314
|
+
try {
|
|
315
|
+
// Check resource limits before each start
|
|
316
|
+
if (!processManager.canSpawnServer()) {
|
|
317
|
+
console.warn(`⚠️ Skipping ${name} - resource limits reached`);
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
await this.startServer(name);
|
|
321
|
+
started++;
|
|
322
|
+
// Small delay between starts to avoid CPU spike
|
|
323
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
324
|
+
}
|
|
325
|
+
catch (error) {
|
|
326
|
+
console.error(`Failed to start server '${name}':`, error);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
console.log(`✅ Started ${started}/${this.servers.size} MCP servers`);
|
|
330
|
+
console.log(processManager.getResourceSummary());
|
|
296
331
|
}
|
|
297
332
|
/**
|
|
298
333
|
* Stop all running MCP servers
|
|
@@ -303,6 +338,12 @@ class MCPServerManager extends events_1.EventEmitter {
|
|
|
303
338
|
return false;
|
|
304
339
|
}));
|
|
305
340
|
await Promise.all(promises);
|
|
341
|
+
// Release singleton lock after stopping all servers
|
|
342
|
+
const singletonLock = (0, mcp_singleton_lock_js_1.getMCPSingletonLock)();
|
|
343
|
+
if (singletonLock.isAcquired()) {
|
|
344
|
+
singletonLock.release();
|
|
345
|
+
console.log('✅ Released MCP singleton lock after stopping all servers');
|
|
346
|
+
}
|
|
306
347
|
}
|
|
307
348
|
/**
|
|
308
349
|
* Get status of a specific server
|
|
@@ -15,6 +15,10 @@ export declare class MCPSingletonLock {
|
|
|
15
15
|
* Release the singleton lock
|
|
16
16
|
*/
|
|
17
17
|
release(): void;
|
|
18
|
+
/**
|
|
19
|
+
* Release the singleton lock without blocking (for graceful shutdown)
|
|
20
|
+
*/
|
|
21
|
+
releaseAsync(): Promise<void>;
|
|
18
22
|
/**
|
|
19
23
|
* Check if lock is currently held by this process
|
|
20
24
|
*/
|
|
@@ -71,6 +71,18 @@ class MCPSingletonLock {
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Release the singleton lock without blocking (for graceful shutdown)
|
|
76
|
+
*/
|
|
77
|
+
releaseAsync() {
|
|
78
|
+
return new Promise((resolve) => {
|
|
79
|
+
// Use setImmediate to avoid blocking
|
|
80
|
+
setImmediate(() => {
|
|
81
|
+
this.release();
|
|
82
|
+
resolve();
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
74
86
|
/**
|
|
75
87
|
* Check if lock is currently held by this process
|
|
76
88
|
*/
|
|
@@ -82,20 +94,35 @@ class MCPSingletonLock {
|
|
|
82
94
|
*/
|
|
83
95
|
setupCleanupHandlers() {
|
|
84
96
|
const cleanup = () => {
|
|
85
|
-
|
|
97
|
+
// Use non-blocking release to prevent hanging during shutdown
|
|
98
|
+
setImmediate(() => {
|
|
99
|
+
this.release();
|
|
100
|
+
});
|
|
86
101
|
};
|
|
87
|
-
|
|
88
|
-
process.
|
|
89
|
-
process.
|
|
90
|
-
process.
|
|
102
|
+
// Remove existing handlers to prevent duplicate registrations
|
|
103
|
+
process.removeAllListeners('exit');
|
|
104
|
+
process.removeAllListeners('SIGINT');
|
|
105
|
+
process.removeAllListeners('SIGTERM');
|
|
106
|
+
process.once('exit', cleanup);
|
|
107
|
+
process.once('SIGINT', () => {
|
|
108
|
+
cleanup();
|
|
109
|
+
// Allow graceful exit after cleanup
|
|
110
|
+
setTimeout(() => process.exit(0), 100);
|
|
111
|
+
});
|
|
112
|
+
process.once('SIGTERM', () => {
|
|
113
|
+
cleanup();
|
|
114
|
+
// Allow graceful exit after cleanup
|
|
115
|
+
setTimeout(() => process.exit(0), 100);
|
|
116
|
+
});
|
|
117
|
+
process.once('uncaughtException', (error) => {
|
|
91
118
|
logger.error('Uncaught exception, releasing MCP lock:', error);
|
|
92
119
|
cleanup();
|
|
93
|
-
process.exit(1);
|
|
120
|
+
setTimeout(() => process.exit(1), 100);
|
|
94
121
|
});
|
|
95
|
-
process.
|
|
122
|
+
process.once('unhandledRejection', (reason) => {
|
|
96
123
|
logger.error('Unhandled rejection, releasing MCP lock:', reason);
|
|
97
124
|
cleanup();
|
|
98
|
-
process.exit(1);
|
|
125
|
+
setTimeout(() => process.exit(1), 100);
|
|
99
126
|
});
|
|
100
127
|
}
|
|
101
128
|
/**
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smart ML Data Fetcher
|
|
3
|
+
* Handles intelligent data fetching for ML training with batching and field discovery
|
|
4
|
+
* Prevents token limit errors and optimizes data retrieval
|
|
5
|
+
*/
|
|
6
|
+
export interface MLDataFetchOptions {
|
|
7
|
+
table: string;
|
|
8
|
+
query?: string;
|
|
9
|
+
totalSamples?: number;
|
|
10
|
+
batchSize?: number;
|
|
11
|
+
fields?: string[];
|
|
12
|
+
discoverFields?: boolean;
|
|
13
|
+
includeContent?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface FieldDiscoveryResult {
|
|
16
|
+
allFields: string[];
|
|
17
|
+
recommendedFields: string[];
|
|
18
|
+
sampleData: any[];
|
|
19
|
+
}
|
|
20
|
+
export interface BatchFetchResult {
|
|
21
|
+
data: any[];
|
|
22
|
+
totalFetched: number;
|
|
23
|
+
batchesProcessed: number;
|
|
24
|
+
fields: string[];
|
|
25
|
+
}
|
|
26
|
+
export declare class MLDataFetcher {
|
|
27
|
+
private operationsMCP;
|
|
28
|
+
constructor(operationsMCP: any);
|
|
29
|
+
/**
|
|
30
|
+
* Smart fetch with automatic field discovery and batching
|
|
31
|
+
*/
|
|
32
|
+
smartFetch(options: MLDataFetchOptions): Promise<BatchFetchResult>;
|
|
33
|
+
/**
|
|
34
|
+
* Get total count of records matching query
|
|
35
|
+
*/
|
|
36
|
+
private getRecordCount;
|
|
37
|
+
/**
|
|
38
|
+
* Discover available fields by sampling a few records
|
|
39
|
+
*/
|
|
40
|
+
private discoverFields;
|
|
41
|
+
/**
|
|
42
|
+
* Fetch a single batch of data
|
|
43
|
+
*/
|
|
44
|
+
private fetchBatch;
|
|
45
|
+
/**
|
|
46
|
+
* Extract data from MCP tool result
|
|
47
|
+
*/
|
|
48
|
+
private extractDataFromResult;
|
|
49
|
+
/**
|
|
50
|
+
* Calculate optimal batch size based on data characteristics
|
|
51
|
+
*/
|
|
52
|
+
private calculateOptimalBatchSize;
|
|
53
|
+
/**
|
|
54
|
+
* Select appropriate fields for ML training
|
|
55
|
+
*/
|
|
56
|
+
private selectMLFields;
|
|
57
|
+
/**
|
|
58
|
+
* Get default fields for a table type
|
|
59
|
+
*/
|
|
60
|
+
private getDefaultFields;
|
|
61
|
+
/**
|
|
62
|
+
* Get key fields that should always be included
|
|
63
|
+
*/
|
|
64
|
+
private getKeyFields;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=ml-data-fetcher.d.ts.map
|