@vfarcic/dot-ai 0.151.0 → 0.152.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.
Files changed (39) hide show
  1. package/README.md +1 -1
  2. package/dist/core/artifacthub.d.ts +85 -0
  3. package/dist/core/artifacthub.d.ts.map +1 -0
  4. package/dist/core/artifacthub.js +106 -0
  5. package/dist/core/helm-types.d.ts +39 -0
  6. package/dist/core/helm-types.d.ts.map +1 -0
  7. package/dist/core/helm-types.js +5 -0
  8. package/dist/core/helm-utils.d.ts +66 -0
  9. package/dist/core/helm-utils.d.ts.map +1 -0
  10. package/dist/core/helm-utils.js +196 -0
  11. package/dist/core/index.d.ts +7 -1
  12. package/dist/core/index.d.ts.map +1 -1
  13. package/dist/core/index.js +12 -0
  14. package/dist/core/schema.d.ts +32 -4
  15. package/dist/core/schema.d.ts.map +1 -1
  16. package/dist/core/schema.js +200 -18
  17. package/dist/core/solution-cr.d.ts.map +1 -1
  18. package/dist/core/solution-cr.js +2 -3
  19. package/dist/tools/answer-question.d.ts.map +1 -1
  20. package/dist/tools/answer-question.js +85 -16
  21. package/dist/tools/choose-solution.d.ts.map +1 -1
  22. package/dist/tools/choose-solution.js +36 -24
  23. package/dist/tools/deploy-manifests.d.ts +2 -1
  24. package/dist/tools/deploy-manifests.d.ts.map +1 -1
  25. package/dist/tools/deploy-manifests.js +86 -2
  26. package/dist/tools/generate-manifests.d.ts +1 -0
  27. package/dist/tools/generate-manifests.d.ts.map +1 -1
  28. package/dist/tools/generate-manifests.js +204 -1
  29. package/dist/tools/recommend.d.ts +3 -2
  30. package/dist/tools/recommend.d.ts.map +1 -1
  31. package/dist/tools/recommend.js +116 -3
  32. package/package.json +1 -1
  33. package/prompts/helm-chart-selection.md +65 -0
  34. package/prompts/helm-generation.md +85 -0
  35. package/prompts/intent-analysis.md +17 -0
  36. package/prompts/question-generation.md +34 -24
  37. package/prompts/resource-selection.md +52 -8
  38. package/shared-prompts/prd-start.md +20 -10
  39. /package/prompts/{manifest-generation.md → capabilities-generation.md} +0 -0
@@ -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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"}
@@ -47,6 +47,7 @@ const capability_vector_service_1 = require("./capability-vector-service");
47
47
  const policy_vector_service_1 = require("./policy-vector-service");
48
48
  const shared_prompt_loader_1 = require("./shared-prompt-loader");
49
49
  const platform_utils_1 = require("./platform-utils");
50
+ const helm_utils_1 = require("./helm-utils");
50
51
  /**
51
52
  * SchemaParser converts kubectl explain output to structured ResourceSchema
52
53
  */
