@vfarcic/dot-ai 0.56.0 → 0.58.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/dist/core/claude.js +1 -1
- package/dist/core/schema.d.ts +116 -16
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +259 -211
- package/package.json +1 -1
- package/prompts/resource-selection.md +58 -23
- package/prompts/resource-solution-ranking.md +0 -158
package/dist/core/claude.js
CHANGED
|
@@ -137,7 +137,7 @@ ${response.content}`;
|
|
|
137
137
|
if (this.apiKey.startsWith('sk-ant-') && this.client) {
|
|
138
138
|
// Make real API call to Claude
|
|
139
139
|
const completion = await this.client.messages.create({
|
|
140
|
-
model: 'claude-
|
|
140
|
+
model: 'claude-sonnet-4-20250514', // Latest Claude Sonnet 4 - check for newer versions periodically
|
|
141
141
|
max_tokens: 4000,
|
|
142
142
|
messages: [{ role: 'user', content: message }]
|
|
143
143
|
});
|
package/dist/core/schema.d.ts
CHANGED
|
@@ -157,7 +157,27 @@ export declare class ResourceRecommender {
|
|
|
157
157
|
/**
|
|
158
158
|
* Find the best resource solution(s) for user intent using two-phase analysis
|
|
159
159
|
*/
|
|
160
|
-
findBestSolutions(intent: string,
|
|
160
|
+
findBestSolutions(intent: string, _explainResource: (resource: string) => Promise<any>): Promise<ResourceSolution[]>;
|
|
161
|
+
/**
|
|
162
|
+
* Phase 2: AI assembles and ranks complete solutions (replaces separate selection + ranking)
|
|
163
|
+
*/
|
|
164
|
+
private assembleAndRankSolutions;
|
|
165
|
+
/**
|
|
166
|
+
* Parse AI response for simple solution structure (no schema matching needed)
|
|
167
|
+
*/
|
|
168
|
+
private parseSimpleSolutionResponse;
|
|
169
|
+
/**
|
|
170
|
+
* Load and format solution assembly prompt from file
|
|
171
|
+
*/
|
|
172
|
+
private loadSolutionAssemblyPrompt;
|
|
173
|
+
/**
|
|
174
|
+
* Add pattern-suggested resources that are missing from capability search results
|
|
175
|
+
*/
|
|
176
|
+
private addMissingPatternResources;
|
|
177
|
+
/**
|
|
178
|
+
* Infer cloud providers from resource name
|
|
179
|
+
*/
|
|
180
|
+
private inferProvidersFromResourceName;
|
|
161
181
|
/**
|
|
162
182
|
* Extract Kubernetes kind from resource name (e.g., "sqls.devopstoolkit.live" -> "SQL")
|
|
163
183
|
*/
|
|
@@ -176,25 +196,105 @@ export declare class ResourceRecommender {
|
|
|
176
196
|
*/
|
|
177
197
|
private searchRelevantPatterns;
|
|
178
198
|
/**
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
199
|
+
const basic = `${index}: ${resource.kind} (${resource.apiVersion})
|
|
200
|
+
Group: ${resource.group || 'core'}
|
|
201
|
+
Namespaced: ${resource.namespaced}`;
|
|
202
|
+
|
|
203
|
+
// Include rich capability context if available (from capability-based pre-filtering)
|
|
204
|
+
if (resource.capabilities) {
|
|
205
|
+
const cap = resource.capabilities;
|
|
206
|
+
return `${basic}
|
|
207
|
+
Resource Name: ${resource.resourceName || 'Not specified'}
|
|
208
|
+
Capabilities: ${cap.capabilities?.join(', ') || 'Not specified'}
|
|
209
|
+
Providers: ${cap.providers?.join(', ') || 'Not specified'}
|
|
210
|
+
Complexity: ${cap.complexity || 'Not specified'}
|
|
211
|
+
Use Case: ${cap.useCase || 'Not specified'}
|
|
212
|
+
Description: ${cap.description || 'Not specified'}
|
|
213
|
+
Confidence: ${cap.confidence || 'N/A'}`;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return basic;
|
|
217
|
+
}).join('\n\n');
|
|
218
|
+
|
|
219
|
+
// Format organizational patterns for AI context
|
|
220
|
+
const patternsContext = patterns.length > 0
|
|
221
|
+
? patterns.map(pattern =>
|
|
222
|
+
`- ID: ${pattern.id}
|
|
223
|
+
Description: ${pattern.description}
|
|
224
|
+
Suggested Resources: ${pattern.suggestedResources?.join(', ') || 'Not specified'}
|
|
225
|
+
Rationale: ${pattern.rationale}
|
|
226
|
+
Triggers: ${pattern.triggers?.join(', ') || 'None'}`
|
|
227
|
+
).join('\n')
|
|
228
|
+
: 'No organizational patterns found for this request.';
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
const fs = await import('fs');
|
|
232
|
+
const path = await import('path');
|
|
233
|
+
|
|
234
|
+
const promptPath = path.join(__dirname, '..', '..', 'prompts', 'resource-selection.md');
|
|
235
|
+
const template = fs.readFileSync(promptPath, 'utf8');
|
|
236
|
+
|
|
237
|
+
const selectionPrompt = template
|
|
238
|
+
.replace('{intent}', intent)
|
|
239
|
+
.replace('{resources}', resourceSummary)
|
|
240
|
+
.replace('{patterns}', patternsContext);
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
const response = await this.claudeIntegration.sendMessage(selectionPrompt, 'resource-selection');
|
|
244
|
+
|
|
245
|
+
try {
|
|
246
|
+
// Extract JSON from response with robust parsing
|
|
247
|
+
let jsonContent = response.content;
|
|
248
|
+
|
|
249
|
+
// First try to find JSON array wrapped in code blocks
|
|
250
|
+
const codeBlockMatch = response.content.match(/```(?:json)?\s*(\[[\s\S]*?\])\s*```/);
|
|
251
|
+
if (codeBlockMatch) {
|
|
252
|
+
jsonContent = codeBlockMatch[1];
|
|
253
|
+
} else {
|
|
254
|
+
// Try to find JSON array that starts with [ and find the matching closing ]
|
|
255
|
+
const startIndex = response.content.indexOf('[');
|
|
256
|
+
if (startIndex !== -1) {
|
|
257
|
+
let bracketCount = 0;
|
|
258
|
+
let endIndex = startIndex;
|
|
259
|
+
|
|
260
|
+
for (let i = startIndex; i < response.content.length; i++) {
|
|
261
|
+
if (response.content[i] === '[') bracketCount++;
|
|
262
|
+
if (response.content[i] === ']') bracketCount--;
|
|
263
|
+
if (bracketCount === 0) {
|
|
264
|
+
endIndex = i;
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (bracketCount === 0) {
|
|
270
|
+
jsonContent = response.content.substring(startIndex, endIndex + 1);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const selectedResources = JSON.parse(jsonContent.trim());
|
|
276
|
+
|
|
277
|
+
if (!Array.isArray(selectedResources)) {
|
|
278
|
+
throw new Error('AI response is not an array');
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Validate that each resource has required fields
|
|
282
|
+
for (const resource of selectedResources) {
|
|
283
|
+
if (!resource.kind || !resource.apiVersion) {
|
|
284
|
+
throw new Error(`AI selected invalid resource: ${JSON.stringify(resource)}`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return selectedResources;
|
|
289
|
+
} catch (error) {
|
|
290
|
+
throw new Error(`AI failed to select resources in valid JSON format. Error: ${(error as Error).message}. AI response: "${response.content.substring(0, 200)}..."`);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
182
294
|
/**
|
|
183
295
|
* Phase 2: Fetch detailed schemas for selected candidates
|
|
184
296
|
*/
|
|
185
297
|
private fetchDetailedSchemas;
|
|
186
|
-
/**
|
|
187
|
-
* Phase 3: Rank resources with detailed schema information
|
|
188
|
-
*/
|
|
189
|
-
private rankWithDetailedSchemas;
|
|
190
|
-
/**
|
|
191
|
-
* Load and format prompt template from file
|
|
192
|
-
*/
|
|
193
|
-
private loadPromptTemplate;
|
|
194
|
-
/**
|
|
195
|
-
* Parse AI response into solution results
|
|
196
|
-
*/
|
|
197
|
-
private parseAISolutionResponse;
|
|
198
298
|
/**
|
|
199
299
|
* Discover cluster options for dynamic question generation
|
|
200
300
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/core/schema.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/core/schema.ts"],"names":[],"mappings":"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"}
|
package/dist/core/schema.js
CHANGED
|
@@ -290,7 +290,7 @@ class ResourceRecommender {
|
|
|
290
290
|
/**
|
|
291
291
|
* Find the best resource solution(s) for user intent using two-phase analysis
|
|
292
292
|
*/
|
|
293
|
-
async findBestSolutions(intent,
|
|
293
|
+
async findBestSolutions(intent, _explainResource) {
|
|
294
294
|
if (!this.claudeIntegration.isInitialized()) {
|
|
295
295
|
throw new Error('Claude integration not initialized. API key required for AI-powered resource ranking.');
|
|
296
296
|
}
|
|
@@ -329,16 +329,175 @@ class ResourceRecommender {
|
|
|
329
329
|
namespaced: true, // Default assumption, could be enhanced
|
|
330
330
|
capabilities: cap.data // Include capability data for AI decision-making
|
|
331
331
|
}));
|
|
332
|
-
// Phase
|
|
333
|
-
const
|
|
334
|
-
// Phase 2:
|
|
335
|
-
const
|
|
336
|
-
|
|
332
|
+
// Phase 1: Add missing pattern-suggested resources to available resources list
|
|
333
|
+
const enhancedResources = await this.addMissingPatternResources(capabilityFilteredResources, relevantPatterns);
|
|
334
|
+
// Phase 2: AI assembles and ranks complete solutions (replaces separate selection + ranking phases)
|
|
335
|
+
const solutions = await this.assembleAndRankSolutions(intent, enhancedResources, relevantPatterns);
|
|
336
|
+
// Phase 3: Generate questions for each solution
|
|
337
|
+
for (const solution of solutions) {
|
|
338
|
+
solution.questions = await this.generateQuestionsWithAI(intent, solution);
|
|
339
|
+
}
|
|
340
|
+
return solutions;
|
|
337
341
|
}
|
|
338
342
|
catch (error) {
|
|
339
343
|
throw new Error(`AI-powered resource solution analysis failed: ${error}`);
|
|
340
344
|
}
|
|
341
345
|
}
|
|
346
|
+
/**
|
|
347
|
+
* Phase 2: AI assembles and ranks complete solutions (replaces separate selection + ranking)
|
|
348
|
+
*/
|
|
349
|
+
async assembleAndRankSolutions(intent, availableResources, patterns) {
|
|
350
|
+
const prompt = await this.loadSolutionAssemblyPrompt(intent, availableResources, patterns);
|
|
351
|
+
const response = await this.claudeIntegration.sendMessage(prompt, 'solution-assembly');
|
|
352
|
+
return this.parseSimpleSolutionResponse(response.content);
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Parse AI response for simple solution structure (no schema matching needed)
|
|
356
|
+
*/
|
|
357
|
+
parseSimpleSolutionResponse(aiResponse) {
|
|
358
|
+
try {
|
|
359
|
+
// Use robust JSON extraction
|
|
360
|
+
const parsed = this.extractJsonFromAIResponse(aiResponse);
|
|
361
|
+
const solutions = parsed.solutions.map((solution) => {
|
|
362
|
+
const isDebugMode = process.env.DOT_AI_DEBUG === 'true';
|
|
363
|
+
if (isDebugMode) {
|
|
364
|
+
console.debug('DEBUG: solution object:', JSON.stringify(solution, null, 2));
|
|
365
|
+
}
|
|
366
|
+
// Convert resource references to ResourceSchema format for compatibility
|
|
367
|
+
const resources = (solution.resources || []).map((resource) => ({
|
|
368
|
+
kind: resource.kind,
|
|
369
|
+
apiVersion: resource.apiVersion,
|
|
370
|
+
group: resource.group || '',
|
|
371
|
+
description: `${resource.kind} resource from ${resource.group || 'core'} group`,
|
|
372
|
+
properties: new Map(),
|
|
373
|
+
namespace: true // Default assumption for new architecture
|
|
374
|
+
}));
|
|
375
|
+
return {
|
|
376
|
+
type: solution.type,
|
|
377
|
+
resources,
|
|
378
|
+
score: solution.score,
|
|
379
|
+
description: solution.description,
|
|
380
|
+
reasons: solution.reasons || [],
|
|
381
|
+
analysis: solution.analysis || '',
|
|
382
|
+
questions: { required: [], basic: [], advanced: [], open: { question: '', placeholder: '' } },
|
|
383
|
+
patternInfluences: solution.patternInfluences || [],
|
|
384
|
+
usedPatterns: solution.usedPatterns || false
|
|
385
|
+
};
|
|
386
|
+
});
|
|
387
|
+
// Sort by score descending
|
|
388
|
+
return solutions.sort((a, b) => b.score - a.score);
|
|
389
|
+
}
|
|
390
|
+
catch (error) {
|
|
391
|
+
// Enhanced error message with more context
|
|
392
|
+
const errorMsg = `Failed to parse AI solution response: ${error.message}`;
|
|
393
|
+
const contextMsg = `\nAI Response (first 500 chars): "${aiResponse.substring(0, 500)}..."`;
|
|
394
|
+
throw new Error(errorMsg + contextMsg);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Load and format solution assembly prompt from file
|
|
399
|
+
*/
|
|
400
|
+
async loadSolutionAssemblyPrompt(intent, resources, patterns) {
|
|
401
|
+
const fs = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
402
|
+
const path = await Promise.resolve().then(() => __importStar(require('path')));
|
|
403
|
+
const promptPath = path.join(__dirname, '..', '..', 'prompts', 'resource-selection.md');
|
|
404
|
+
const template = fs.readFileSync(promptPath, 'utf8');
|
|
405
|
+
// Format resources for the prompt with capability information
|
|
406
|
+
const resourcesText = resources.map((resource, index) => {
|
|
407
|
+
return `${index}: ${resource.kind.toUpperCase()} (${resource.apiVersion})
|
|
408
|
+
Group: ${resource.group || 'core'}
|
|
409
|
+
Namespaced: ${resource.namespaced}
|
|
410
|
+
Resource Name: ${resource.resourceName}
|
|
411
|
+
Capabilities: ${Array.isArray(resource.capabilities.capabilities) ? resource.capabilities.capabilities.join(', ') : 'Not specified'}
|
|
412
|
+
Providers: ${Array.isArray(resource.capabilities.providers) ? resource.capabilities.providers.join(', ') : resource.capabilities.providers || 'kubernetes'}
|
|
413
|
+
Complexity: ${resource.capabilities.complexity || 'medium'}
|
|
414
|
+
Use Case: ${resource.capabilities.useCase || resource.capabilities.description || 'General purpose'}
|
|
415
|
+
Description: ${resource.capabilities.description || 'Kubernetes resource'}
|
|
416
|
+
Confidence: ${resource.capabilities.confidence || 1.0}`;
|
|
417
|
+
}).join('\n\n');
|
|
418
|
+
// Format organizational patterns for AI context
|
|
419
|
+
const patternsContext = patterns.length > 0
|
|
420
|
+
? patterns.map(pattern => `- ID: ${pattern.id}
|
|
421
|
+
Description: ${pattern.description}
|
|
422
|
+
Suggested Resources: ${pattern.suggestedResources?.join(', ') || 'Not specified'}
|
|
423
|
+
Rationale: ${pattern.rationale}
|
|
424
|
+
Triggers: ${pattern.triggers?.join(', ') || 'None'}`).join('\n')
|
|
425
|
+
: 'No organizational patterns found for this request.';
|
|
426
|
+
return template
|
|
427
|
+
.replace('{intent}', intent)
|
|
428
|
+
.replace('{resources}', resourcesText)
|
|
429
|
+
.replace('{patterns}', patternsContext);
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Add pattern-suggested resources that are missing from capability search results
|
|
433
|
+
*/
|
|
434
|
+
async addMissingPatternResources(capabilityResources, patterns) {
|
|
435
|
+
if (!patterns.length) {
|
|
436
|
+
return capabilityResources;
|
|
437
|
+
}
|
|
438
|
+
// Extract all resource names already in capability results
|
|
439
|
+
const existingResourceNames = new Set(capabilityResources.map(r => r.resourceName));
|
|
440
|
+
// Collect missing pattern resources
|
|
441
|
+
const missingPatternResources = [];
|
|
442
|
+
for (const pattern of patterns) {
|
|
443
|
+
if (pattern.suggestedResources) {
|
|
444
|
+
for (const suggestedResource of pattern.suggestedResources) {
|
|
445
|
+
// Skip null/undefined resources
|
|
446
|
+
if (!suggestedResource || typeof suggestedResource !== 'string') {
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
449
|
+
// Convert pattern resource format to resource name (e.g., "resourcegroups.azure.upbound.io" -> resourceName)
|
|
450
|
+
const resourceName = suggestedResource.includes('.') ? suggestedResource : `${suggestedResource}.core`;
|
|
451
|
+
// Only add if not already present in capability results
|
|
452
|
+
if (!existingResourceNames.has(resourceName)) {
|
|
453
|
+
try {
|
|
454
|
+
// Parse resource components
|
|
455
|
+
const parts = suggestedResource.split('.');
|
|
456
|
+
const kind = parts[0]; // Use resource name as-is: resourcegroups, servicemonitors, etc.
|
|
457
|
+
const group = parts.length > 1 ? parts.slice(1).join('.') : '';
|
|
458
|
+
const version = 'v1beta1'; // Default version for CRDs, could be enhanced
|
|
459
|
+
const apiVersion = group ? `${group}/${version}` : version;
|
|
460
|
+
missingPatternResources.push({
|
|
461
|
+
kind,
|
|
462
|
+
group,
|
|
463
|
+
apiVersion,
|
|
464
|
+
resourceName,
|
|
465
|
+
namespaced: true, // Default assumption for pattern resources
|
|
466
|
+
capabilities: {
|
|
467
|
+
resourceName,
|
|
468
|
+
description: `Resource suggested by organizational pattern: ${pattern.description}`,
|
|
469
|
+
capabilities: [`organizational pattern`, pattern.description.toLowerCase()],
|
|
470
|
+
providers: this.inferProvidersFromResourceName(suggestedResource),
|
|
471
|
+
complexity: 'medium',
|
|
472
|
+
useCase: `Pattern-suggested resource for: ${pattern.rationale}`,
|
|
473
|
+
confidence: 1.0, // High confidence since it's from organizational pattern
|
|
474
|
+
source: 'organizational-pattern',
|
|
475
|
+
patternId: pattern.id
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
existingResourceNames.add(resourceName);
|
|
479
|
+
}
|
|
480
|
+
catch (error) {
|
|
481
|
+
console.warn(`Failed to parse pattern resource ${suggestedResource}:`, error);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
return [...capabilityResources, ...missingPatternResources];
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Infer cloud providers from resource name
|
|
491
|
+
*/
|
|
492
|
+
inferProvidersFromResourceName(resourceName) {
|
|
493
|
+
if (resourceName.includes('azure'))
|
|
494
|
+
return ['azure'];
|
|
495
|
+
if (resourceName.includes('aws'))
|
|
496
|
+
return ['aws'];
|
|
497
|
+
if (resourceName.includes('gcp') || resourceName.includes('google'))
|
|
498
|
+
return ['gcp'];
|
|
499
|
+
return ['kubernetes'];
|
|
500
|
+
}
|
|
342
501
|
/**
|
|
343
502
|
* Extract Kubernetes kind from resource name (e.g., "sqls.devopstoolkit.live" -> "SQL")
|
|
344
503
|
*/
|
|
@@ -395,104 +554,104 @@ class ResourceRecommender {
|
|
|
395
554
|
return [];
|
|
396
555
|
}
|
|
397
556
|
}
|
|
557
|
+
// REMOVED: selectResourceCandidates - replaced by single-phase assembleAndRankSolutions
|
|
558
|
+
// REMOVED: fetchDetailedSchemas - no longer needed in single-phase architecture
|
|
398
559
|
/**
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
const
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
bracketCount++;
|
|
468
|
-
if (response.content[i] === ']')
|
|
469
|
-
bracketCount--;
|
|
470
|
-
if (bracketCount === 0) {
|
|
471
|
-
endIndex = i;
|
|
472
|
-
break;
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
if (bracketCount === 0) {
|
|
476
|
-
jsonContent = response.content.substring(startIndex, endIndex + 1);
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
const selectedResources = JSON.parse(jsonContent.trim());
|
|
481
|
-
if (!Array.isArray(selectedResources)) {
|
|
482
|
-
throw new Error('AI response is not an array');
|
|
560
|
+
const basic = `${index}: ${resource.kind} (${resource.apiVersion})
|
|
561
|
+
Group: ${resource.group || 'core'}
|
|
562
|
+
Namespaced: ${resource.namespaced}`;
|
|
563
|
+
|
|
564
|
+
// Include rich capability context if available (from capability-based pre-filtering)
|
|
565
|
+
if (resource.capabilities) {
|
|
566
|
+
const cap = resource.capabilities;
|
|
567
|
+
return `${basic}
|
|
568
|
+
Resource Name: ${resource.resourceName || 'Not specified'}
|
|
569
|
+
Capabilities: ${cap.capabilities?.join(', ') || 'Not specified'}
|
|
570
|
+
Providers: ${cap.providers?.join(', ') || 'Not specified'}
|
|
571
|
+
Complexity: ${cap.complexity || 'Not specified'}
|
|
572
|
+
Use Case: ${cap.useCase || 'Not specified'}
|
|
573
|
+
Description: ${cap.description || 'Not specified'}
|
|
574
|
+
Confidence: ${cap.confidence || 'N/A'}`;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
return basic;
|
|
578
|
+
}).join('\n\n');
|
|
579
|
+
|
|
580
|
+
// Format organizational patterns for AI context
|
|
581
|
+
const patternsContext = patterns.length > 0
|
|
582
|
+
? patterns.map(pattern =>
|
|
583
|
+
`- ID: ${pattern.id}
|
|
584
|
+
Description: ${pattern.description}
|
|
585
|
+
Suggested Resources: ${pattern.suggestedResources?.join(', ') || 'Not specified'}
|
|
586
|
+
Rationale: ${pattern.rationale}
|
|
587
|
+
Triggers: ${pattern.triggers?.join(', ') || 'None'}`
|
|
588
|
+
).join('\n')
|
|
589
|
+
: 'No organizational patterns found for this request.';
|
|
590
|
+
|
|
591
|
+
|
|
592
|
+
const fs = await import('fs');
|
|
593
|
+
const path = await import('path');
|
|
594
|
+
|
|
595
|
+
const promptPath = path.join(__dirname, '..', '..', 'prompts', 'resource-selection.md');
|
|
596
|
+
const template = fs.readFileSync(promptPath, 'utf8');
|
|
597
|
+
|
|
598
|
+
const selectionPrompt = template
|
|
599
|
+
.replace('{intent}', intent)
|
|
600
|
+
.replace('{resources}', resourceSummary)
|
|
601
|
+
.replace('{patterns}', patternsContext);
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
const response = await this.claudeIntegration.sendMessage(selectionPrompt, 'resource-selection');
|
|
605
|
+
|
|
606
|
+
try {
|
|
607
|
+
// Extract JSON from response with robust parsing
|
|
608
|
+
let jsonContent = response.content;
|
|
609
|
+
|
|
610
|
+
// First try to find JSON array wrapped in code blocks
|
|
611
|
+
const codeBlockMatch = response.content.match(/```(?:json)?\s*(\[[\s\S]*?\])\s*```/);
|
|
612
|
+
if (codeBlockMatch) {
|
|
613
|
+
jsonContent = codeBlockMatch[1];
|
|
614
|
+
} else {
|
|
615
|
+
// Try to find JSON array that starts with [ and find the matching closing ]
|
|
616
|
+
const startIndex = response.content.indexOf('[');
|
|
617
|
+
if (startIndex !== -1) {
|
|
618
|
+
let bracketCount = 0;
|
|
619
|
+
let endIndex = startIndex;
|
|
620
|
+
|
|
621
|
+
for (let i = startIndex; i < response.content.length; i++) {
|
|
622
|
+
if (response.content[i] === '[') bracketCount++;
|
|
623
|
+
if (response.content[i] === ']') bracketCount--;
|
|
624
|
+
if (bracketCount === 0) {
|
|
625
|
+
endIndex = i;
|
|
626
|
+
break;
|
|
627
|
+
}
|
|
483
628
|
}
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
throw new Error(`AI selected invalid resource: ${JSON.stringify(resource)}`);
|
|
488
|
-
}
|
|
629
|
+
|
|
630
|
+
if (bracketCount === 0) {
|
|
631
|
+
jsonContent = response.content.substring(startIndex, endIndex + 1);
|
|
489
632
|
}
|
|
490
|
-
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
const selectedResources = JSON.parse(jsonContent.trim());
|
|
637
|
+
|
|
638
|
+
if (!Array.isArray(selectedResources)) {
|
|
639
|
+
throw new Error('AI response is not an array');
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
// Validate that each resource has required fields
|
|
643
|
+
for (const resource of selectedResources) {
|
|
644
|
+
if (!resource.kind || !resource.apiVersion) {
|
|
645
|
+
throw new Error(`AI selected invalid resource: ${JSON.stringify(resource)}`);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
return selectedResources;
|
|
650
|
+
} catch (error) {
|
|
651
|
+
throw new Error(`AI failed to select resources in valid JSON format. Error: ${(error as Error).message}. AI response: "${response.content.substring(0, 200)}..."`);
|
|
652
|
+
}
|
|
495
653
|
}
|
|
654
|
+
|
|
496
655
|
/**
|
|
497
656
|
* Phase 2: Fetch detailed schemas for selected candidates
|
|
498
657
|
*/
|
|
@@ -536,117 +695,6 @@ class ResourceRecommender {
|
|
|
536
695
|
}
|
|
537
696
|
return schemas;
|
|
538
697
|
}
|
|
539
|
-
/**
|
|
540
|
-
* Phase 3: Rank resources with detailed schema information
|
|
541
|
-
*/
|
|
542
|
-
async rankWithDetailedSchemas(intent, schemas, patterns = []) {
|
|
543
|
-
const prompt = await this.loadPromptTemplate(intent, schemas, patterns);
|
|
544
|
-
const response = await this.claudeIntegration.sendMessage(prompt, 'resource-ranking');
|
|
545
|
-
const solutions = this.parseAISolutionResponse(response.content, schemas);
|
|
546
|
-
// Generate AI-powered questions for each solution
|
|
547
|
-
for (const solution of solutions) {
|
|
548
|
-
solution.questions = await this.generateQuestionsWithAI(intent, solution);
|
|
549
|
-
}
|
|
550
|
-
return solutions;
|
|
551
|
-
}
|
|
552
|
-
/**
|
|
553
|
-
* Load and format prompt template from file
|
|
554
|
-
*/
|
|
555
|
-
async loadPromptTemplate(intent, schemas, patterns = []) {
|
|
556
|
-
const fs = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
557
|
-
const path = await Promise.resolve().then(() => __importStar(require('path')));
|
|
558
|
-
const promptPath = path.join(__dirname, '..', '..', 'prompts', 'resource-solution-ranking.md');
|
|
559
|
-
const template = fs.readFileSync(promptPath, 'utf8');
|
|
560
|
-
// Format resources for the prompt with detailed schema information
|
|
561
|
-
const resourcesText = schemas.map((schema, index) => {
|
|
562
|
-
let resourceInfo = `${index}: ${schema.kind} (${schema.apiVersion})
|
|
563
|
-
Group: ${schema.group || 'core'}
|
|
564
|
-
Description: ${schema.description}
|
|
565
|
-
Namespaced: ${schema.namespace}`;
|
|
566
|
-
// Include detailed schema information for capability analysis
|
|
567
|
-
if (schema.rawExplanation) {
|
|
568
|
-
resourceInfo += `\n\n Complete Schema Information:\n${schema.rawExplanation}`;
|
|
569
|
-
}
|
|
570
|
-
return resourceInfo;
|
|
571
|
-
}).join('\n\n');
|
|
572
|
-
// Format organizational patterns for AI context
|
|
573
|
-
const patternsContext = patterns.length > 0
|
|
574
|
-
? patterns.map(pattern => `- ID: ${pattern.id}
|
|
575
|
-
Description: ${pattern.description}
|
|
576
|
-
Suggested Resources: ${pattern.suggestedResources?.join(', ') || 'Not specified'}
|
|
577
|
-
Rationale: ${pattern.rationale}
|
|
578
|
-
Triggers: ${pattern.triggers?.join(', ') || 'None'}`).join('\n')
|
|
579
|
-
: 'No organizational patterns found for this request.';
|
|
580
|
-
return template
|
|
581
|
-
.replace('{intent}', intent)
|
|
582
|
-
.replace('{resources}', resourcesText)
|
|
583
|
-
.replace('{patterns}', patternsContext);
|
|
584
|
-
}
|
|
585
|
-
/**
|
|
586
|
-
* Parse AI response into solution results
|
|
587
|
-
*/
|
|
588
|
-
parseAISolutionResponse(aiResponse, schemas) {
|
|
589
|
-
try {
|
|
590
|
-
// Use robust JSON extraction
|
|
591
|
-
const parsed = this.extractJsonFromAIResponse(aiResponse);
|
|
592
|
-
const solutions = parsed.solutions.map((solution) => {
|
|
593
|
-
const isDebugMode = process.env.DOT_AI_DEBUG === 'true';
|
|
594
|
-
if (isDebugMode) {
|
|
595
|
-
console.debug('DEBUG: solution object:', JSON.stringify(solution, null, 2));
|
|
596
|
-
}
|
|
597
|
-
// Find matching schemas for the requested resources
|
|
598
|
-
const resources = [];
|
|
599
|
-
const notFound = [];
|
|
600
|
-
for (const requestedResource of solution.resources || []) {
|
|
601
|
-
const matchingSchema = schemas.find(schema => schema.kind === requestedResource.kind &&
|
|
602
|
-
schema.apiVersion === requestedResource.apiVersion &&
|
|
603
|
-
schema.group === requestedResource.group);
|
|
604
|
-
if (matchingSchema) {
|
|
605
|
-
resources.push(matchingSchema);
|
|
606
|
-
}
|
|
607
|
-
else {
|
|
608
|
-
notFound.push(requestedResource);
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
if (resources.length === 0) {
|
|
612
|
-
if (isDebugMode) {
|
|
613
|
-
console.debug('DEBUG: No matching resources found');
|
|
614
|
-
console.debug('DEBUG: Requested resources:', solution.resources);
|
|
615
|
-
console.debug('DEBUG: Available schemas:', schemas.map(s => ({ kind: s.kind, apiVersion: s.apiVersion, group: s.group })));
|
|
616
|
-
}
|
|
617
|
-
const debugInfo = {
|
|
618
|
-
requestedResources: solution.resources || [],
|
|
619
|
-
notFoundResources: notFound,
|
|
620
|
-
availableSchemas: schemas.map(s => ({ kind: s.kind, apiVersion: s.apiVersion, group: s.group }))
|
|
621
|
-
};
|
|
622
|
-
throw new Error(`No matching resources found: ${JSON.stringify(debugInfo, null, 2)}`);
|
|
623
|
-
}
|
|
624
|
-
if (notFound.length > 0 && isDebugMode) {
|
|
625
|
-
console.debug('DEBUG: Some resources not found:', notFound);
|
|
626
|
-
}
|
|
627
|
-
return {
|
|
628
|
-
type: solution.type,
|
|
629
|
-
resources,
|
|
630
|
-
score: solution.score,
|
|
631
|
-
description: solution.description,
|
|
632
|
-
reasons: solution.reasons || [],
|
|
633
|
-
analysis: solution.analysis || '',
|
|
634
|
-
questions: { required: [], basic: [], advanced: [], open: { question: '', placeholder: '' } },
|
|
635
|
-
patternInfluences: solution.patternInfluences || [],
|
|
636
|
-
usedPatterns: solution.usedPatterns || false
|
|
637
|
-
};
|
|
638
|
-
});
|
|
639
|
-
// Sort by score descending
|
|
640
|
-
return solutions.sort((a, b) => b.score - a.score);
|
|
641
|
-
}
|
|
642
|
-
catch (error) {
|
|
643
|
-
// Enhanced error message with more context
|
|
644
|
-
const errorMsg = `Failed to parse AI solution response: ${error.message}`;
|
|
645
|
-
const contextMsg = `\nAI Response (first 500 chars): "${aiResponse.substring(0, 500)}..."`;
|
|
646
|
-
const schemasMsg = `\nAvailable schemas: ${schemas.map(s => s.kind).join(', ')} (total: ${schemas.length})`;
|
|
647
|
-
throw new Error(errorMsg + contextMsg + schemasMsg);
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
698
|
/**
|
|
651
699
|
* Discover cluster options for dynamic question generation
|
|
652
700
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Solution Assembly and Ranking Prompt
|
|
2
2
|
|
|
3
|
-
You are a Kubernetes expert. Given this user intent
|
|
3
|
+
You are a Kubernetes expert. Given this user intent, available resources, and organizational patterns, create and rank complete solutions that address the user's needs.
|
|
4
4
|
|
|
5
5
|
## User Intent
|
|
6
6
|
{intent}
|
|
@@ -15,14 +15,30 @@ You are a Kubernetes expert. Given this user intent and available resources, sel
|
|
|
15
15
|
|
|
16
16
|
## 🏆 PATTERN PRIORITIZATION (HIGHEST PRIORITY)
|
|
17
17
|
|
|
18
|
-
**
|
|
19
|
-
- **
|
|
20
|
-
- **
|
|
18
|
+
**Pattern-Aware Resource Selection:**
|
|
19
|
+
- **Pattern resources are included** in the Available Resources list below with source marked as "organizational-pattern"
|
|
20
|
+
- **Golden Path Priority** - Pattern resources represent approved organizational standards and should rank higher than alternatives
|
|
21
21
|
- **Higher-Level Abstractions** - Pattern resources often provide better user experience than low-level cloud provider resources
|
|
22
|
-
- **Resource Name Matching** - Find exact "Suggested Resources" names in the "Resource Name" field of available resources
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
**SOLUTION ASSEMBLY APPROACH:**
|
|
24
|
+
|
|
25
|
+
1. **Analyze Available Resources**: Review capabilities, providers, complexity, and use cases
|
|
26
|
+
2. **Apply Pattern Logic**: Read pattern rationales to understand when they apply
|
|
27
|
+
3. **Create Complete Solutions**: Assemble resources into working combinations
|
|
28
|
+
4. **Rank by Effectiveness**: Score based on capability match, pattern compliance, and user intent
|
|
29
|
+
|
|
30
|
+
**CRITICAL: Pattern Conditional Logic**
|
|
31
|
+
- **Read each pattern's "Rationale" field carefully** - it specifies WHEN the pattern applies
|
|
32
|
+
- **Apply patterns conditionally** - only include pattern resources when their technical conditions are met
|
|
33
|
+
- **Resource compatibility analysis**: Before including pattern resources in a solution, verify the pattern's rationale matches the resources you're selecting
|
|
34
|
+
- **API group dependencies**: If a pattern rationale mentions specific API groups (e.g., "solutions using X.api"), only apply that pattern when the solution actually uses resources from those API groups
|
|
35
|
+
- **Multi-provider abstractions**: Higher-level abstractions that work across providers should not automatically trigger provider-specific auxiliary patterns unless technically required
|
|
36
|
+
- **Pattern compliance increases solution score** - solutions following organizational patterns should rank higher, but only when patterns are correctly applied based on technical compatibility
|
|
37
|
+
|
|
38
|
+
Create multiple alternative solutions. Consider:
|
|
39
|
+
- **🥇 FIRST: Pattern-based solutions** - Complete solutions using organizational patterns when applicable
|
|
40
|
+
- **🥈 SECOND: Technology-focused solutions** - Solutions optimized for specific technologies or providers
|
|
41
|
+
- **🥉 THIRD: Complexity variations** - Simple vs comprehensive approaches
|
|
26
42
|
- Direct relevance to the user's needs (applications, infrastructure, operators, networking, storage)
|
|
27
43
|
- Common Kubernetes patterns and best practices
|
|
28
44
|
- Resource relationships and combinations
|
|
@@ -36,28 +52,47 @@ Select all resources that could be relevant for this intent. Consider:
|
|
|
36
52
|
- **Operator patterns**: Look for operators that provide simplified management of complex infrastructure
|
|
37
53
|
- **CRD Selection Priority**: If you see multiple CRDs from the same group with similar purposes (like "App" and "AppClaim"), include the namespace-scoped ones (marked as "Namespaced: true") rather than cluster-scoped ones, as they're more appropriate for application deployments
|
|
38
54
|
|
|
39
|
-
|
|
55
|
+
**Generate 2-5 different solutions** that genuinely address the user intent. Prioritize relevance over quantity - it's better to provide 2-3 high-quality, relevant solutions than to include irrelevant alternatives just to reach a target number.
|
|
40
56
|
|
|
41
57
|
## Response Format
|
|
42
58
|
|
|
43
|
-
Respond with ONLY a JSON
|
|
59
|
+
Respond with ONLY a JSON object containing an array of complete solutions. Each solution should include resources, description, scoring, and pattern compliance:
|
|
44
60
|
|
|
45
61
|
```json
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
62
|
+
{
|
|
63
|
+
"solutions": [
|
|
64
|
+
{
|
|
65
|
+
"type": "combination",
|
|
66
|
+
"resources": [
|
|
67
|
+
{
|
|
68
|
+
"kind": "Deployment",
|
|
69
|
+
"apiVersion": "apps/v1",
|
|
70
|
+
"group": "apps"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"kind": "Service",
|
|
74
|
+
"apiVersion": "v1",
|
|
75
|
+
"group": ""
|
|
76
|
+
}
|
|
77
|
+
],
|
|
78
|
+
"score": 95,
|
|
79
|
+
"description": "Complete web application deployment with networking",
|
|
80
|
+
"reasons": ["High capability match for web applications", "Includes essential networking"],
|
|
81
|
+
"patternInfluences": [
|
|
82
|
+
{
|
|
83
|
+
"patternId": "web-app-pattern-123",
|
|
84
|
+
"description": "Web application deployment pattern",
|
|
85
|
+
"influence": "high",
|
|
86
|
+
"matchedTriggers": ["web application", "frontend"]
|
|
87
|
+
}
|
|
88
|
+
],
|
|
89
|
+
"usedPatterns": true
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
}
|
|
58
93
|
```
|
|
59
94
|
|
|
60
|
-
IMPORTANT: Your response must be ONLY the JSON
|
|
95
|
+
IMPORTANT: Your response must be ONLY the JSON object, nothing else.
|
|
61
96
|
|
|
62
97
|
## Selection Philosophy
|
|
63
98
|
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
# Resource Solution Ranking Prompt
|
|
2
|
-
|
|
3
|
-
You are a Kubernetes expert helping to determine which resource(s) best meet a user's needs.
|
|
4
|
-
|
|
5
|
-
## User Intent
|
|
6
|
-
{intent}
|
|
7
|
-
|
|
8
|
-
## Available Resources
|
|
9
|
-
{resources}
|
|
10
|
-
|
|
11
|
-
## Organizational Patterns
|
|
12
|
-
{patterns}
|
|
13
|
-
|
|
14
|
-
**Note**: If no organizational patterns are provided above, this means pattern matching is unavailable (Vector DB not configured). Focus on pure Kubernetes resource analysis and recommendations.
|
|
15
|
-
|
|
16
|
-
## Instructions
|
|
17
|
-
|
|
18
|
-
Analyze the user's intent and determine the best solution(s). **Provide multiple alternative approaches** ranked by effectiveness, such as:
|
|
19
|
-
- A single resource that fully addresses the need
|
|
20
|
-
- A combination of resources that can actually integrate and work together to create a complete solution
|
|
21
|
-
- Different approaches with varying complexity and capabilities
|
|
22
|
-
|
|
23
|
-
**Organizational Patterns**: Multiple organizational patterns may be provided, each addressing different aspects of the deployment:
|
|
24
|
-
|
|
25
|
-
- **Generic Application Patterns**: Apply to all applications (networking, monitoring, security)
|
|
26
|
-
- **Architectural Patterns**: Apply to specific architectural styles (stateless, microservice, etc.)
|
|
27
|
-
- **Infrastructure Patterns**: Apply to specific integrations (database, messaging, etc.)
|
|
28
|
-
- **Operational Patterns**: Apply to specific operational requirements (scaling, schema management, etc.)
|
|
29
|
-
|
|
30
|
-
**Pattern Composition Strategy**:
|
|
31
|
-
- **Combine relevant patterns** - A single solution can be influenced by multiple patterns
|
|
32
|
-
- **Prioritize by specificity** - More specific patterns should have higher influence than generic ones
|
|
33
|
-
- **Layer pattern guidance** - Generic patterns provide baseline, specific patterns add requirements
|
|
34
|
-
- **Use complete patterns** - When a pattern is relevant, include ALL resources from that pattern unless you have a specific technical reason to exclude them
|
|
35
|
-
- **Pattern resource completeness** - Organizational patterns represent battle-tested, complete solutions. Missing pattern resources often leads to incomplete deployments
|
|
36
|
-
- **Avoid conflicts** - If patterns conflict, prioritize user intent and technical accuracy
|
|
37
|
-
|
|
38
|
-
**IMPORTANT**: Always provide at least 2-3 different solution alternatives when possible, even if some score lower than others. Users benefit from seeing multiple options to choose from.
|
|
39
|
-
|
|
40
|
-
## Validation Requirements
|
|
41
|
-
|
|
42
|
-
**Capability Verification**: For each resource in your solution, examine its schema fields to verify it can fulfill the user's requirements. Do not assume capabilities that aren't explicitly present in the schema fields.
|
|
43
|
-
|
|
44
|
-
**IMPORTANT - Pattern vs Individual Resource Validation**: When using organizational patterns, validate the PATTERN as a whole, not individual resources. Individual resources in a pattern may serve supporting roles and don't need to individually fulfill the complete user requirement - they work together as a complete solution.
|
|
45
|
-
|
|
46
|
-
**Complete Solutions**: Include ALL resource types needed for the solution to work. If your analysis mentions integration with other resources, include those resources in your resources array. For example, if a workload resource has built-in templates or references to other resource types, include those referenced resource types in your solution even if they're managed through the primary resource.
|
|
47
|
-
|
|
48
|
-
**Integration Validation**: For multi-resource solutions, verify that resources have schema fields to reference each other.
|
|
49
|
-
|
|
50
|
-
## Scoring Guidelines
|
|
51
|
-
|
|
52
|
-
**CRITICAL**: Identify whether each solution uses CRDs or standard Kubernetes resources, then apply the appropriate scoring range:
|
|
53
|
-
|
|
54
|
-
### For CRD/Custom Resource Solutions:
|
|
55
|
-
- **90-100**: CRD that clearly addresses user intent - operators provide higher-level abstractions and automatic resource management
|
|
56
|
-
- **70-89**: CRD with partial relevance to user intent - may work but not ideal fit
|
|
57
|
-
- **30-69**: CRD with limited relevance - significant gaps for this use case
|
|
58
|
-
- **0-29**: CRD completely irrelevant to user intent
|
|
59
|
-
|
|
60
|
-
### For Standard Kubernetes Resource Solutions:
|
|
61
|
-
- **80-89**: Standard resource combination that fully addresses user intent
|
|
62
|
-
- **60-79**: Standard resources with minor gaps or additional complexity
|
|
63
|
-
- **30-59**: Standard resources with significant limitations - major gaps in functionality
|
|
64
|
-
- **0-29**: Standard resources poorly suited for this intent
|
|
65
|
-
|
|
66
|
-
**Rationale**: CRDs get preference when relevant because operators provide domain expertise and simplified management. Standard resources remain reliable when no suitable CRDs exist.
|
|
67
|
-
|
|
68
|
-
**IMPORTANT**: Never score a CRD in the 80-89 range (reserved for standard resources) or standard resources in the 90-100 range (reserved for CRDs).
|
|
69
|
-
|
|
70
|
-
## Response Format
|
|
71
|
-
|
|
72
|
-
```json
|
|
73
|
-
{
|
|
74
|
-
"solutions": [
|
|
75
|
-
{
|
|
76
|
-
"type": "combination",
|
|
77
|
-
"resources": [
|
|
78
|
-
{
|
|
79
|
-
"kind": "Deployment",
|
|
80
|
-
"apiVersion": "apps/v1",
|
|
81
|
-
"group": "apps"
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
"kind": "Service",
|
|
85
|
-
"apiVersion": "v1",
|
|
86
|
-
"group": ""
|
|
87
|
-
}
|
|
88
|
-
],
|
|
89
|
-
"score": 95,
|
|
90
|
-
"description": "Complete application deployment with networking",
|
|
91
|
-
"reasons": ["Provides full application lifecycle", "Includes network access"],
|
|
92
|
-
"analysis": "Detailed explanation of schema analysis and why this solution meets the user's needs",
|
|
93
|
-
"patternInfluences": [
|
|
94
|
-
{
|
|
95
|
-
"patternId": "stateless-app-pattern-123",
|
|
96
|
-
"description": "Stateless application deployment pattern",
|
|
97
|
-
"influence": "high",
|
|
98
|
-
"matchedTriggers": ["stateless app", "web application"],
|
|
99
|
-
"matchedConcept": "stateless application"
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
"patternId": "network-policy-pattern-456",
|
|
103
|
-
"description": "Standard networking and security pattern",
|
|
104
|
-
"influence": "medium",
|
|
105
|
-
"matchedTriggers": ["application", "deployment"],
|
|
106
|
-
"matchedConcept": "generic application"
|
|
107
|
-
}
|
|
108
|
-
],
|
|
109
|
-
"usedPatterns": true
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
"type": "single",
|
|
113
|
-
"resources": [
|
|
114
|
-
{
|
|
115
|
-
"kind": "Deployment",
|
|
116
|
-
"apiVersion": "apps/v1",
|
|
117
|
-
"group": "apps"
|
|
118
|
-
}
|
|
119
|
-
],
|
|
120
|
-
"score": 75,
|
|
121
|
-
"description": "Basic application deployment",
|
|
122
|
-
"reasons": ["Simple deployment option", "Lower complexity"],
|
|
123
|
-
"analysis": "Alternative approach with reduced functionality but simpler setup",
|
|
124
|
-
"patternInfluences": [],
|
|
125
|
-
"usedPatterns": false
|
|
126
|
-
}
|
|
127
|
-
]
|
|
128
|
-
}
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
## Pattern Influence Tracking
|
|
132
|
-
|
|
133
|
-
For each solution, you MUST include pattern influence information:
|
|
134
|
-
|
|
135
|
-
**If organizational patterns influenced this solution:**
|
|
136
|
-
- Set `"usedPatterns": true`
|
|
137
|
-
- Include `"patternInfluences"` array with:
|
|
138
|
-
- `patternId`: Use the pattern's ID from the organizational patterns section
|
|
139
|
-
- `description`: Brief description of the pattern
|
|
140
|
-
- `influence`: Rate as "high", "medium", or "low" based on how much the pattern shaped this solution
|
|
141
|
-
- `matchedTriggers`: Which pattern triggers matched the user's intent
|
|
142
|
-
|
|
143
|
-
**If no patterns influenced this solution (or no patterns available):**
|
|
144
|
-
- Set `"usedPatterns": false`
|
|
145
|
-
- Use empty array: `"patternInfluences": []`
|
|
146
|
-
|
|
147
|
-
**Pattern Influence Guidelines:**
|
|
148
|
-
- **High influence**: Pattern directly suggested these specific resources or architecture
|
|
149
|
-
- **Medium influence**: Pattern informed the approach but didn't dictate specific resources
|
|
150
|
-
- **Low influence**: Pattern provided general guidance but minimal impact on final solution
|
|
151
|
-
|
|
152
|
-
**Multiple Pattern Handling:**
|
|
153
|
-
- **Include all relevant patterns** that influenced the solution, even if slightly
|
|
154
|
-
- **Use different influence levels** to show relative importance of each pattern
|
|
155
|
-
- **Match concept context** - Reference which deployment concept led to each pattern match
|
|
156
|
-
- **Show composition** - Demonstrate how multiple patterns work together
|
|
157
|
-
|
|
158
|
-
**IMPORTANT**: In your analysis field, explicitly explain which schema fields enable each requirement from the user intent. If a requirement cannot be fulfilled by available schema fields, explain this and score accordingly.
|