@vfarcic/dot-ai 0.57.0 → 0.59.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.
@@ -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-3-5-sonnet-20241022',
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
  });
@@ -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, explainResource: (resource: string) => Promise<any>): Promise<ResourceSolution[]>;
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
- * Phase 1: AI selects promising resource candidates from lightweight list
180
- */
181
- private selectResourceCandidates;
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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"}
@@ -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, explainResource) {
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 1b: AI selects best candidates from capability-filtered resources (maintains existing logic)
333
- const candidates = await this.selectResourceCandidates(intent, capabilityFilteredResources, relevantPatterns);
334
- // Phase 2: Fetch detailed schemas for AI-selected candidates and rank (unchanged)
335
- const schemas = await this.fetchDetailedSchemas(candidates, explainResource);
336
- return await this.rankWithDetailedSchemas(intent, schemas, relevantPatterns);
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
- * Phase 1: AI selects promising resource candidates from lightweight list
400
- */
401
- async selectResourceCandidates(intent, resources, patterns = []) {
402
- // Normalize resource structures between standard resources and CRDs
403
- const normalizedResources = resources.map(resource => {
404
- // Handle both standard resources and CRDs
405
- const apiVersion = resource.apiVersion ||
406
- (resource.group ? `${resource.group}/${resource.version}` : resource.version);
407
- const isNamespaced = resource.namespaced !== undefined ?
408
- resource.namespaced :
409
- resource.scope === 'Namespaced';
410
- return {
411
- ...resource,
412
- apiVersion,
413
- namespaced: isNamespaced
414
- };
415
- });
416
- const resourceSummary = normalizedResources.map((resource, index) => {
417
- const basic = `${index}: ${resource.kind} (${resource.apiVersion})
418
- Group: ${resource.group || 'core'}
419
- Namespaced: ${resource.namespaced}`;
420
- // Include rich capability context if available (from capability-based pre-filtering)
421
- if (resource.capabilities) {
422
- const cap = resource.capabilities;
423
- return `${basic}
424
- Resource Name: ${resource.resourceName || 'Not specified'}
425
- Capabilities: ${cap.capabilities?.join(', ') || 'Not specified'}
426
- Providers: ${cap.providers?.join(', ') || 'Not specified'}
427
- Complexity: ${cap.complexity || 'Not specified'}
428
- Use Case: ${cap.useCase || 'Not specified'}
429
- Description: ${cap.description || 'Not specified'}
430
- Confidence: ${cap.confidence || 'N/A'}`;
431
- }
432
- return basic;
433
- }).join('\n\n');
434
- // Format organizational patterns for AI context
435
- const patternsContext = patterns.length > 0
436
- ? patterns.map(pattern => `- ID: ${pattern.id}
437
- Description: ${pattern.description}
438
- Suggested Resources: ${pattern.suggestedResources?.join(', ') || 'Not specified'}
439
- Rationale: ${pattern.rationale}
440
- Triggers: ${pattern.triggers?.join(', ') || 'None'}`).join('\n')
441
- : 'No organizational patterns found for this request.';
442
- const fs = await Promise.resolve().then(() => __importStar(require('fs')));
443
- const path = await Promise.resolve().then(() => __importStar(require('path')));
444
- const promptPath = path.join(__dirname, '..', '..', 'prompts', 'resource-selection.md');
445
- const template = fs.readFileSync(promptPath, 'utf8');
446
- const selectionPrompt = template
447
- .replace('{intent}', intent)
448
- .replace('{resources}', resourceSummary)
449
- .replace('{patterns}', patternsContext);
450
- const response = await this.claudeIntegration.sendMessage(selectionPrompt, 'resource-selection');
451
- try {
452
- // Extract JSON from response with robust parsing
453
- let jsonContent = response.content;
454
- // First try to find JSON array wrapped in code blocks
455
- const codeBlockMatch = response.content.match(/```(?:json)?\s*(\[[\s\S]*?\])\s*```/);
456
- if (codeBlockMatch) {
457
- jsonContent = codeBlockMatch[1];
458
- }
459
- else {
460
- // Try to find JSON array that starts with [ and find the matching closing ]
461
- const startIndex = response.content.indexOf('[');
462
- if (startIndex !== -1) {
463
- let bracketCount = 0;
464
- let endIndex = startIndex;
465
- for (let i = startIndex; i < response.content.length; i++) {
466
- if (response.content[i] === '[')
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
- // Validate that each resource has required fields
485
- for (const resource of selectedResources) {
486
- if (!resource.kind || !resource.apiVersion) {
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
- return selectedResources;
491
- }
492
- catch (error) {
493
- throw new Error(`AI failed to select resources in valid JSON format. Error: ${error.message}. AI response: "${response.content.substring(0, 200)}..."`);
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
  {
2
2
  "name": "@vfarcic/dot-ai",
3
- "version": "0.57.0",
3
+ "version": "0.59.0",
4
4
  "description": "Universal Kubernetes application deployment agent with CLI and MCP interfaces",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,6 +1,6 @@
1
- # Resource Selection Prompt
1
+ # Solution Assembly and Ranking Prompt
2
2
 
3
- You are a Kubernetes expert. Given this user intent and available resources, select the resources that could be relevant for detailed analysis.
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
- **If any organizational pattern above matches this intent (based on pattern triggers), prioritize those resources above all others:**
19
- - **Golden Path Priority** - Pattern resources represent approved organizational standards and should rank higher than cloud-native alternatives
20
- - **Pattern Recognition** - Match pattern triggers against user intent keywords. If triggers match, the pattern's "Suggested Resources" become high-priority candidates
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
- Select all resources that could be relevant for this intent. Consider:
25
- - **🥇 FIRST: Organizational pattern resources** - When patterns match the intent, their suggested resources should appear early in your selection
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
- Don't limit yourself - if the intent is complex, select as many resources as needed. **Be extra inclusive** - the detailed schema analysis phase will filter out inappropriate resources, so it's better to include more candidates initially.
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 array of resource objects with full identifiers. Do NOT wrap in an object - just return the array:
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
- "kind": "Deployment",
49
- "apiVersion": "apps/v1",
50
- "group": "apps"
51
- },
52
- {
53
- "kind": "Service",
54
- "apiVersion": "v1",
55
- "group": ""
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 array, nothing else.
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.