@@ -360,12 +361,17 @@ class ResourceRecommender {
360
361
  // Phase 1: Add missing pattern-suggested resources to available resources list
361
362
  const enhancedResources = await this.addMissingPatternResources(capabilityFilteredResources, relevantPatterns);
362
363
  // Phase 2: AI assembles and ranks complete solutions (replaces separate selection + ranking phases)
363
- const solutions = await this.assembleAndRankSolutions(intent, enhancedResources, relevantPatterns, interaction_id);
364
- // Phase 3: Generate questions for each solution
365
- for (const solution of solutions) {
364
+ const solutionResult = await this.assembleAndRankSolutions(intent, enhancedResources, relevantPatterns, interaction_id);
365
+ // If Helm is recommended, return early - questions will be generated from Helm chart values later
366
+ if (solutionResult.helmRecommendation) {
367
+ console.log(`🎯 Helm installation recommended for "${intent}": ${solutionResult.helmRecommendation.suggestedTool}`);
368
+ return solutionResult;
369
+ }
370
+ // Phase 3: Generate questions for each capability-based solution
371
+ for (const solution of solutionResult.solutions) {
366
372
  solution.questions = await this.generateQuestionsWithAI(intent, solution, _explainResource, interaction_id);
367
373
  }
368
- return solutions;
374
+ return solutionResult;
369
375
  }
370
376
  catch (error) {
371
377
  throw new Error(`AI-powered resource solution analysis failed: ${error}`);
@@ -389,7 +395,16 @@ class ResourceRecommender {
389
395
  try {
390
396
  // Use robust JSON extraction
391
397
  const parsed = (0, platform_utils_1.extractJsonFromAIResponse)(aiResponse);
392
- const solutions = parsed.solutions.map((solution) => {
398
+ // Handle Helm recommendation case (presence of helmRecommendation means Helm is needed)
399
+ const helmRecommendation = parsed.helmRecommendation || null;
400
+ // If Helm is recommended (empty solutions + helmRecommendation present), return early
401
+ if (helmRecommendation && (!parsed.solutions || parsed.solutions.length === 0)) {
402
+ return {
403
+ solutions: [],
404
+ helmRecommendation
405
+ };
406
+ }
407
+ const solutions = (parsed.solutions || []).map((solution) => {
393
408
  const isDebugMode = process.env.DOT_AI_DEBUG === 'true';
394
409
  if (isDebugMode) {
395
410
  console.debug('DEBUG: solution object:', JSON.stringify(solution, null, 2));
@@ -410,13 +425,16 @@ class ResourceRecommender {
410
425
  score: solution.score,
411
426
  description: solution.description,
412
427
  reasons: solution.reasons || [],
413
- analysis: solution.analysis || '',
414
428
  questions: { required: [], basic: [], advanced: [], open: { question: '', placeholder: '' } },
415
429
  appliedPatterns: solution.appliedPatterns || []
416
430
  };
417
431
  });
418
432
  // Sort by score descending
419
- return solutions.sort((a, b) => b.score - a.score);
433
+ const sortedSolutions = solutions.sort((a, b) => b.score - a.score);
434
+ return {
435
+ solutions: sortedSolutions,
436
+ helmRecommendation
437
+ };
420
438
  }
421
439
  catch (error) {
422
440
  // Enhanced error message with more context
@@ -623,21 +641,29 @@ class ResourceRecommender {
623
641
  // Discover namespaces
624
642
  const namespacesResult = await executeKubectl(['get', 'namespaces', '-o', 'jsonpath={.items[*].metadata.name}']);
625
643
  const namespaces = namespacesResult.split(/\s+/).filter(Boolean);
626
- // Discover storage classes
644
+ // Discover storage classes with default marking
627
645
  let storageClasses = [];
628
646
  try {
629
- const storageResult = await executeKubectl(['get', 'storageclass', '-o', 'jsonpath={.items[*].metadata.name}']);
630
- storageClasses = storageResult.split(/\s+/).filter(Boolean);
647
+ const storageResult = await executeKubectl(['get', 'storageclass', '-o', 'json']);
648
+ const storageData = JSON.parse(storageResult);
649
+ storageClasses = (storageData.items || []).map((item) => ({
650
+ name: item.metadata?.name || '',
651
+ isDefault: item.metadata?.annotations?.['storageclass.kubernetes.io/is-default-class'] === 'true'
652
+ }));
631
653
  }
632
654
  catch {
633
655
  // Storage classes might not be available in all clusters
634
656
  storageClasses = [];
635
657
  }
636
- // Discover ingress classes
658
+ // Discover ingress classes with default marking
637
659
  let ingressClasses = [];
638
660
  try {
639
- const ingressResult = await executeKubectl(['get', 'ingressclass', '-o', 'jsonpath={.items[*].metadata.name}']);
640
- ingressClasses = ingressResult.split(/\s+/).filter(Boolean);
661
+ const ingressResult = await executeKubectl(['get', 'ingressclass', '-o', 'json']);
662
+ const ingressData = JSON.parse(ingressResult);
663
+ ingressClasses = (ingressData.items || []).map((item) => ({
664
+ name: item.metadata?.name || '',
665
+ isDefault: item.metadata?.annotations?.['ingressclass.kubernetes.io/is-default-class'] === 'true'
666
+ }));
641
667
  }
642
668
  catch {
643
669
  // Ingress classes might not be available
@@ -678,6 +704,20 @@ class ResourceRecommender {
678
704
  };
679
705
  }
680
706
  }
707
+ /**
708
+ * Format cluster options for inclusion in prompts
709
+ */
710
+ formatClusterOptionsText(clusterOptions) {
711
+ const formatResourceList = (items) => {
712
+ if (items.length === 0)
713
+ return 'None discovered';
714
+ return items.map(item => item.isDefault ? `${item.name} (default)` : item.name).join(', ');
715
+ };
716
+ return `Available Namespaces: ${clusterOptions.namespaces.join(', ')}
717
+ Available Storage Classes: ${formatResourceList(clusterOptions.storageClasses)}
718
+ Available Ingress Classes: ${formatResourceList(clusterOptions.ingressClasses)}
719
+ Available Node Labels: ${clusterOptions.nodeLabels.length > 0 ? clusterOptions.nodeLabels.slice(0, 10).join(', ') : 'None discovered'}`;
720
+ }
681
721
  /**
682
722
  * Generate contextual questions using AI based on user intent and solution resources
683
723
  */
@@ -748,10 +788,7 @@ ${properties}`;
748
788
  }
749
789
  }).join('\n\n');
750
790
  // Format cluster options for the prompt
751
- const clusterOptionsText = `Available Namespaces: ${clusterOptions.namespaces.join(', ')}
752
- Available Storage Classes: ${clusterOptions.storageClasses.length > 0 ? clusterOptions.storageClasses.join(', ') : 'None discovered'}
753
- Available Ingress Classes: ${clusterOptions.ingressClasses.length > 0 ? clusterOptions.ingressClasses.join(', ') : 'None discovered'}
754
- Available Node Labels: ${clusterOptions.nodeLabels.length > 0 ? clusterOptions.nodeLabels.slice(0, 10).join(', ') : 'None discovered'}`;
791
+ const clusterOptionsText = this.formatClusterOptionsText(clusterOptions);
755
792
  // Format organizational policies for AI context with relevance scores
756
793
  const policyContextText = relevantPolicyResults.length > 0
757
794
  ? relevantPolicyResults.map(result => `- ID: ${result.policy.id}
@@ -760,11 +797,17 @@ Available Node Labels: ${clusterOptions.nodeLabels.length > 0 ? clusterOptions.n
760
797
  Triggers: ${result.policy.triggers?.join(', ') || 'None'}
761
798
  Score: ${result.score.toFixed(3)} (${result.matchType})`).join('\n')
762
799
  : 'No organizational policies found for this request.';
800
+ // Build source_material for capabilities (Kubernetes resource-based solutions)
801
+ const sourceMaterial = `## Source Material
802
+ You are generating questions for Kubernetes resources. The schemas below define the available configuration options.
803
+
804
+ ## Resources in Solution
805
+ ${resourceDetails}`;
763
806
  // Generate question prompt with variables
764
807
  const questionPrompt = (0, shared_prompt_loader_1.loadPrompt)('question-generation', {
765
808
  intent,
766
809
  solution_description: solution.description,
767
- resource_details: resourceDetails,
810
+ source_material: sourceMaterial,
768
811
  cluster_options: clusterOptionsText,
769
812
  policy_context: policyContextText
770
813
  });
@@ -798,5 +841,144 @@ Available Node Labels: ${clusterOptions.nodeLabels.length > 0 ? clusterOptions.n
798
841
  };
799
842
  }
800
843
  }
844
+ /**
845
+ * Generate contextual questions for Helm chart installation
846
+ */
847
+ async generateQuestionsForHelmChart(intent, chart, description, interaction_id) {
848
+ try {
849
+ console.log(`📊 Generating questions for Helm chart: ${chart.repositoryName}/${chart.chartName}`);
850
+ // Fetch chart values.yaml and README
851
+ const { valuesYaml, readme } = await this.fetchHelmChartContent(chart);
852
+ // Discover cluster options for dynamic questions
853
+ const clusterOptions = await this.discoverClusterOptions();
854
+ // Search for relevant policy intents
855
+ let relevantPolicyResults = [];
856
+ if (this.policyService) {
857
+ try {
858
+ const policyResults = await this.policyService.searchPolicyIntents(`${intent} ${chart.chartName} helm chart installation`, { limit: 50 });
859
+ relevantPolicyResults = policyResults.map(result => ({
860
+ policy: result.data,
861
+ score: result.score,
862
+ matchType: result.matchType
863
+ }));
864
+ console.log(`🛡️ Found ${relevantPolicyResults.length} relevant policy intents for Helm question generation`);
865
+ }
866
+ catch (error) {
867
+ console.warn('⚠️ Policy search failed during Helm question generation:', error);
868
+ }
869
+ }
870
+ // Build source_material for Helm chart
871
+ const sourceMaterial = `## Source Material
872
+ You are generating questions for a Helm chart installation. The values.yaml and README below define the available configuration options.
873
+
874
+ ## Chart Information
875
+ - Chart: ${chart.chartName}
876
+ - Repository: ${chart.repository}
877
+ - Version: ${chart.version || 'latest'}
878
+
879
+ ## Values.yaml
880
+ \`\`\`yaml
881
+ ${valuesYaml || '# No values.yaml available'}
882
+ \`\`\`
883
+
884
+ ## README
885
+ ${readme || 'No README available'}`;
886
+ // Format organizational policies
887
+ const policyContextText = relevantPolicyResults.length > 0
888
+ ? relevantPolicyResults.map(result => `- ID: ${result.policy.id}
889
+ Description: ${result.policy.description}
890
+ Rationale: ${result.policy.rationale}
891
+ Triggers: ${result.policy.triggers?.join(', ') || 'None'}
892
+ Score: ${result.score.toFixed(3)} (${result.matchType})`).join('\n')
893
+ : 'No organizational policies found for this request.';
894
+ // Format cluster options for the prompt
895
+ const clusterOptionsText = this.formatClusterOptionsText(clusterOptions);
896
+ // Generate questions using the shared prompt
897
+ const questionPrompt = (0, shared_prompt_loader_1.loadPrompt)('question-generation', {
898
+ intent,
899
+ solution_description: description,
900
+ source_material: sourceMaterial,
901
+ cluster_options: clusterOptionsText,
902
+ policy_context: policyContextText
903
+ });
904
+ const response = await this.aiProvider.sendMessage(questionPrompt, 'helm-question-generation', {
905
+ user_intent: `Generate Helm installation questions for: ${intent}`,
906
+ interaction_id: interaction_id || 'helm_question_generation'
907
+ });
908
+ const questions = (0, platform_utils_1.extractJsonFromAIResponse)(response.content);
909
+ if (!questions.required || !questions.basic || !questions.advanced) {
910
+ throw new Error('Invalid question structure from AI');
911
+ }
912
+ if (!questions.open) {
913
+ questions.open = {
914
+ question: "Any additional configuration requirements?",
915
+ placeholder: "e.g., custom values, specific settings..."
916
+ };
917
+ }
918
+ console.log(`✅ Generated ${questions.required.length} required, ${questions.basic.length} basic, ${questions.advanced.length} advanced questions`);
919
+ return questions;
920
+ }
921
+ catch (error) {
922
+ console.warn(`Failed to generate questions for Helm chart: ${error}`);
923
+ // Fallback to minimal questions
924
+ return {
925
+ required: [
926
+ {
927
+ id: 'name',
928
+ question: 'What name should be used for this Helm release?',
929
+ type: 'text',
930
+ suggestedAnswer: chart.chartName
931
+ },
932
+ {
933
+ id: 'namespace',
934
+ question: 'Which namespace should this be installed in?',
935
+ type: 'text',
936
+ suggestedAnswer: 'default'
937
+ }
938
+ ],
939
+ basic: [],
940
+ advanced: [],
941
+ open: {
942
+ question: "Any additional configuration requirements?",
943
+ placeholder: "e.g., custom values, specific settings..."
944
+ }
945
+ };
946
+ }
947
+ }
948
+ /**
949
+ * Fetch Helm chart values.yaml and README
950
+ */
951
+ async fetchHelmChartContent(chart) {
952
+ let valuesYaml = '';
953
+ let readme = '';
954
+ // Sanitize chart info to prevent command injection
955
+ const safeChart = (0, helm_utils_1.sanitizeChartInfo)(chart);
956
+ const versionFlag = safeChart.version ? `--version ${safeChart.version}` : '';
957
+ try {
958
+ // Add repo and update
959
+ await (0, platform_utils_1.execAsync)(`helm repo add ${safeChart.repositoryName} ${safeChart.repository} 2>/dev/null || true`);
960
+ await (0, platform_utils_1.execAsync)('helm repo update 2>/dev/null || true');
961
+ }
962
+ catch {
963
+ console.warn(`⚠️ Could not add/update Helm repo ${safeChart.repositoryName}`);
964
+ }
965
+ try {
966
+ const { stdout } = await (0, platform_utils_1.execAsync)(`helm show values ${safeChart.repositoryName}/${safeChart.chartName} ${versionFlag}`.trim());
967
+ valuesYaml = stdout || '';
968
+ console.log(`📄 Fetched values.yaml (${valuesYaml.length} chars)`);
969
+ }
970
+ catch (error) {
971
+ console.warn(`⚠️ Could not fetch values.yaml: ${error}`);
972
+ }
973
+ try {
974
+ const { stdout } = await (0, platform_utils_1.execAsync)(`helm show readme ${safeChart.repositoryName}/${safeChart.chartName} ${versionFlag}`.trim());
975
+ readme = stdout || '';
976
+ console.log(`📄 Fetched README (${readme.length} chars)`);
977
+ }
978
+ catch {
979
+ // README is optional
980
+ }
981
+ return { valuesYaml, readme };
982
+ }
801
983
  }
802
984
  exports.ResourceRecommender = ResourceRecommender;
@@ -1 +1 @@
1
- {"version":3,"file":"solution-cr.d.ts","sourceRoot":"","sources":["../../src/core/solution-cr.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,YAAY,CAAC;IACvB,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CA2CrE"}
1
+ {"version":3,"file":"solution-cr.d.ts","sourceRoot":"","sources":["../../src/core/solution-cr.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,YAAY,CAAC;IACvB,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CA0CrE"}
@@ -51,11 +51,10 @@ function generateSolutionCR(options) {
51
51
  const { solutionId, namespace, solution, generatedManifestsYaml } = options;
52
52
  // Parse generated manifests to extract actual resource references
53
53
  const resourceReferences = extractResourceReferences(generatedManifestsYaml, namespace);
54
- // Build rationale from solution description, reasons, and analysis
54
+ // Build rationale from solution description and reasons
55
55
  const rationale = [
56
56
  solution.description,
57
- ...solution.reasons,
58
- solution.analysis
57
+ ...solution.reasons
59
58
  ].filter(Boolean).join('\n\n');
60
59
  // Get patterns and policies from session
61
60
  const patterns = solution.appliedPatterns || [];
@@ -1 +1 @@
1
- {"version":3,"file":"answer-question.d.ts","sourceRoot":"","sources":["../../src/tools/answer-question.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAOhD,eAAO,MAAM,wBAAwB,mBAAmB,CAAC;AACzD,eAAO,MAAM,+BAA+B,8HAA4H,CAAC;AAGzK,eAAO,MAAM,gCAAgC;;;;;;;;;;CAK5C,CAAC;AAifF;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,EACtI,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CAAC,CAgSxD"}
1
+ {"version":3,"file":"answer-question.d.ts","sourceRoot":"","sources":["../../src/tools/answer-question.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAOhD,eAAO,MAAM,wBAAwB,mBAAmB,CAAC;AACzD,eAAO,MAAM,+BAA+B,8HAA4H,CAAC;AAGzK,eAAO,MAAM,gCAAgC;;;;;;;;;;CAK5C,CAAC;AA4hBF;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,EACtI,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CAAC,CAgUxD"}
@@ -74,15 +74,19 @@ function validateAnswer(answer, question) {
74
74
  }
75
75
  /**
76
76
  * Get stage-specific instructions for different stages
77
+ * For Helm solutions, advanced stage proceeds directly to manifest generation (no open stage)
77
78
  */
78
- function getStageSpecificInstructions(stage) {
79
+ function getStageSpecificInstructions(stage, isHelm = false) {
79
80
  switch (stage) {
80
81
  case 'required':
81
82
  return 'STAGE: REQUIRED - All questions must be answered before proceeding. No skipping allowed.';
82
83
  case 'basic':
83
84
  return 'STAGE: BASIC - These questions can be skipped. User can provide answers or say "skip" to proceed to advanced stage.';
84
85
  case 'advanced':
85
- return 'STAGE: ADVANCED - These questions can be skipped. User can provide answers or say "skip" to proceed to open stage.';
86
+ // For Helm, don't mention open stage since it's skipped
87
+ return isHelm
88
+ ? 'STAGE: ADVANCED - These questions can be skipped. User can provide answers or say "skip" to proceed to manifest generation.'
89
+ : 'STAGE: ADVANCED - These questions can be skipped. User can provide answers or say "skip" to proceed to open stage.';
86
90
  case 'open':
87
91
  return 'STAGE: OPEN - Final configuration stage. User can provide additional requirements or say "N/A" to proceed to manifest generation.';
88
92
  default:
@@ -92,7 +96,7 @@ function getStageSpecificInstructions(stage) {
92
96
  /**
93
97
  * Get enhanced anti-cascade agent instructions for stage responses
94
98
  */
95
- function getAgentInstructions(stage) {
99
+ function getAgentInstructions(stage, isHelm = false) {
96
100
  const antiCascadeRule = 'CRITICAL ANTI-CASCADE RULE: When user says "skip" for ANY stage, only skip THAT specific stage and present the NEXT stage questions to the user. NEVER automatically skip multiple stages in sequence.';
97
101
  const mandatoryWorkflow = `
98
102
  MANDATORY CLIENT AGENT WORKFLOW:
@@ -102,42 +106,61 @@ MANDATORY CLIENT AGENT WORKFLOW:
102
106
  4. If user says "skip": call answerQuestion with empty answers object ({})
103
107
  5. NEVER call answerQuestion without receiving user input first
104
108
  6. NEVER assume what the user wants for subsequent stages`;
105
- const strictConstraints = `
109
+ // For Helm, don't mention open stage constraints
110
+ const strictConstraints = isHelm ? `
111
+ STRICT BEHAVIORAL CONSTRAINTS:
112
+ - DO NOT call answerQuestion automatically
113
+ - DO NOT assume user wants to proceed to manifest generation
114
+ - DO NOT interpret "skip" as "automatically proceed to next stage"
115
+ - MUST present each stage's questions individually and wait for user response` : `
106
116
  STRICT BEHAVIORAL CONSTRAINTS:
107
117
  - DO NOT call answerQuestion automatically
108
118
  - DO NOT assume user wants to proceed to manifest generation
109
119
  - DO NOT call answerQuestion with empty open stage answers unless user explicitly provides them
110
120
  - DO NOT interpret "skip" as "automatically proceed to next stage"
111
121
  - MUST present each stage's questions individually and wait for user response`;
112
- const stageSpecific = getStageSpecificInstructions(stage);
122
+ const stageSpecific = getStageSpecificInstructions(stage, isHelm);
113
123
  return `${antiCascadeRule}\n${mandatoryWorkflow}\n${strictConstraints}\n\n${stageSpecific}`;
114
124
  }
125
+ /**
126
+ * Check if solution is a Helm-based installation
127
+ */
128
+ function isHelmSolution(solution) {
129
+ return solution.type === 'helm';
130
+ }
115
131
  /**
116
132
  * Determine current stage based on solution state
133
+ * For Helm solutions, the open stage is skipped entirely
117
134
  */
118
135
  function getCurrentStage(solution) {
119
136
  const hasRequired = solution.questions.required && solution.questions.required.length > 0;
120
137
  const hasBasic = solution.questions.basic && solution.questions.basic.length > 0;
121
138
  const hasAdvanced = solution.questions.advanced && solution.questions.advanced.length > 0;
122
139
  const hasOpen = !!solution.questions.open;
140
+ const isHelm = isHelmSolution(solution);
123
141
  // Check completion status
124
142
  const requiredComplete = !hasRequired || solution.questions.required.every((q) => q.answer !== undefined);
125
143
  const basicComplete = !hasBasic || solution.questions.basic.every((q) => q.answer !== undefined);
126
144
  const advancedComplete = !hasAdvanced || solution.questions.advanced.every((q) => q.answer !== undefined);
127
- const openComplete = !hasOpen || solution.questions.open.answer !== undefined;
145
+ // For Helm solutions, treat open as always complete (skip it)
146
+ const openComplete = isHelm || !hasOpen || solution.questions.open.answer !== undefined;
128
147
  // Determine current stage
129
148
  if (!requiredComplete) {
149
+ // For Helm: skip open in nextStage calculation
150
+ const nextAfterRequired = hasBasic ? 'basic' : (hasAdvanced ? 'advanced' : (isHelm ? null : 'open'));
130
151
  return {
131
152
  currentStage: 'required',
132
- nextStage: hasBasic ? 'basic' : 'open',
153
+ nextStage: nextAfterRequired,
133
154
  hasQuestions: true,
134
155
  isComplete: false
135
156
  };
136
157
  }
137
158
  if (!basicComplete) {
159
+ // For Helm: skip open in nextStage calculation
160
+ const nextAfterBasic = hasAdvanced ? 'advanced' : (isHelm ? null : 'open');
138
161
  return {
139
162
  currentStage: 'basic',
140
- nextStage: hasAdvanced ? 'advanced' : 'open',
163
+ nextStage: nextAfterBasic,
141
164
  hasQuestions: true,
142
165
  isComplete: false
143
166
  };
@@ -145,11 +168,21 @@ function getCurrentStage(solution) {
145
168
  if (!advancedComplete) {
146
169
  return {
147
170
  currentStage: 'advanced',
148
- nextStage: 'open',
171
+ // For Helm: go directly to completion (null), not open
172
+ nextStage: isHelm ? null : 'open',
149
173
  hasQuestions: true,
150
174
  isComplete: false
151
175
  };
152
176
  }
177
+ // For Helm, we're complete after advanced (skip open)
178
+ if (isHelm) {
179
+ return {
180
+ currentStage: 'advanced',
181
+ nextStage: null,
182
+ hasQuestions: false,
183
+ isComplete: true
184
+ };
185
+ }
153
186
  if (!openComplete) {
154
187
  return {
155
188
  currentStage: 'open',
@@ -174,6 +207,7 @@ function validateStageTransition(currentStage, requestedStage, solution) {
174
207
  if (currentStage === requestedStage) {
175
208
  return { valid: true };
176
209
  }
210
+ const isHelm = isHelmSolution(solution);
177
211
  // Determine the next stage based on what questions exist
178
212
  let expectedNext = null;
179
213
  if (currentStage === 'required') {
@@ -184,7 +218,8 @@ function validateStageTransition(currentStage, requestedStage, solution) {
184
218
  expectedNext = 'advanced';
185
219
  }
186
220
  else {
187
- expectedNext = 'open';
221
+ // For Helm, skip open stage
222
+ expectedNext = isHelm ? null : 'open';
188
223
  }
189
224
  }
190
225
  else if (currentStage === 'basic') {
@@ -192,11 +227,13 @@ function validateStageTransition(currentStage, requestedStage, solution) {
192
227
  expectedNext = 'advanced';
193
228
  }
194
229
  else {
195
- expectedNext = 'open';
230
+ // For Helm, skip open stage
231
+ expectedNext = isHelm ? null : 'open';
196
232
  }
197
233
  }
198
234
  else if (currentStage === 'advanced') {
199
- expectedNext = 'open';
235
+ // For Helm, skip open stage - go to completion
236
+ expectedNext = isHelm ? null : 'open';
200
237
  }
201
238
  else {
202
239
  expectedNext = null; // open stage is final
@@ -254,14 +291,17 @@ function getStageMessage(stage) {
254
291
  /**
255
292
  * Get stage-specific guidance
256
293
  */
257
- function getStageGuidance(stage) {
294
+ function getStageGuidance(stage, isHelm = false) {
258
295
  switch (stage) {
259
296
  case 'required':
260
297
  return 'All required questions must be answered to proceed.';
261
298
  case 'basic':
262
299
  return 'Answer questions in this stage or skip to proceed to the advanced stage. Do NOT try to generate manifests yet.';
263
300
  case 'advanced':
264
- return 'Answer questions in this stage or skip to proceed to the open stage. Do NOT try to generate manifests yet.';
301
+ // For Helm, don't mention the open stage since it's skipped
302
+ return isHelm
303
+ ? 'Answer questions in this stage or skip to proceed to manifest generation.'
304
+ : 'Answer questions in this stage or skip to proceed to the open stage. Do NOT try to generate manifests yet.';
265
305
  case 'open':
266
306
  return 'Use "N/A" if you have no additional requirements. Complete this stage before generating manifests.';
267
307
  default:
@@ -642,6 +682,35 @@ async function handleAnswerQuestionTool(args, dotAI, logger, requestId) {
642
682
  }
643
683
  // Regular stage flow: determine next stage and return questions
644
684
  const newStageState = getCurrentStage(solution);
685
+ // For Helm solutions, if all stages are complete, return ready for manifest generation
686
+ // This happens when advanced stage is completed (open stage is skipped for Helm)
687
+ if (newStageState.isComplete && isHelmSolution(solution)) {
688
+ const userAnswers = (0, solution_utils_1.extractUserAnswers)(solution);
689
+ const completionResponse = {
690
+ status: 'ready_for_manifest_generation',
691
+ solutionId: args.solutionId,
692
+ message: 'Configuration complete. Ready to generate Helm values.',
693
+ solutionData: {
694
+ primaryResources: solution.resources || [],
695
+ type: solution.type || 'helm',
696
+ description: solution.description || '',
697
+ userAnswers: userAnswers,
698
+ hasOpenRequirements: false
699
+ },
700
+ nextAction: 'Call recommend tool with stage: generateManifests',
701
+ guidance: 'All configuration stages are complete. Ready to generate Helm values.yaml for deployment.',
702
+ agentInstructions: 'All configuration stages are now complete. You may proceed to generate Helm values using the generateManifests tool.',
703
+ timestamp: new Date().toISOString()
704
+ };
705
+ return {
706
+ content: [
707
+ {
708
+ type: 'text',
709
+ text: JSON.stringify(completionResponse, null, 2)
710
+ }
711
+ ]
712
+ };
713
+ }
645
714
  // If stage is complete, move to next stage
646
715
  const nextStageQuestions = getQuestionsForStage(solution, newStageState.currentStage);
647
716
  const response = {
@@ -651,8 +720,8 @@ async function handleAnswerQuestionTool(args, dotAI, logger, requestId) {
651
720
  questions: nextStageQuestions,
652
721
  nextStage: newStageState.nextStage,
653
722
  message: getStageMessage(newStageState.currentStage),
654
- guidance: getStageGuidance(newStageState.currentStage),
655
- agentInstructions: getAgentInstructions(newStageState.currentStage),
723
+ guidance: getStageGuidance(newStageState.currentStage, isHelmSolution(solution)),
724
+ agentInstructions: getAgentInstructions(newStageState.currentStage, isHelmSolution(solution)),
656
725
  nextAction: `Call recommend tool with stage: answerQuestion:${newStageState.currentStage}`,
657
726
  timestamp: new Date().toISOString()
658
727
  };
@@ -1 +1 @@
1
- {"version":3,"file":"choose-solution.d.ts","sourceRoot":"","sources":["../../src/tools/choose-solution.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAKhD,eAAO,MAAM,wBAAwB,mBAAmB,CAAC;AACzD,eAAO,MAAM,+BAA+B,uEAAuE,CAAC;AAGpH,eAAO,MAAM,gCAAgC;;CAE5C,CAAC;AAIF;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,EAC5B,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CAAC,CA2GxD"}
1
+ {"version":3,"file":"choose-solution.d.ts","sourceRoot":"","sources":["../../src/tools/choose-solution.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAKhD,eAAO,MAAM,wBAAwB,mBAAmB,CAAC;AACzD,eAAO,MAAM,+BAA+B,uEAAuE,CAAC;AAGpH,eAAO,MAAM,gCAAgC;;CAE5C,CAAC;AAIF;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,EAC5B,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CAAC,CA8HxD"}
@@ -43,31 +43,43 @@ async function handleChooseSolutionTool(args, dotAI, logger, requestId) {
43
43
  });
44
44
  }
45
45
  const solution = session.data;
46
- try {
47
- logger.debug('Solution file loaded successfully', {
48
- solutionId: args.solutionId,
49
- hasQuestions: !!solution.questions,
50
- questionCategories: {
51
- required: solution.questions?.required?.length || 0,
52
- basic: solution.questions?.basic?.length || 0,
53
- advanced: solution.questions?.advanced?.length || 0,
54
- hasOpen: !!solution.questions?.open
55
- }
56
- });
57
- }
58
- catch (error) {
59
- throw error_handling_1.ErrorHandler.createError(error_handling_1.ErrorCategory.STORAGE, error_handling_1.ErrorSeverity.HIGH, error instanceof Error ? error.message : 'Failed to load solution session', {
60
- operation: 'solution_session_load',
61
- component: 'ChooseSolutionTool',
62
- requestId,
63
- input: { solutionId: args.solutionId },
64
- suggestedActions: [
65
- 'Check that the solution ID is correct',
66
- 'Verify the solution session exists',
67
- 'Ensure the solution was created by a recent recommend tool call'
68
- ]
69
- });
46
+ // For Helm solutions, generate questions if not already present
47
+ if (solution.type === 'helm' && solution.chart) {
48
+ const hasQuestions = (solution.questions?.required?.length ?? 0) > 0 ||
49
+ (solution.questions?.basic?.length ?? 0) > 0 ||
50
+ (solution.questions?.advanced?.length ?? 0) > 0;
51
+ if (!hasQuestions) {
52
+ logger.info('Generating questions for Helm solution', {
53
+ requestId,
54
+ solutionId: args.solutionId,
55
+ chart: solution.chart.chartName
56
+ });
57
+ const questions = await dotAI.schema.generateQuestionsForHelmChart(solution.intent, solution.chart, solution.description, `choose_solution_${args.solutionId}`);
58
+ solution.questions = questions;
59
+ // Update the session with generated questions
60
+ sessionManager.updateSession(args.solutionId, solution);
61
+ logger.info('Helm questions generated and saved', {
62
+ requestId,
63
+ solutionId: args.solutionId,
64
+ questionCounts: {
65
+ required: questions.required?.length || 0,
66
+ basic: questions.basic?.length || 0,
67
+ advanced: questions.advanced?.length || 0
68
+ }
69
+ });
70
+ }
70
71
  }
72
+ logger.debug('Solution file loaded successfully', {
73
+ solutionId: args.solutionId,
74
+ type: solution.type,
75
+ hasQuestions: !!solution.questions,
76
+ questionCategories: {
77
+ required: solution.questions?.required?.length || 0,
78
+ basic: solution.questions?.basic?.length || 0,
79
+ advanced: solution.questions?.advanced?.length || 0,
80
+ hasOpen: !!solution.questions?.open
81
+ }
82
+ });
71
83
  // Prepare response with solution details and questions
72
84
  const response = {
73
85
  status: 'stage_questions',