@vfarcic/dot-ai 0.48.0 → 0.50.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 +49 -2
- package/dist/core/base-vector-service.d.ts +86 -0
- package/dist/core/base-vector-service.d.ts.map +1 -0
- package/dist/core/base-vector-service.js +223 -0
- package/dist/core/capabilities.d.ts +71 -0
- package/dist/core/capabilities.d.ts.map +1 -0
- package/dist/core/capabilities.js +215 -0
- package/dist/core/capability-vector-service.d.ts +80 -0
- package/dist/core/capability-vector-service.d.ts.map +1 -0
- package/dist/core/capability-vector-service.js +142 -0
- package/dist/core/claude.d.ts +14 -1
- package/dist/core/claude.d.ts.map +1 -1
- package/dist/core/claude.js +109 -13
- package/dist/core/discovery.d.ts +6 -0
- package/dist/core/discovery.d.ts.map +1 -1
- package/dist/core/discovery.js +7 -1
- package/dist/core/embedding-service.d.ts +3 -3
- package/dist/core/embedding-service.d.ts.map +1 -1
- package/dist/core/embedding-service.js +6 -7
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +7 -4
- package/dist/core/pattern-vector-service.d.ts +11 -80
- package/dist/core/pattern-vector-service.d.ts.map +1 -1
- package/dist/core/pattern-vector-service.js +40 -277
- package/dist/core/schema.d.ts +11 -30
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +107 -126
- package/dist/core/vector-db-service.d.ts +6 -0
- package/dist/core/vector-db-service.d.ts.map +1 -1
- package/dist/core/vector-db-service.js +40 -10
- package/dist/tools/organizational-data.d.ts +18 -3
- package/dist/tools/organizational-data.d.ts.map +1 -1
- package/dist/tools/organizational-data.js +1750 -17
- package/dist/tools/recommend.d.ts.map +1 -1
- package/dist/tools/recommend.js +3 -7
- package/dist/tools/version.d.ts +9 -0
- package/dist/tools/version.d.ts.map +1 -1
- package/dist/tools/version.js +115 -5
- package/package.json +1 -1
- package/prompts/capability-inference.md +121 -0
- package/prompts/doc-testing-test-section.md +40 -2
- package/prompts/resource-selection.md +10 -3
- package/shared-prompts/prd-done.md +5 -4
- package/shared-prompts/prd-update-decisions.md +9 -0
- package/shared-prompts/prd-update-progress.md +33 -0
- package/prompts/concept-extraction.md +0 -95
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ DevOps AI Toolkit is an AI-powered development productivity platform that enhanc
|
|
|
12
12
|
|
|
13
13
|
### Kubernetes Deployment
|
|
14
14
|
- **Developers**: Deploy applications without needing deep Kubernetes expertise
|
|
15
|
-
- **Platform Engineers**: Create organizational deployment patterns that enhance AI recommendations with institutional knowledge and best practices
|
|
15
|
+
- **Platform Engineers**: Create organizational deployment patterns that enhance AI recommendations with institutional knowledge and best practices, and scan cluster resources to enable semantic matching for dramatically improved recommendation accuracy
|
|
16
16
|
|
|
17
17
|
### Documentation Testing
|
|
18
18
|
- **Documentation Maintainers**: Automatically validate documentation accuracy and catch outdated content
|
|
@@ -31,10 +31,34 @@ DevOps AI Toolkit is an AI-powered development productivity platform that enhanc
|
|
|
31
31
|
|
|
32
32
|
### Kubernetes Deployment Intelligence
|
|
33
33
|
🔍 **Smart Discovery**: Automatically finds all available resources and operators in your cluster
|
|
34
|
-
|
|
34
|
+
🧠 **Semantic Capability Management**: Discovers what each resource actually does for intelligent matching
|
|
35
|
+
🤖 **AI Recommendations**: Get deployment suggestions tailored to your specific cluster setup with enhanced semantic understanding
|
|
35
36
|
🔧 **Operator-Aware**: Leverages custom operators and CRDs when available
|
|
36
37
|
🚀 **Complete Workflow**: From discovery to deployment with automated Kubernetes integration
|
|
37
38
|
|
|
39
|
+
#### Capability-Enhanced Recommendations
|
|
40
|
+
Transform how AI understands your cluster by discovering semantic capabilities of each resource:
|
|
41
|
+
|
|
42
|
+
**The Problem**: Traditional discovery sees `sqls.devopstoolkit.live` as a meaningless name among hundreds of resources.
|
|
43
|
+
|
|
44
|
+
**The Solution**: Capability management teaches the system that `sqls.devopstoolkit.live` handles PostgreSQL databases with multi-cloud support.
|
|
45
|
+
|
|
46
|
+
**Before Capability Management:**
|
|
47
|
+
```
|
|
48
|
+
User: "I need a PostgreSQL database"
|
|
49
|
+
AI: Gets 400+ generic resource names → picks complex multi-resource solution
|
|
50
|
+
Result: Misses optimal single-resource solutions
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**After Capability Management:**
|
|
54
|
+
```
|
|
55
|
+
User: "I need a PostgreSQL database"
|
|
56
|
+
AI: Gets pre-filtered relevant resources with rich context
|
|
57
|
+
Result: Finds sqls.devopstoolkit.live as perfect match ✨
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Get Started**: See the [Capability Management Guide](./docs/mcp-capability-management-guide.md) for complete workflows including cluster scanning, capability search, and recommendation enhancement.
|
|
61
|
+
|
|
38
62
|
### Documentation Testing & Validation
|
|
39
63
|
📖 **Automated Testing**: Validates documentation by executing commands and testing examples
|
|
40
64
|
🔍 **Two-Phase Validation**: Tests both functionality (does it work?) and semantic accuracy (are descriptions truthful?)
|
|
@@ -164,6 +188,29 @@ Agent: Perfect! Generating manifests and deploying now...
|
|
|
164
188
|
Agent: ✅ Successfully deployed! Your application is running.
|
|
165
189
|
```
|
|
166
190
|
|
|
191
|
+
**Example: Capability Management**
|
|
192
|
+
```
|
|
193
|
+
User: I want to scan my cluster for resource capabilities to improve recommendations
|
|
194
|
+
|
|
195
|
+
Agent: I'll help you scan your cluster to discover semantic capabilities. This will dramatically improve recommendation accuracy.
|
|
196
|
+
[Uses manageOrgData with capabilities scanning]
|
|
197
|
+
|
|
198
|
+
Agent: Would you like to scan all cluster resources or specify a subset?
|
|
199
|
+
Options: 1) All resources 2) Specific subset
|
|
200
|
+
|
|
201
|
+
User: All resources in auto mode
|
|
202
|
+
|
|
203
|
+
Agent: Starting comprehensive cluster capability scan...
|
|
204
|
+
✅ Capability scan completed! Processed cluster resources successfully.
|
|
205
|
+
|
|
206
|
+
User: Now I need a PostgreSQL database
|
|
207
|
+
|
|
208
|
+
Agent: Let me get enhanced recommendations using your capability data.
|
|
209
|
+
[Uses recommend tool with capability pre-filtering]
|
|
210
|
+
|
|
211
|
+
Agent: Perfect! I found sqls.devopstoolkit.live as the top match - it's a managed database solution supporting PostgreSQL with multi-cloud capabilities and low complexity. Much better than the generic StatefulSet approach I would have suggested before!
|
|
212
|
+
```
|
|
213
|
+
|
|
167
214
|
**Example: Documentation Testing**
|
|
168
215
|
```
|
|
169
216
|
User: I want to test my README.md file to make sure all the examples work
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Vector Service
|
|
3
|
+
*
|
|
4
|
+
* Generic vector operations that can be extended for different data types
|
|
5
|
+
* (patterns, capabilities, dependencies, etc.)
|
|
6
|
+
*/
|
|
7
|
+
import { VectorDBService } from './vector-db-service';
|
|
8
|
+
import { EmbeddingService } from './embedding-service';
|
|
9
|
+
export interface BaseSearchOptions {
|
|
10
|
+
limit?: number;
|
|
11
|
+
scoreThreshold?: number;
|
|
12
|
+
keywordWeight?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface BaseSearchResult<T> {
|
|
15
|
+
data: T;
|
|
16
|
+
score: number;
|
|
17
|
+
matchType: 'keyword' | 'semantic' | 'hybrid';
|
|
18
|
+
}
|
|
19
|
+
export interface SearchMode {
|
|
20
|
+
semantic: boolean;
|
|
21
|
+
provider?: string;
|
|
22
|
+
reason?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Abstract base class for vector-based data services
|
|
26
|
+
*/
|
|
27
|
+
export declare abstract class BaseVectorService<T> {
|
|
28
|
+
protected vectorDB: VectorDBService;
|
|
29
|
+
protected embeddingService: EmbeddingService;
|
|
30
|
+
protected collectionName: string;
|
|
31
|
+
constructor(collectionName: string, vectorDB?: VectorDBService, embeddingService?: EmbeddingService);
|
|
32
|
+
/**
|
|
33
|
+
* Initialize the collection
|
|
34
|
+
*/
|
|
35
|
+
initialize(): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Health check for Vector DB connection
|
|
38
|
+
*/
|
|
39
|
+
healthCheck(): Promise<boolean>;
|
|
40
|
+
/**
|
|
41
|
+
* Store data in Vector DB with optional semantic embedding
|
|
42
|
+
*/
|
|
43
|
+
storeData(data: T): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Search for data using hybrid semantic + keyword matching
|
|
46
|
+
*/
|
|
47
|
+
searchData(query: string, options?: BaseSearchOptions): Promise<BaseSearchResult<T>[]>;
|
|
48
|
+
/**
|
|
49
|
+
* Get data by ID
|
|
50
|
+
*/
|
|
51
|
+
getData(id: string): Promise<T | null>;
|
|
52
|
+
/**
|
|
53
|
+
* Delete data by ID
|
|
54
|
+
*/
|
|
55
|
+
deleteData(id: string): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Delete all data (recreate collection)
|
|
58
|
+
*/
|
|
59
|
+
deleteAllData(): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* Get all data (limited)
|
|
62
|
+
*/
|
|
63
|
+
getAllData(limit?: number): Promise<T[]>;
|
|
64
|
+
/**
|
|
65
|
+
* Get total count of data items
|
|
66
|
+
*/
|
|
67
|
+
getDataCount(): Promise<number>;
|
|
68
|
+
/**
|
|
69
|
+
* Get current search mode (semantic vs keyword-only)
|
|
70
|
+
*/
|
|
71
|
+
getSearchMode(): SearchMode;
|
|
72
|
+
protected abstract createSearchText(data: T): string;
|
|
73
|
+
protected abstract extractId(data: T): string;
|
|
74
|
+
protected abstract createPayload(data: T): Record<string, any>;
|
|
75
|
+
protected abstract payloadToData(payload: Record<string, any>): T;
|
|
76
|
+
protected extractKeywords(query: string): string[];
|
|
77
|
+
/**
|
|
78
|
+
* Hybrid search combining semantic and keyword matching
|
|
79
|
+
*/
|
|
80
|
+
private hybridSearch;
|
|
81
|
+
/**
|
|
82
|
+
* Combine semantic and keyword results with hybrid ranking
|
|
83
|
+
*/
|
|
84
|
+
private combineHybridResults;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=base-vector-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-vector-service.d.ts","sourceRoot":"","sources":["../../src/core/base-vector-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAkB,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,IAAI,EAAE,CAAC,CAAC;IACR,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAC;CAC9C;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,8BAAsB,iBAAiB,CAAC,CAAC;IACvC,SAAS,CAAC,QAAQ,EAAE,eAAe,CAAC;IACpC,SAAS,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC7C,SAAS,CAAC,cAAc,EAAE,MAAM,CAAC;gBAErB,cAAc,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,eAAe,EAAE,gBAAgB,CAAC,EAAE,gBAAgB;IAMnG;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQjC;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAIrC;;OAEG;IACG,SAAS,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BvC;;OAEG;IACG,UAAU,CACd,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;IAyBjC;;OAEG;IACG,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAW5C;;OAEG;IACG,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAIpC;;OAEG;IACG,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAS9C;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAWrC;;OAEG;IACH,aAAa,IAAI,UAAU;IAU3B,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC,GAAG,MAAM;IACpD,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,GAAG,MAAM;IAC7C,SAAS,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAC9D,SAAS,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC;IAGjE,SAAS,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAIlD;;OAEG;YACW,YAAY;IAkC1B;;OAEG;IACH,OAAO,CAAC,oBAAoB;CA2C7B"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Base Vector Service
|
|
4
|
+
*
|
|
5
|
+
* Generic vector operations that can be extended for different data types
|
|
6
|
+
* (patterns, capabilities, dependencies, etc.)
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.BaseVectorService = void 0;
|
|
10
|
+
const vector_db_service_1 = require("./vector-db-service");
|
|
11
|
+
const embedding_service_1 = require("./embedding-service");
|
|
12
|
+
/**
|
|
13
|
+
* Abstract base class for vector-based data services
|
|
14
|
+
*/
|
|
15
|
+
class BaseVectorService {
|
|
16
|
+
vectorDB;
|
|
17
|
+
embeddingService;
|
|
18
|
+
collectionName;
|
|
19
|
+
constructor(collectionName, vectorDB, embeddingService) {
|
|
20
|
+
this.collectionName = collectionName;
|
|
21
|
+
this.vectorDB = vectorDB || new vector_db_service_1.VectorDBService({ collectionName });
|
|
22
|
+
this.embeddingService = embeddingService || new embedding_service_1.EmbeddingService();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Initialize the collection
|
|
26
|
+
*/
|
|
27
|
+
async initialize() {
|
|
28
|
+
// Use embedding dimensions if available, otherwise default to 1536 (OpenAI default)
|
|
29
|
+
const dimensions = this.embeddingService.isAvailable() ?
|
|
30
|
+
this.embeddingService.getDimensions() :
|
|
31
|
+
1536;
|
|
32
|
+
await this.vectorDB.initializeCollection(dimensions);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Health check for Vector DB connection
|
|
36
|
+
*/
|
|
37
|
+
async healthCheck() {
|
|
38
|
+
return await this.vectorDB.healthCheck();
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Store data in Vector DB with optional semantic embedding
|
|
42
|
+
*/
|
|
43
|
+
async storeData(data) {
|
|
44
|
+
const searchText = this.createSearchText(data);
|
|
45
|
+
const id = this.extractId(data);
|
|
46
|
+
// Generate embedding - required for vector storage
|
|
47
|
+
let embedding;
|
|
48
|
+
if (this.embeddingService.isAvailable()) {
|
|
49
|
+
try {
|
|
50
|
+
embedding = await this.embeddingService.generateEmbedding(searchText);
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
// Fail immediately with clear error about embedding generation
|
|
54
|
+
throw new Error(`Embedding generation failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
// Embedding service not available - fail with clear error
|
|
59
|
+
throw new Error('Embedding service not available - cannot store data in vector collection');
|
|
60
|
+
}
|
|
61
|
+
const document = {
|
|
62
|
+
id,
|
|
63
|
+
payload: {
|
|
64
|
+
...this.createPayload(data),
|
|
65
|
+
searchText: searchText,
|
|
66
|
+
hasEmbedding: true
|
|
67
|
+
},
|
|
68
|
+
vector: embedding
|
|
69
|
+
};
|
|
70
|
+
await this.vectorDB.upsertDocument(document);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Search for data using hybrid semantic + keyword matching
|
|
74
|
+
*/
|
|
75
|
+
async searchData(query, options = {}) {
|
|
76
|
+
// Fail immediately if embedding service not available - no graceful fallback
|
|
77
|
+
if (!this.embeddingService.isAvailable()) {
|
|
78
|
+
throw new Error('Embedding service not available - cannot perform semantic search');
|
|
79
|
+
}
|
|
80
|
+
// Extract keywords for keyword search
|
|
81
|
+
const queryKeywords = this.extractKeywords(query);
|
|
82
|
+
if (queryKeywords.length === 0) {
|
|
83
|
+
return [];
|
|
84
|
+
}
|
|
85
|
+
const limit = options.limit || 10;
|
|
86
|
+
const scoreThreshold = options.scoreThreshold || 0.01;
|
|
87
|
+
// Perform hybrid search (semantic + keyword)
|
|
88
|
+
try {
|
|
89
|
+
return await this.hybridSearch(query, queryKeywords, { limit, scoreThreshold });
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
// Fail immediately - no fallback to keyword-only search
|
|
93
|
+
throw new Error(`Semantic search failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Get data by ID
|
|
98
|
+
*/
|
|
99
|
+
async getData(id) {
|
|
100
|
+
const document = await this.vectorDB.getDocument(id);
|
|
101
|
+
if (!document) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
const data = this.payloadToData(document.payload);
|
|
105
|
+
// Set the ID from the document
|
|
106
|
+
data.id = document.id;
|
|
107
|
+
return data;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Delete data by ID
|
|
111
|
+
*/
|
|
112
|
+
async deleteData(id) {
|
|
113
|
+
await this.vectorDB.deleteDocument(id);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Delete all data (recreate collection)
|
|
117
|
+
*/
|
|
118
|
+
async deleteAllData() {
|
|
119
|
+
await this.vectorDB.deleteAllDocuments();
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Get all data (limited)
|
|
123
|
+
*/
|
|
124
|
+
async getAllData(limit) {
|
|
125
|
+
const documents = await this.vectorDB.getAllDocuments(limit);
|
|
126
|
+
return documents.map(doc => {
|
|
127
|
+
const data = this.payloadToData(doc.payload);
|
|
128
|
+
data.id = doc.id;
|
|
129
|
+
return data;
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Get total count of data items
|
|
134
|
+
*/
|
|
135
|
+
async getDataCount() {
|
|
136
|
+
try {
|
|
137
|
+
const info = await this.vectorDB.getCollectionInfo();
|
|
138
|
+
return info.points_count || 0;
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
// Fallback: get all and count
|
|
142
|
+
const data = await this.getAllData();
|
|
143
|
+
return data.length;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Get current search mode (semantic vs keyword-only)
|
|
148
|
+
*/
|
|
149
|
+
getSearchMode() {
|
|
150
|
+
const status = this.embeddingService.getStatus();
|
|
151
|
+
return {
|
|
152
|
+
semantic: status.available,
|
|
153
|
+
provider: status.provider || undefined,
|
|
154
|
+
reason: status.reason || (status.available ? 'Embedding service available' : undefined)
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
// Virtual methods that can be overridden by subclasses
|
|
158
|
+
extractKeywords(query) {
|
|
159
|
+
return query.toLowerCase().split(/\s+/).filter(word => word.length > 2);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Hybrid search combining semantic and keyword matching
|
|
163
|
+
*/
|
|
164
|
+
async hybridSearch(query, queryKeywords, options) {
|
|
165
|
+
// Generate query embedding - required for semantic search
|
|
166
|
+
const queryEmbedding = await this.embeddingService.generateEmbedding(query);
|
|
167
|
+
if (!queryEmbedding) {
|
|
168
|
+
throw new Error('Failed to generate query embedding for semantic search');
|
|
169
|
+
}
|
|
170
|
+
// Semantic search using vector similarity
|
|
171
|
+
const semanticResults = await this.vectorDB.searchSimilar(queryEmbedding, {
|
|
172
|
+
limit: options.limit * 2, // Get more candidates for hybrid ranking
|
|
173
|
+
scoreThreshold: 0.1 // Very permissive threshold for single-word queries
|
|
174
|
+
});
|
|
175
|
+
// Keyword search
|
|
176
|
+
const keywordResults = await this.vectorDB.searchByKeywords(queryKeywords, {
|
|
177
|
+
limit: options.limit * 2,
|
|
178
|
+
scoreThreshold: 0.1
|
|
179
|
+
});
|
|
180
|
+
// Combine and rank results
|
|
181
|
+
return this.combineHybridResults(semanticResults, keywordResults, queryKeywords, options);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Combine semantic and keyword results with hybrid ranking
|
|
185
|
+
*/
|
|
186
|
+
combineHybridResults(semanticResults, keywordResults, queryKeywords, options) {
|
|
187
|
+
const combinedResults = new Map();
|
|
188
|
+
// Add semantic results
|
|
189
|
+
for (const result of semanticResults) {
|
|
190
|
+
const data = this.payloadToData(result.payload);
|
|
191
|
+
data.id = result.id;
|
|
192
|
+
combinedResults.set(result.id, {
|
|
193
|
+
data,
|
|
194
|
+
score: result.score * 0.7, // Weight semantic similarity
|
|
195
|
+
matchType: 'semantic'
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
// Add or boost keyword results
|
|
199
|
+
for (const result of keywordResults) {
|
|
200
|
+
const existing = combinedResults.get(result.id);
|
|
201
|
+
if (existing) {
|
|
202
|
+
// Boost score for hybrid match
|
|
203
|
+
existing.score = Math.max(existing.score, result.score * 0.8);
|
|
204
|
+
existing.matchType = 'hybrid';
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
const data = this.payloadToData(result.payload);
|
|
208
|
+
data.id = result.id;
|
|
209
|
+
combinedResults.set(result.id, {
|
|
210
|
+
data,
|
|
211
|
+
score: result.score * 0.6, // Weight keyword matching
|
|
212
|
+
matchType: 'keyword'
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
// Sort by score and apply limits
|
|
217
|
+
return Array.from(combinedResults.values())
|
|
218
|
+
.filter(result => result.score >= options.scoreThreshold)
|
|
219
|
+
.sort((a, b) => b.score - a.score)
|
|
220
|
+
.slice(0, options.limit);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
exports.BaseVectorService = BaseVectorService;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource Capability Discovery & Inference Engine
|
|
3
|
+
*
|
|
4
|
+
* PRD #48: Resource Capabilities Discovery & Integration
|
|
5
|
+
*
|
|
6
|
+
* This module provides capability inference for Kubernetes resources through
|
|
7
|
+
* AI-powered analysis of schemas and metadata.
|
|
8
|
+
*/
|
|
9
|
+
import { Logger } from './error-handling';
|
|
10
|
+
import { ClaudeIntegration } from './claude';
|
|
11
|
+
/**
|
|
12
|
+
* Complete resource capability data structure for Vector DB storage
|
|
13
|
+
*/
|
|
14
|
+
export interface ResourceCapability {
|
|
15
|
+
resourceName: string;
|
|
16
|
+
capabilities: string[];
|
|
17
|
+
providers: string[];
|
|
18
|
+
abstractions: string[];
|
|
19
|
+
complexity: 'low' | 'medium' | 'high';
|
|
20
|
+
description: string;
|
|
21
|
+
useCase: string;
|
|
22
|
+
embedding?: number[];
|
|
23
|
+
analyzedAt: string;
|
|
24
|
+
confidence: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Generic Capability Inference Engine
|
|
28
|
+
*
|
|
29
|
+
* Analyzes any Kubernetes CRD using AI to extract semantic capabilities
|
|
30
|
+
* for improved AI recommendations and resource matching.
|
|
31
|
+
*/
|
|
32
|
+
export declare class CapabilityInferenceEngine {
|
|
33
|
+
private logger;
|
|
34
|
+
private claudeIntegration;
|
|
35
|
+
constructor(claudeIntegration: ClaudeIntegration, logger: Logger);
|
|
36
|
+
/**
|
|
37
|
+
* Main entry point: analyze resource to infer complete capabilities
|
|
38
|
+
*
|
|
39
|
+
* @param resourceName - Full resource name (e.g., "resourcegroups.azure.upbound.io")
|
|
40
|
+
* @throws Error if capability inference fails for any reason
|
|
41
|
+
*/
|
|
42
|
+
inferCapabilities(resourceName: string, schema?: string, metadata?: any): Promise<ResourceCapability>;
|
|
43
|
+
/**
|
|
44
|
+
* Use AI to infer capabilities from all available resource context
|
|
45
|
+
*
|
|
46
|
+
* @throws Error if AI inference fails
|
|
47
|
+
*/
|
|
48
|
+
private inferWithAI;
|
|
49
|
+
/**
|
|
50
|
+
* Build AI inference prompt using standard prompt loading pattern
|
|
51
|
+
*
|
|
52
|
+
* @throws Error if prompt template cannot be loaded
|
|
53
|
+
*/
|
|
54
|
+
private buildInferencePrompt;
|
|
55
|
+
/**
|
|
56
|
+
* Parse AI response into structured capability data
|
|
57
|
+
*
|
|
58
|
+
* @throws Error if AI response cannot be parsed or is invalid
|
|
59
|
+
*/
|
|
60
|
+
private parseCapabilitiesFromAI;
|
|
61
|
+
/**
|
|
62
|
+
* Build final ResourceCapability from AI analysis result
|
|
63
|
+
*/
|
|
64
|
+
private buildResourceCapability;
|
|
65
|
+
/**
|
|
66
|
+
* Generate Vector DB ID for capability storage
|
|
67
|
+
* Creates deterministic UUID from resource name for Qdrant compatibility
|
|
68
|
+
*/
|
|
69
|
+
static generateCapabilityId(resourceName: string): string;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=capabilities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../src/core/capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAK7C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAEjC,YAAY,EAAE,MAAM,CAAC;IAGrB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAGtC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAGhB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAGrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,qBAAa,yBAAyB;IACpC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,iBAAiB,CAAoB;gBAEjC,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM;IAKhE;;;;;OAKG;IACG,iBAAiB,CACrB,YAAY,EAAE,MAAM,EACpB,MAAM,CAAC,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,GAAG,GACb,OAAO,CAAC,kBAAkB,CAAC;IA4B9B;;;;OAIG;YACW,WAAW;IA2BzB;;;;OAIG;YACW,oBAAoB;IAkClC;;;;OAIG;IACH,OAAO,CAAC,uBAAuB;IAwD/B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAyB/B;;;OAGG;IACH,MAAM,CAAC,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;CAQ1D"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Resource Capability Discovery & Inference Engine
|
|
4
|
+
*
|
|
5
|
+
* PRD #48: Resource Capabilities Discovery & Integration
|
|
6
|
+
*
|
|
7
|
+
* This module provides capability inference for Kubernetes resources through
|
|
8
|
+
* AI-powered analysis of schemas and metadata.
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
27
|
+
var ownKeys = function(o) {
|
|
28
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
29
|
+
var ar = [];
|
|
30
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
31
|
+
return ar;
|
|
32
|
+
};
|
|
33
|
+
return ownKeys(o);
|
|
34
|
+
};
|
|
35
|
+
return function (mod) {
|
|
36
|
+
if (mod && mod.__esModule) return mod;
|
|
37
|
+
var result = {};
|
|
38
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
39
|
+
__setModuleDefault(result, mod);
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
})();
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.CapabilityInferenceEngine = void 0;
|
|
45
|
+
const fs = __importStar(require("fs"));
|
|
46
|
+
const path = __importStar(require("path"));
|
|
47
|
+
/**
|
|
48
|
+
* Generic Capability Inference Engine
|
|
49
|
+
*
|
|
50
|
+
* Analyzes any Kubernetes CRD using AI to extract semantic capabilities
|
|
51
|
+
* for improved AI recommendations and resource matching.
|
|
52
|
+
*/
|
|
53
|
+
class CapabilityInferenceEngine {
|
|
54
|
+
logger;
|
|
55
|
+
claudeIntegration;
|
|
56
|
+
constructor(claudeIntegration, logger) {
|
|
57
|
+
this.claudeIntegration = claudeIntegration;
|
|
58
|
+
this.logger = logger;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Main entry point: analyze resource to infer complete capabilities
|
|
62
|
+
*
|
|
63
|
+
* @param resourceName - Full resource name (e.g., "resourcegroups.azure.upbound.io")
|
|
64
|
+
* @throws Error if capability inference fails for any reason
|
|
65
|
+
*/
|
|
66
|
+
async inferCapabilities(resourceName, schema, metadata) {
|
|
67
|
+
const requestId = `capability-inference-${Date.now()}`;
|
|
68
|
+
this.logger.info('Starting capability inference', {
|
|
69
|
+
requestId,
|
|
70
|
+
resource: resourceName,
|
|
71
|
+
hasSchema: !!schema,
|
|
72
|
+
hasMetadata: !!metadata
|
|
73
|
+
});
|
|
74
|
+
// Use AI to analyze all available information
|
|
75
|
+
const aiResult = await this.inferWithAI(resourceName, schema, metadata, requestId);
|
|
76
|
+
// Convert AI result to final capability structure
|
|
77
|
+
const finalCapability = this.buildResourceCapability(resourceName, aiResult);
|
|
78
|
+
this.logger.info('Capability inference completed', {
|
|
79
|
+
requestId,
|
|
80
|
+
resource: resourceName,
|
|
81
|
+
capabilitiesFound: finalCapability.capabilities.length,
|
|
82
|
+
providersFound: finalCapability.providers.length,
|
|
83
|
+
complexity: finalCapability.complexity,
|
|
84
|
+
confidence: finalCapability.confidence
|
|
85
|
+
});
|
|
86
|
+
return finalCapability;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Use AI to infer capabilities from all available resource context
|
|
90
|
+
*
|
|
91
|
+
* @throws Error if AI inference fails
|
|
92
|
+
*/
|
|
93
|
+
async inferWithAI(resourceName, schema, metadata, requestId) {
|
|
94
|
+
try {
|
|
95
|
+
const prompt = await this.buildInferencePrompt(resourceName, schema, metadata);
|
|
96
|
+
const response = await this.claudeIntegration.sendMessage(prompt);
|
|
97
|
+
return this.parseCapabilitiesFromAI(response.content);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
this.logger.error('AI capability inference failed', error, {
|
|
101
|
+
requestId,
|
|
102
|
+
resource: resourceName
|
|
103
|
+
});
|
|
104
|
+
throw error; // Re-throw to maintain fail-fast behavior
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Build AI inference prompt using standard prompt loading pattern
|
|
109
|
+
*
|
|
110
|
+
* @throws Error if prompt template cannot be loaded
|
|
111
|
+
*/
|
|
112
|
+
async buildInferencePrompt(resourceName, schema, metadata) {
|
|
113
|
+
// Load prompt template using standard pattern from existing codebase
|
|
114
|
+
const promptPath = path.join(__dirname, '..', '..', 'prompts', 'capability-inference.md');
|
|
115
|
+
if (!fs.existsSync(promptPath)) {
|
|
116
|
+
throw new Error(`Capability inference prompt template not found: ${promptPath}`);
|
|
117
|
+
}
|
|
118
|
+
let template;
|
|
119
|
+
try {
|
|
120
|
+
template = fs.readFileSync(promptPath, 'utf8');
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
throw new Error(`Failed to read capability inference prompt: ${error instanceof Error ? error.message : String(error)}`);
|
|
124
|
+
}
|
|
125
|
+
// Replace template variables using standard pattern
|
|
126
|
+
const analysisContext = schema && metadata ?
|
|
127
|
+
'Schema and metadata available' :
|
|
128
|
+
schema ? 'Schema only' :
|
|
129
|
+
metadata ? 'Metadata only' : 'Limited context';
|
|
130
|
+
const finalPrompt = template
|
|
131
|
+
.replace(/\{resourceName\}/g, resourceName)
|
|
132
|
+
.replace(/\{analysisContext\}/g, analysisContext)
|
|
133
|
+
.replace(/\{schema\}/g, schema || 'No schema provided')
|
|
134
|
+
.replace(/\{metadata\}/g, metadata ? JSON.stringify(metadata, null, 2) : 'No metadata provided');
|
|
135
|
+
return finalPrompt;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Parse AI response into structured capability data
|
|
139
|
+
*
|
|
140
|
+
* @throws Error if AI response cannot be parsed or is invalid
|
|
141
|
+
*/
|
|
142
|
+
parseCapabilitiesFromAI(response) {
|
|
143
|
+
// Look for JSON in the response using standard pattern
|
|
144
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
145
|
+
if (!jsonMatch) {
|
|
146
|
+
throw new Error(`No JSON found in AI response. Response: ${response.substring(0, 200)}...`);
|
|
147
|
+
}
|
|
148
|
+
let parsed;
|
|
149
|
+
try {
|
|
150
|
+
parsed = JSON.parse(jsonMatch[0]);
|
|
151
|
+
}
|
|
152
|
+
catch (parseError) {
|
|
153
|
+
throw new Error(`Invalid JSON in AI response: ${parseError instanceof Error ? parseError.message : String(parseError)}. JSON: ${jsonMatch[0].substring(0, 200)}...`);
|
|
154
|
+
}
|
|
155
|
+
// Validate required fields with detailed error messages
|
|
156
|
+
if (!Array.isArray(parsed.capabilities)) {
|
|
157
|
+
throw new Error(`AI response missing or invalid capabilities array. Got: ${typeof parsed.capabilities}`);
|
|
158
|
+
}
|
|
159
|
+
if (!Array.isArray(parsed.providers)) {
|
|
160
|
+
throw new Error(`AI response missing or invalid providers array. Got: ${typeof parsed.providers}`);
|
|
161
|
+
}
|
|
162
|
+
if (!Array.isArray(parsed.abstractions)) {
|
|
163
|
+
throw new Error(`AI response missing or invalid abstractions array. Got: ${typeof parsed.abstractions}`);
|
|
164
|
+
}
|
|
165
|
+
if (!['low', 'medium', 'high'].includes(parsed.complexity)) {
|
|
166
|
+
throw new Error(`AI response invalid complexity: ${parsed.complexity}. Must be low, medium, or high`);
|
|
167
|
+
}
|
|
168
|
+
if (typeof parsed.description !== 'string' || parsed.description.trim() === '') {
|
|
169
|
+
throw new Error(`AI response missing or invalid description. Got: ${typeof parsed.description}`);
|
|
170
|
+
}
|
|
171
|
+
if (typeof parsed.useCase !== 'string' || parsed.useCase.trim() === '') {
|
|
172
|
+
throw new Error(`AI response missing or invalid useCase. Got: ${typeof parsed.useCase}`);
|
|
173
|
+
}
|
|
174
|
+
if (typeof parsed.confidence !== 'number' || parsed.confidence < 0 || parsed.confidence > 1) {
|
|
175
|
+
throw new Error(`AI response invalid confidence score: ${parsed.confidence}. Must be number between 0-1`);
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
capabilities: parsed.capabilities,
|
|
179
|
+
providers: parsed.providers,
|
|
180
|
+
abstractions: parsed.abstractions,
|
|
181
|
+
complexity: parsed.complexity,
|
|
182
|
+
description: parsed.description.trim(),
|
|
183
|
+
useCase: parsed.useCase.trim(),
|
|
184
|
+
confidence: parsed.confidence
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Build final ResourceCapability from AI analysis result
|
|
189
|
+
*/
|
|
190
|
+
buildResourceCapability(resourceName, aiResult) {
|
|
191
|
+
return {
|
|
192
|
+
resourceName,
|
|
193
|
+
capabilities: aiResult.capabilities,
|
|
194
|
+
providers: aiResult.providers,
|
|
195
|
+
abstractions: aiResult.abstractions,
|
|
196
|
+
complexity: aiResult.complexity,
|
|
197
|
+
description: aiResult.description,
|
|
198
|
+
useCase: aiResult.useCase,
|
|
199
|
+
confidence: aiResult.confidence,
|
|
200
|
+
analyzedAt: new Date().toISOString()
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Generate Vector DB ID for capability storage
|
|
205
|
+
* Creates deterministic UUID from resource name for Qdrant compatibility
|
|
206
|
+
*/
|
|
207
|
+
static generateCapabilityId(resourceName) {
|
|
208
|
+
// Create deterministic UUID from resource name hash
|
|
209
|
+
const crypto = require('crypto');
|
|
210
|
+
const hash = crypto.createHash('sha256').update(`capability-${resourceName}`).digest('hex');
|
|
211
|
+
// Convert to UUID format: 8-4-4-4-12
|
|
212
|
+
return `${hash.substring(0, 8)}-${hash.substring(8, 12)}-${hash.substring(12, 16)}-${hash.substring(16, 20)}-${hash.substring(20, 32)}`;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
exports.CapabilityInferenceEngine = CapabilityInferenceEngine;
|