@vfarcic/dot-ai 0.192.0 → 0.194.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.
- package/README.md +6 -6
- package/dist/core/agent-display.d.ts +2 -4
- package/dist/core/agent-display.d.ts.map +1 -1
- package/dist/core/agent-display.js +4 -12
- package/dist/core/base-vector-service.d.ts +6 -0
- package/dist/core/base-vector-service.d.ts.map +1 -1
- package/dist/core/base-vector-service.js +18 -8
- package/dist/core/capabilities.d.ts +12 -0
- package/dist/core/capabilities.d.ts.map +1 -1
- package/dist/core/capability-operations.d.ts +3 -0
- package/dist/core/capability-operations.d.ts.map +1 -1
- package/dist/core/capability-operations.js +88 -5
- package/dist/core/capability-scan-workflow.d.ts +35 -5
- package/dist/core/capability-scan-workflow.d.ts.map +1 -1
- package/dist/core/capability-scan-workflow.js +169 -145
- package/dist/core/capability-vector-service.d.ts +11 -2
- package/dist/core/capability-vector-service.d.ts.map +1 -1
- package/dist/core/capability-vector-service.js +50 -0
- package/dist/core/discovery.d.ts +34 -0
- package/dist/core/discovery.d.ts.map +1 -1
- package/dist/core/discovery.js +105 -19
- package/dist/core/index.d.ts +0 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -6
- package/dist/core/kubectl-tools.d.ts +5 -0
- package/dist/core/kubectl-tools.d.ts.map +1 -1
- package/dist/core/kubectl-tools.js +74 -2
- package/dist/core/kubernetes-utils.d.ts +1 -0
- package/dist/core/kubernetes-utils.d.ts.map +1 -1
- package/dist/core/kubernetes-utils.js +92 -49
- package/dist/core/packaging.d.ts.map +1 -1
- package/dist/core/packaging.js +1 -0
- package/dist/core/resource-tools.d.ts +163 -1
- package/dist/core/resource-tools.d.ts.map +1 -1
- package/dist/core/resource-tools.js +343 -23
- package/dist/core/resource-vector-service.d.ts +17 -0
- package/dist/core/resource-vector-service.d.ts.map +1 -1
- package/dist/core/resource-vector-service.js +67 -3
- package/dist/core/telemetry/client.d.ts +16 -0
- package/dist/core/telemetry/client.d.ts.map +1 -0
- package/dist/core/telemetry/client.js +293 -0
- package/dist/core/telemetry/config.d.ts +12 -0
- package/dist/core/telemetry/config.d.ts.map +1 -0
- package/dist/core/telemetry/config.js +130 -0
- package/dist/core/telemetry/index.d.ts +30 -0
- package/dist/core/telemetry/index.d.ts.map +1 -0
- package/dist/core/telemetry/index.js +49 -0
- package/dist/core/telemetry/types.d.ts +125 -0
- package/dist/core/telemetry/types.d.ts.map +1 -0
- package/dist/core/telemetry/types.js +7 -0
- package/dist/core/tracing/index.d.ts +1 -1
- package/dist/core/tracing/index.d.ts.map +1 -1
- package/dist/core/tracing/tool-tracing.d.ts +11 -2
- package/dist/core/tracing/tool-tracing.d.ts.map +1 -1
- package/dist/core/tracing/tool-tracing.js +17 -3
- package/dist/core/vector-db-service.d.ts +7 -0
- package/dist/core/vector-db-service.d.ts.map +1 -1
- package/dist/core/vector-db-service.js +165 -61
- package/dist/core/visualization.d.ts +16 -1
- package/dist/core/visualization.d.ts.map +1 -1
- package/dist/core/visualization.js +64 -1
- package/dist/interfaces/mcp.d.ts +6 -0
- package/dist/interfaces/mcp.d.ts.map +1 -1
- package/dist/interfaces/mcp.js +36 -7
- package/dist/interfaces/rest-api.d.ts +63 -2
- package/dist/interfaces/rest-api.d.ts.map +1 -1
- package/dist/interfaces/rest-api.js +611 -51
- package/dist/mcp/server.js +55 -9
- package/dist/tools/answer-question.d.ts.map +1 -1
- package/dist/tools/answer-question.js +18 -0
- package/dist/tools/choose-solution.d.ts.map +1 -1
- package/dist/tools/choose-solution.js +22 -1
- package/dist/tools/deploy-manifests.d.ts.map +1 -1
- package/dist/tools/deploy-manifests.js +16 -2
- package/dist/tools/generate-manifests.d.ts.map +1 -1
- package/dist/tools/generate-manifests.js +12 -18
- package/dist/tools/operate.d.ts.map +1 -1
- package/dist/tools/operate.js +3 -11
- package/dist/tools/organizational-data.d.ts +1 -1
- package/dist/tools/organizational-data.d.ts.map +1 -1
- package/dist/tools/organizational-data.js +8 -17
- package/dist/tools/project-setup.d.ts.map +1 -1
- package/dist/tools/project-setup.js +5 -18
- package/dist/tools/query.d.ts +2 -11
- package/dist/tools/query.d.ts.map +1 -1
- package/dist/tools/query.js +63 -44
- package/dist/tools/recommend.d.ts +18 -1
- package/dist/tools/recommend.d.ts.map +1 -1
- package/dist/tools/recommend.js +44 -10
- package/dist/tools/remediate.d.ts.map +1 -1
- package/dist/tools/remediate.js +2 -24
- package/dist/tools/version.d.ts.map +1 -1
- package/dist/tools/version.js +4 -7
- package/package.json +2 -1
- package/prompts/partials/query-simple-output.md +11 -0
- package/prompts/partials/visualization-output.md +93 -0
- package/prompts/query-system.md +8 -12
- package/prompts/resource-selection.md +4 -0
- package/prompts/visualize.md +1 -68
- package/scripts/dot-ai.nu +1 -0
- package/scripts/reset-sync-and-scan-test-cluster.sh +120 -0
- package/shared-prompts/prd-create.md +1 -1
- package/dist/core/feedback.d.ts +0 -43
- package/dist/core/feedback.d.ts.map +0 -1
- package/dist/core/feedback.js +0 -98
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* specification, processing mode selection, and the actual scanning process
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.scanSingleResource = scanSingleResource;
|
|
9
10
|
exports.handleResourceSelection = handleResourceSelection;
|
|
10
11
|
exports.handleResourceSpecification = handleResourceSpecification;
|
|
11
12
|
exports.handleScanning = handleScanning;
|
|
@@ -13,24 +14,126 @@ const discovery_1 = require("./discovery");
|
|
|
13
14
|
const capabilities_1 = require("./capabilities");
|
|
14
15
|
const ai_provider_factory_1 = require("./ai-provider-factory");
|
|
15
16
|
/**
|
|
16
|
-
*
|
|
17
|
+
* Scan a single resource - fetches all data, runs AI inference, stores to DB
|
|
18
|
+
* This is the core function that both full scan and targeted scan call for each resource.
|
|
17
19
|
*/
|
|
18
|
-
function
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
async function scanSingleResource(resourceName, discovery, engine, capabilityService, logger, requestId, interactionId) {
|
|
21
|
+
try {
|
|
22
|
+
// Step 1: Get resource metadata (including printerColumns for CRDs)
|
|
23
|
+
let metadata;
|
|
24
|
+
if (resourceName.includes('.')) {
|
|
25
|
+
// This is a CRD - fetch CRD data to get metadata including printerColumns
|
|
26
|
+
const dotIndex = resourceName.indexOf('.');
|
|
27
|
+
const kind = resourceName.substring(0, dotIndex);
|
|
28
|
+
const group = resourceName.substring(dotIndex + 1);
|
|
29
|
+
// Try common plural patterns to find CRD
|
|
30
|
+
const pluralGuesses = [
|
|
31
|
+
kind.toLowerCase() + 's',
|
|
32
|
+
kind.toLowerCase().endsWith('y') ? kind.toLowerCase().slice(0, -1) + 'ies' : null,
|
|
33
|
+
kind.toLowerCase().endsWith('s') ? kind.toLowerCase() + 'es' : null
|
|
34
|
+
].filter(Boolean);
|
|
35
|
+
for (const plural of pluralGuesses) {
|
|
36
|
+
try {
|
|
37
|
+
const crdName = `${plural}.${group}`;
|
|
38
|
+
const crdData = await discovery.getCRDData(crdName);
|
|
39
|
+
const storageVersion = crdData.versions.find(v => v.storage) || crdData.versions[0];
|
|
40
|
+
metadata = {
|
|
41
|
+
apiVersion: `${crdData.group}/${crdData.version}`,
|
|
42
|
+
version: crdData.version,
|
|
43
|
+
group: crdData.group,
|
|
44
|
+
resourcePlural: crdData.resourcePlural,
|
|
45
|
+
printerColumns: storageVersion?.additionalPrinterColumns
|
|
46
|
+
};
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// Try next plural form
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// Step 2: Get resource definition via kubectl explain
|
|
55
|
+
let resourceDefinition;
|
|
56
|
+
try {
|
|
57
|
+
resourceDefinition = await discovery.explainResource(resourceName);
|
|
58
|
+
}
|
|
59
|
+
catch (explainError) {
|
|
60
|
+
// If explain fails and resource has a dot, try with just the Kind
|
|
61
|
+
if (resourceName.includes('.')) {
|
|
62
|
+
const resourceKind = resourceName.split('.')[0];
|
|
63
|
+
resourceDefinition = await discovery.explainResource(resourceKind);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
throw explainError;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// If no CRD metadata, parse from kubectl explain output
|
|
70
|
+
if (!metadata && resourceDefinition) {
|
|
71
|
+
const lines = resourceDefinition.split('\n');
|
|
72
|
+
const groupLine = lines.find((line) => line.startsWith('GROUP:'));
|
|
73
|
+
const versionLine = lines.find((line) => line.startsWith('VERSION:'));
|
|
74
|
+
if (versionLine) {
|
|
75
|
+
const group = groupLine ? groupLine.replace('GROUP:', '').trim() : '';
|
|
76
|
+
const version = versionLine.replace('VERSION:', '').trim();
|
|
77
|
+
const apiVersion = group ? `${group}/${version}` : version;
|
|
78
|
+
// For core resources, derive plural from kind
|
|
79
|
+
const kind = resourceName.includes('.') ? resourceName.split('.')[0] : resourceName;
|
|
80
|
+
const resourcePlural = kind.toLowerCase() + 's';
|
|
81
|
+
metadata = { apiVersion, version, group, resourcePlural };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Step 3: Run AI inference
|
|
85
|
+
const capability = await engine.inferCapabilities(resourceName, resourceDefinition, interactionId, metadata?.apiVersion, metadata?.version, metadata?.group);
|
|
86
|
+
const capabilityId = capabilities_1.CapabilityInferenceEngine.generateCapabilityId(resourceName);
|
|
87
|
+
// Step 4: Set printer columns
|
|
88
|
+
const nameColumn = {
|
|
89
|
+
name: 'Name',
|
|
90
|
+
type: 'string',
|
|
91
|
+
jsonPath: '.metadata.name',
|
|
92
|
+
description: 'Resource name',
|
|
93
|
+
priority: 0
|
|
94
|
+
};
|
|
95
|
+
if (metadata?.printerColumns && metadata.printerColumns.length > 0) {
|
|
96
|
+
// Use printer columns from CRD metadata (includes jsonPath)
|
|
97
|
+
capability.printerColumns = [nameColumn, ...metadata.printerColumns];
|
|
98
|
+
}
|
|
99
|
+
else if (metadata?.apiVersion && metadata?.resourcePlural) {
|
|
100
|
+
// Fall back to Table API for core resources
|
|
101
|
+
try {
|
|
102
|
+
const printerColumns = await discovery.getPrinterColumns(metadata.resourcePlural, metadata.apiVersion);
|
|
103
|
+
capability.printerColumns = printerColumns;
|
|
104
|
+
}
|
|
105
|
+
catch (printerError) {
|
|
106
|
+
logger.warn(`Failed to fetch printer columns for ${resourceName}`, {
|
|
107
|
+
requestId,
|
|
108
|
+
resource: resourceName,
|
|
109
|
+
error: printerError instanceof Error ? printerError.message : String(printerError)
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// Step 5: Store to DB
|
|
114
|
+
await capabilityService.storeCapability(capability);
|
|
115
|
+
return {
|
|
116
|
+
success: true,
|
|
117
|
+
resource: resourceName,
|
|
118
|
+
id: capabilityId,
|
|
119
|
+
capabilities: capability.capabilities,
|
|
120
|
+
providers: capability.providers,
|
|
121
|
+
complexity: capability.complexity,
|
|
122
|
+
confidence: capability.confidence
|
|
123
|
+
};
|
|
29
124
|
}
|
|
30
|
-
|
|
31
|
-
|
|
125
|
+
catch (error) {
|
|
126
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
127
|
+
logger.error(`Failed to scan resource ${resourceName}`, error, {
|
|
128
|
+
requestId,
|
|
129
|
+
resource: resourceName
|
|
130
|
+
});
|
|
131
|
+
return {
|
|
132
|
+
success: false,
|
|
133
|
+
resource: resourceName,
|
|
134
|
+
error: errorMessage
|
|
135
|
+
};
|
|
32
136
|
}
|
|
33
|
-
return userFriendlyMessage;
|
|
34
137
|
}
|
|
35
138
|
/**
|
|
36
139
|
* Handle resource selection step
|
|
@@ -200,11 +303,17 @@ async function handleResourceSpecification(session, args, logger, requestId, cap
|
|
|
200
303
|
}
|
|
201
304
|
};
|
|
202
305
|
}
|
|
203
|
-
|
|
306
|
+
logger.info('Resource specification received', {
|
|
307
|
+
requestId,
|
|
308
|
+
sessionId: session.sessionId,
|
|
309
|
+
resourceCount: resources.length,
|
|
310
|
+
resources
|
|
311
|
+
});
|
|
312
|
+
// Transition directly to scanning - scanSingleResource will fetch metadata for each
|
|
204
313
|
transitionCapabilitySession(session, 'scanning', {
|
|
205
314
|
selectedResources: resources,
|
|
206
315
|
resourceList: args.resourceList,
|
|
207
|
-
currentResourceIndex: 0
|
|
316
|
+
currentResourceIndex: 0
|
|
208
317
|
}, args);
|
|
209
318
|
// Begin actual capability scanning and return completion summary
|
|
210
319
|
return await handleScanningFn(session, { ...args, response: undefined }, logger, requestId, capabilityService, parseNumericResponse, transitionCapabilitySession, cleanupCapabilitySession, createCapabilityScanCompletionResponse);
|
|
@@ -247,19 +356,21 @@ async function handleScanning(session, args, logger, requestId, capabilityServic
|
|
|
247
356
|
// For 'all' mode, discover actual cluster resources first
|
|
248
357
|
try {
|
|
249
358
|
logger.info('Discovering all cluster resources for capability scanning', { requestId, sessionId: session.sessionId });
|
|
250
|
-
// Import discovery engine
|
|
251
359
|
const discovery = new discovery_1.KubernetesDiscovery();
|
|
252
360
|
await discovery.connect();
|
|
253
361
|
// Discover all available resources
|
|
254
362
|
const resourceMap = await discovery.discoverResources();
|
|
255
363
|
const allResources = [...resourceMap.resources, ...resourceMap.custom];
|
|
256
|
-
// Extract resource names
|
|
364
|
+
// Extract resource names only - scanSingleResource will fetch metadata for each
|
|
257
365
|
const discoveredResourceNames = [];
|
|
258
|
-
const resourceMetadata = {};
|
|
259
366
|
for (const resource of allResources) {
|
|
260
367
|
let resourceName = 'unknown-resource';
|
|
261
|
-
// For CRDs (custom resources),
|
|
262
|
-
if (resource
|
|
368
|
+
// For CRDs (custom resources), use Kind.group format
|
|
369
|
+
if ('kind' in resource && resource.kind && 'group' in resource && resource.group) {
|
|
370
|
+
resourceName = `${resource.kind}.${resource.group}`;
|
|
371
|
+
}
|
|
372
|
+
// For CRDs with name format "plural.group"
|
|
373
|
+
else if (resource.name && resource.name.includes('.')) {
|
|
263
374
|
resourceName = resource.name;
|
|
264
375
|
}
|
|
265
376
|
// For standard resources, use kind
|
|
@@ -272,36 +383,13 @@ async function handleScanning(session, args, logger, requestId, capabilityServic
|
|
|
272
383
|
}
|
|
273
384
|
if (resourceName !== 'unknown-resource') {
|
|
274
385
|
discoveredResourceNames.push(resourceName);
|
|
275
|
-
// Store apiVersion metadata for later use
|
|
276
|
-
// Handle both EnhancedResource (has apiVersion) and EnhancedCRD (has group+version)
|
|
277
|
-
let apiVersion = '';
|
|
278
|
-
let version = '';
|
|
279
|
-
let group = '';
|
|
280
|
-
if ('apiVersion' in resource) {
|
|
281
|
-
// EnhancedResource type
|
|
282
|
-
apiVersion = resource.apiVersion || '';
|
|
283
|
-
version = apiVersion.includes('/') ? apiVersion.split('/')[1] : apiVersion;
|
|
284
|
-
group = resource.group || '';
|
|
285
|
-
}
|
|
286
|
-
else {
|
|
287
|
-
// EnhancedCRD type - construct apiVersion from group and version
|
|
288
|
-
group = resource.group || '';
|
|
289
|
-
version = resource.version || '';
|
|
290
|
-
apiVersion = group ? `${group}/${version}` : version;
|
|
291
|
-
}
|
|
292
|
-
resourceMetadata[resourceName] = {
|
|
293
|
-
apiVersion,
|
|
294
|
-
version,
|
|
295
|
-
group
|
|
296
|
-
};
|
|
297
386
|
}
|
|
298
387
|
}
|
|
299
388
|
logger.info('Discovered cluster resources for capability scanning', {
|
|
300
389
|
requestId,
|
|
301
390
|
sessionId: session.sessionId,
|
|
302
391
|
totalDiscovered: discoveredResourceNames.length,
|
|
303
|
-
sampleResources: discoveredResourceNames.slice(0, 5)
|
|
304
|
-
metadataPreserved: Object.keys(resourceMetadata).length
|
|
392
|
+
sampleResources: discoveredResourceNames.slice(0, 5)
|
|
305
393
|
});
|
|
306
394
|
if (discoveredResourceNames.length === 0) {
|
|
307
395
|
return {
|
|
@@ -315,10 +403,9 @@ async function handleScanning(session, args, logger, requestId, capabilityServic
|
|
|
315
403
|
}
|
|
316
404
|
};
|
|
317
405
|
}
|
|
318
|
-
// Update session with discovered resources
|
|
406
|
+
// Update session with discovered resources
|
|
319
407
|
transitionCapabilitySession(session, 'scanning', {
|
|
320
408
|
selectedResources: discoveredResourceNames,
|
|
321
|
-
resourceMetadata: resourceMetadata,
|
|
322
409
|
currentResourceIndex: 0
|
|
323
410
|
}, args);
|
|
324
411
|
// Fall through to batch processing with discovered resources
|
|
@@ -396,127 +483,64 @@ async function handleScanning(session, args, logger, requestId, capabilityServic
|
|
|
396
483
|
progress: progressData
|
|
397
484
|
}, args);
|
|
398
485
|
};
|
|
399
|
-
// Setup kubectl access
|
|
400
|
-
|
|
486
|
+
// Setup kubectl access
|
|
487
|
+
const discovery = new discovery_1.KubernetesDiscovery();
|
|
401
488
|
try {
|
|
402
|
-
discovery = new discovery_1.KubernetesDiscovery();
|
|
403
489
|
await discovery.connect();
|
|
404
|
-
logger.info('Connected to Kubernetes for
|
|
490
|
+
logger.info('Connected to Kubernetes for capability scanning', {
|
|
405
491
|
requestId,
|
|
406
492
|
sessionId: session.sessionId
|
|
407
493
|
});
|
|
408
494
|
}
|
|
409
495
|
catch (error) {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
496
|
+
return {
|
|
497
|
+
success: false,
|
|
498
|
+
operation: 'scan',
|
|
499
|
+
dataType: 'capabilities',
|
|
500
|
+
error: {
|
|
501
|
+
message: 'Could not connect to Kubernetes cluster',
|
|
502
|
+
details: error instanceof Error ? error.message : String(error),
|
|
503
|
+
sessionId: session.sessionId
|
|
504
|
+
}
|
|
505
|
+
};
|
|
415
506
|
}
|
|
416
|
-
// Process each resource
|
|
507
|
+
// Process each resource using scanSingleResource
|
|
417
508
|
for (let i = 0; i < resources.length; i++) {
|
|
418
509
|
const currentResource = resources[i];
|
|
419
|
-
// Get complete resource definition for this resource
|
|
420
|
-
let currentResourceDefinition;
|
|
421
|
-
if (discovery) {
|
|
422
|
-
try {
|
|
423
|
-
// Try kubectl explain with full name first (works for CRDs and core resources)
|
|
424
|
-
try {
|
|
425
|
-
currentResourceDefinition = await discovery.explainResource(currentResource);
|
|
426
|
-
}
|
|
427
|
-
catch (explainError) {
|
|
428
|
-
// If explain fails and resource has a dot (like Deployment.apps), try with just the Kind
|
|
429
|
-
if (currentResource.includes('.')) {
|
|
430
|
-
const resourceKind = currentResource.split('.')[0];
|
|
431
|
-
logger.info(`kubectl explain failed for ${currentResource}, attempting with Kind only: ${resourceKind}`, {
|
|
432
|
-
requestId,
|
|
433
|
-
sessionId: session.sessionId,
|
|
434
|
-
resource: currentResource,
|
|
435
|
-
resourceKind
|
|
436
|
-
});
|
|
437
|
-
currentResourceDefinition = await discovery.explainResource(resourceKind);
|
|
438
|
-
}
|
|
439
|
-
else {
|
|
440
|
-
// Re-throw explain error for resources without dots
|
|
441
|
-
throw explainError;
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
catch (error) {
|
|
446
|
-
logger.error(`Failed to get resource definition for ${currentResource}`, error, {
|
|
447
|
-
requestId,
|
|
448
|
-
sessionId: session.sessionId,
|
|
449
|
-
resource: currentResource
|
|
450
|
-
});
|
|
451
|
-
// Add to errors array and skip processing this resource
|
|
452
|
-
errors.push({
|
|
453
|
-
resource: currentResource,
|
|
454
|
-
error: createResourceDefinitionErrorMessage(currentResource, error),
|
|
455
|
-
timestamp: new Date().toISOString()
|
|
456
|
-
});
|
|
457
|
-
// Skip processing this resource
|
|
458
|
-
continue;
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
510
|
// Update progress before processing
|
|
462
511
|
updateProgress(i + 1, currentResource, processedResults.length, errors.length, errors);
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
// If no session metadata and we have resource definition, parse from kubectl explain output
|
|
473
|
-
if (!metadata && currentResourceDefinition) {
|
|
474
|
-
const lines = currentResourceDefinition.split('\n');
|
|
475
|
-
const groupLine = lines.find((line) => line.startsWith('GROUP:'));
|
|
476
|
-
const versionLine = lines.find((line) => line.startsWith('VERSION:'));
|
|
477
|
-
// Extract metadata if version is found (group is optional for core resources)
|
|
478
|
-
if (versionLine) {
|
|
479
|
-
const group = groupLine ? groupLine.replace('GROUP:', '').trim() : '';
|
|
480
|
-
const version = versionLine.replace('VERSION:', '').trim();
|
|
481
|
-
const apiVersion = group ? `${group}/${version}` : version;
|
|
482
|
-
metadata = { apiVersion, version, group };
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
const capability = await engine.inferCapabilities(currentResource, currentResourceDefinition, args.interaction_id, metadata?.apiVersion, metadata?.version, metadata?.group);
|
|
486
|
-
const capabilityId = capabilities_1.CapabilityInferenceEngine.generateCapabilityId(currentResource);
|
|
487
|
-
// Store capability in Vector DB
|
|
488
|
-
await capabilityService.storeCapability(capability);
|
|
512
|
+
logger.info(`Processing resource ${i + 1}/${totalResources}`, {
|
|
513
|
+
requestId,
|
|
514
|
+
sessionId: session.sessionId,
|
|
515
|
+
resource: currentResource,
|
|
516
|
+
percentage: Math.round(((i + 1) / totalResources) * 100)
|
|
517
|
+
});
|
|
518
|
+
// Call the shared single-resource scan function
|
|
519
|
+
const result = await scanSingleResource(currentResource, discovery, engine, capabilityService, logger, requestId, args.interaction_id);
|
|
520
|
+
if (result.success) {
|
|
489
521
|
processedResults.push({
|
|
490
|
-
resource:
|
|
491
|
-
id:
|
|
492
|
-
capabilities:
|
|
493
|
-
providers:
|
|
494
|
-
complexity:
|
|
495
|
-
confidence:
|
|
522
|
+
resource: result.resource,
|
|
523
|
+
id: result.id,
|
|
524
|
+
capabilities: result.capabilities,
|
|
525
|
+
providers: result.providers,
|
|
526
|
+
complexity: result.complexity,
|
|
527
|
+
confidence: result.confidence
|
|
496
528
|
});
|
|
497
529
|
logger.info(`Successfully processed resource ${i + 1}/${totalResources}`, {
|
|
498
530
|
requestId,
|
|
499
531
|
sessionId: session.sessionId,
|
|
500
532
|
resource: currentResource,
|
|
501
|
-
capabilitiesFound:
|
|
533
|
+
capabilitiesFound: result.capabilities?.length || 0,
|
|
502
534
|
percentage: Math.round(((i + 1) / totalResources) * 100)
|
|
503
535
|
});
|
|
504
536
|
}
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
error: errorMessage,
|
|
537
|
+
else {
|
|
538
|
+
errors.push({
|
|
539
|
+
resource: result.resource,
|
|
540
|
+
error: result.error,
|
|
510
541
|
index: i + 1,
|
|
511
542
|
timestamp: new Date().toISOString()
|
|
512
|
-
};
|
|
513
|
-
logger.error(`Failed to process resource ${i + 1}/${totalResources}`, error, {
|
|
514
|
-
requestId,
|
|
515
|
-
sessionId: session.sessionId,
|
|
516
|
-
resource: currentResource,
|
|
517
|
-
percentage: Math.round(((i + 1) / totalResources) * 100)
|
|
518
543
|
});
|
|
519
|
-
errors.push(errorDetail);
|
|
520
544
|
}
|
|
521
545
|
}
|
|
522
546
|
// Final progress update - mark as completed
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
import { BaseVectorService, BaseSearchOptions, BaseSearchResult } from './base-vector-service';
|
|
8
8
|
import { VectorDBService } from './vector-db-service';
|
|
9
9
|
import { EmbeddingService } from './embedding-service';
|
|
10
|
-
import { ResourceCapability } from './capabilities';
|
|
11
|
-
export type { ResourceCapability };
|
|
10
|
+
import { ResourceCapability, PrinterColumn } from './capabilities';
|
|
11
|
+
export type { ResourceCapability, PrinterColumn };
|
|
12
12
|
export interface CapabilitySearchOptions extends BaseSearchOptions {
|
|
13
13
|
complexityFilter?: 'low' | 'medium' | 'high';
|
|
14
14
|
providerFilter?: string[];
|
|
@@ -47,6 +47,15 @@ export declare class CapabilityVectorService extends BaseVectorService<ResourceC
|
|
|
47
47
|
* Used by MCP operations with IDs from list/search results
|
|
48
48
|
*/
|
|
49
49
|
getCapability(id: string): Promise<ResourceCapability | null>;
|
|
50
|
+
/**
|
|
51
|
+
* Get capability by kind and apiVersion
|
|
52
|
+
* Used for JSON format lookup from dashboard UI
|
|
53
|
+
*
|
|
54
|
+
* @param kind - Resource kind (e.g., "Deployment", "Cluster")
|
|
55
|
+
* @param apiVersion - Full apiVersion (e.g., "apps/v1", "postgresql.cnpg.io/v1")
|
|
56
|
+
* @returns Matching capability or null if not found
|
|
57
|
+
*/
|
|
58
|
+
getCapabilityByKindApiVersion(kind: string, apiVersion: string): Promise<ResourceCapability | null>;
|
|
50
59
|
/**
|
|
51
60
|
* Delete capability by resource name
|
|
52
61
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capability-vector-service.d.ts","sourceRoot":"","sources":["../../src/core/capability-vector-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC/F,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAA6B,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"capability-vector-service.d.ts","sourceRoot":"","sources":["../../src/core/capability-vector-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC/F,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAA6B,kBAAkB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAG9F,YAAY,EAAE,kBAAkB,EAAE,aAAa,EAAE,CAAC;AAElD,MAAM,WAAW,uBAAwB,SAAQ,iBAAiB;IAChE,gBAAgB,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC7C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,iBAAiB,CAAC,kBAAkB,CAAC;gBAEpE,cAAc,GAAE,MAAuB,EAAE,QAAQ,CAAC,EAAE,eAAe,EAAE,gBAAgB,CAAC,EAAE,gBAAgB;IAIpH;;OAEG;IACH,SAAS,CAAC,gBAAgB,CAAC,UAAU,EAAE,kBAAkB,GAAG,MAAM;IAYlE;;OAEG;IACH,SAAS,CAAC,SAAS,CAAC,UAAU,EAAE,kBAAkB,GAAG,MAAM;IAI3D;;OAEG;IACH,SAAS,CAAC,aAAa,CAAC,UAAU,EAAE,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAkB5E;;OAEG;IACH,SAAS,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,kBAAkB;IAkBzE;;OAEG;IACG,eAAe,CAAC,UAAU,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE;;OAEG;IACG,kBAAkB,CACtB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,EAAE,CAAC;IAoBlD;;;OAGG;IACG,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAInE;;;;;;;OAOG;IACG,6BAA6B,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAwCzG;;OAEG;IACG,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK3D;;OAEG;IACG,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrD;;OAEG;IACG,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5C;;OAEG;IACG,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAIvE;;OAEG;IACG,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC;CAK9C"}
|
|
@@ -51,6 +51,7 @@ class CapabilityVectorService extends base_vector_service_1.BaseVectorService {
|
|
|
51
51
|
complexity: capability.complexity,
|
|
52
52
|
description: capability.description,
|
|
53
53
|
useCase: capability.useCase,
|
|
54
|
+
printerColumns: capability.printerColumns,
|
|
54
55
|
confidence: capability.confidence,
|
|
55
56
|
analyzedAt: capability.analyzedAt
|
|
56
57
|
};
|
|
@@ -70,6 +71,7 @@ class CapabilityVectorService extends base_vector_service_1.BaseVectorService {
|
|
|
70
71
|
complexity: payload.complexity || 'medium',
|
|
71
72
|
description: payload.description || '',
|
|
72
73
|
useCase: payload.useCase || '',
|
|
74
|
+
printerColumns: payload.printerColumns,
|
|
73
75
|
confidence: payload.confidence || 0,
|
|
74
76
|
analyzedAt: payload.analyzedAt || new Date().toISOString()
|
|
75
77
|
};
|
|
@@ -102,6 +104,54 @@ class CapabilityVectorService extends base_vector_service_1.BaseVectorService {
|
|
|
102
104
|
async getCapability(id) {
|
|
103
105
|
return await this.getData(id);
|
|
104
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Get capability by kind and apiVersion
|
|
109
|
+
* Used for JSON format lookup from dashboard UI
|
|
110
|
+
*
|
|
111
|
+
* @param kind - Resource kind (e.g., "Deployment", "Cluster")
|
|
112
|
+
* @param apiVersion - Full apiVersion (e.g., "apps/v1", "postgresql.cnpg.io/v1")
|
|
113
|
+
* @returns Matching capability or null if not found
|
|
114
|
+
*/
|
|
115
|
+
async getCapabilityByKindApiVersion(kind, apiVersion) {
|
|
116
|
+
// Build Qdrant filter for exact apiVersion match
|
|
117
|
+
const filter = {
|
|
118
|
+
must: [
|
|
119
|
+
{ key: 'apiVersion', match: { value: apiVersion } }
|
|
120
|
+
]
|
|
121
|
+
};
|
|
122
|
+
const results = await this.queryWithFilter(filter, 100);
|
|
123
|
+
if (results.length === 0) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
// Find matching capability by kind
|
|
127
|
+
// For standard resources: resourceName === kind (case insensitive)
|
|
128
|
+
// For CRDs: resourceName matches Kind.group or plural.group pattern
|
|
129
|
+
const kindLower = kind.toLowerCase();
|
|
130
|
+
const match = results.find(cap => {
|
|
131
|
+
const resourceNameLower = cap.resourceName.toLowerCase();
|
|
132
|
+
// Exact match
|
|
133
|
+
if (resourceNameLower === kindLower)
|
|
134
|
+
return true;
|
|
135
|
+
// Pluralized exact match (e.g., "deployment" -> "deployments")
|
|
136
|
+
if (resourceNameLower === kindLower + 's' || resourceNameLower === kindLower + 'es')
|
|
137
|
+
return true;
|
|
138
|
+
// CRD format: Kind.group (e.g., "deployment" -> "deployment.apps")
|
|
139
|
+
// Must match kind followed by a dot to avoid false positives like "cluster" matching "clusterroles"
|
|
140
|
+
if (resourceNameLower.startsWith(kindLower + '.'))
|
|
141
|
+
return true;
|
|
142
|
+
// CRD format: plural.group (e.g., "cluster" -> "clusters.devopstoolkit.live")
|
|
143
|
+
if (resourceNameLower.startsWith(kindLower + 's.') || resourceNameLower.startsWith(kindLower + 'es.'))
|
|
144
|
+
return true;
|
|
145
|
+
// Handle -y -> -ies pluralization (e.g., "policy" -> "policies.group")
|
|
146
|
+
if (kindLower.endsWith('y')) {
|
|
147
|
+
const stem = kindLower.slice(0, -1);
|
|
148
|
+
if (resourceNameLower === stem + 'ies' || resourceNameLower.startsWith(stem + 'ies.'))
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
return false;
|
|
152
|
+
});
|
|
153
|
+
return match || null;
|
|
154
|
+
}
|
|
105
155
|
/**
|
|
106
156
|
* Delete capability by resource name
|
|
107
157
|
*/
|
package/dist/core/discovery.d.ts
CHANGED
|
@@ -20,11 +20,19 @@ export interface EnhancedCRD {
|
|
|
20
20
|
version: string;
|
|
21
21
|
kind: string;
|
|
22
22
|
scope: 'Namespaced' | 'Cluster';
|
|
23
|
+
resourcePlural: string;
|
|
23
24
|
versions: Array<{
|
|
24
25
|
name: string;
|
|
25
26
|
served: boolean;
|
|
26
27
|
storage: boolean;
|
|
27
28
|
schema?: any;
|
|
29
|
+
additionalPrinterColumns?: Array<{
|
|
30
|
+
name: string;
|
|
31
|
+
type: string;
|
|
32
|
+
jsonPath: string;
|
|
33
|
+
description?: string;
|
|
34
|
+
priority?: number;
|
|
35
|
+
}>;
|
|
28
36
|
}>;
|
|
29
37
|
schema?: any;
|
|
30
38
|
}
|
|
@@ -141,6 +149,15 @@ export declare class KubernetesDiscovery {
|
|
|
141
149
|
* Delegates to shared utility function
|
|
142
150
|
*/
|
|
143
151
|
executeKubectl(args: string[], config?: KubectlConfig): Promise<string>;
|
|
152
|
+
/**
|
|
153
|
+
* Parse a raw CRD object into EnhancedCRD format
|
|
154
|
+
*/
|
|
155
|
+
private parseCRDItem;
|
|
156
|
+
/**
|
|
157
|
+
* Fetch a single CRD by name with all metadata including printer columns
|
|
158
|
+
* This is the single source of truth for CRD data - used by both full and targeted scans
|
|
159
|
+
*/
|
|
160
|
+
getCRDData(crdName: string): Promise<EnhancedCRD>;
|
|
144
161
|
discoverCRDs(options?: {
|
|
145
162
|
group?: string;
|
|
146
163
|
}): Promise<EnhancedCRD[]>;
|
|
@@ -156,6 +173,23 @@ export declare class KubernetesDiscovery {
|
|
|
156
173
|
* @returns Cleaned YAML string suitable for AI prompts
|
|
157
174
|
*/
|
|
158
175
|
getCRDDefinition(crdName: string): Promise<string>;
|
|
176
|
+
/**
|
|
177
|
+
* Get printer columns for a resource type via Kubernetes Table API
|
|
178
|
+
* Works for both CRDs and core Kubernetes resources
|
|
179
|
+
* For CRDs, also fetches jsonPath from the CRD spec (not available in Table API)
|
|
180
|
+
*
|
|
181
|
+
* @param resourcePlural - Plural name of the resource (e.g., 'deployments', 'pods', 'sqls')
|
|
182
|
+
* @param apiVersion - Full API version (e.g., 'apps/v1', 'v1', 'devopstoolkit.live/v1beta1')
|
|
183
|
+
* @returns Array of printer column definitions (may be empty if resource has no custom columns)
|
|
184
|
+
* @throws Error on API/auth failures
|
|
185
|
+
*/
|
|
186
|
+
getPrinterColumns(resourcePlural: string, apiVersion: string): Promise<Array<{
|
|
187
|
+
name: string;
|
|
188
|
+
type: string;
|
|
189
|
+
jsonPath: string;
|
|
190
|
+
description?: string;
|
|
191
|
+
priority?: number;
|
|
192
|
+
}>>;
|
|
159
193
|
fingerprintCluster(): Promise<ClusterFingerprint>;
|
|
160
194
|
private getResourceCounts;
|
|
161
195
|
private getNetworkingInfo;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/core/discovery.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,GAAG,MAAM,yBAAyB,CAAC;AAI/C,OAAO,EAEL,aAAa,EAEd,MAAM,oBAAoB,CAAC;AAG5B,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AAKD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,YAAY,GAAG,SAAS,CAAC;IAChC,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,OAAO,CAAC;QAChB,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,CAAC,EAAE,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/core/discovery.ts"],"names":[],"mappings":"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"}
|