@vfarcic/dot-ai 0.155.0 → 0.157.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -25
- package/assets/images/logo-orig.jpeg +0 -0
- package/assets/images/logo.jpeg +0 -0
- package/dist/core/packaging.d.ts +50 -0
- package/dist/core/packaging.d.ts.map +1 -0
- package/dist/core/packaging.js +281 -0
- package/dist/core/schema.d.ts +6 -0
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +46 -5
- package/dist/tools/generate-manifests.d.ts.map +1 -1
- package/dist/tools/generate-manifests.js +233 -4
- package/package.json +1 -1
- package/prompts/intent-analysis.md +1 -1
- package/prompts/packaging-generation.md +66 -0
- package/prompts/question-generation.md +2 -0
- package/assets/images/logo.png +0 -0
package/README.md
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
# DevOps AI Toolkit
|
|
2
2
|
|
|
3
|
+
<!-- docs-exclude-start -->
|
|
3
4
|
<div align="center">
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
<p align="center">
|
|
7
|
+
<img src="assets/images/logo.jpeg" alt="DevOps AI Toolkit Logo" width="400">
|
|
8
|
+
</p>
|
|
6
9
|
|
|
7
10
|
[](https://www.npmjs.com/package/@vfarcic/dot-ai)
|
|
8
11
|
[](https://www.npmjs.com/package/@vfarcic/dot-ai)
|
|
@@ -13,11 +16,13 @@
|
|
|
13
16
|
[](https://github.com/vfarcic/dot-ai)
|
|
14
17
|
|
|
15
18
|
</div>
|
|
19
|
+
<!-- docs-exclude-end -->
|
|
16
20
|
|
|
17
21
|
**AI-powered platform engineering and DevOps automation through intelligent Kubernetes operations and conversational workflows.**
|
|
18
22
|
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
<!-- docs-exclude-start -->
|
|
24
|
+
📚 [Quick Start](./docs/quick-start.md) | 🔧 [MCP Setup](./docs/setup/mcp-setup.md) | 🛠️ [Features & Tools](./docs/guides/mcp-tools-overview.md)
|
|
25
|
+
<!-- docs-exclude-end -->
|
|
21
26
|
---
|
|
22
27
|
|
|
23
28
|
## What is DevOps AI Toolkit?
|
|
@@ -58,36 +63,30 @@ DevOps AI Toolkit democratizes platform engineering and cloud native operations
|
|
|
58
63
|
|
|
59
64
|
### 🔍 Resource Provisioning Intelligence
|
|
60
65
|
Automatically discovers cluster resources using semantic capability management. AI understands what each resource actually does, providing intelligent recommendations for provisioning resources across clouds using Kubernetes as a control plane. When no matching capability exists, automatically discovers and installs third-party tools (Prometheus, Argo CD, Crossplane, etc.) via Helm charts from ArtifactHub.
|
|
61
|
-
📖 [Deployment Guide](./docs/mcp-recommendation-guide.md) | [Capability Management](./docs/mcp-capability-management-guide.md)
|
|
66
|
+
📖 [Deployment Guide](./docs/guides/mcp-recommendation-guide.md) | [Capability Management](./docs/guides/mcp-capability-management-guide.md)
|
|
62
67
|
|
|
63
68
|
### 🛠️ Issue Remediation
|
|
64
69
|
AI-powered root cause analysis with multi-step investigation, executable remediation commands, and safety mechanisms for manual or automatic execution.
|
|
65
|
-
📖 [Learn more →](./docs/mcp-remediate-guide.md)
|
|
70
|
+
📖 [Learn more →](./docs/guides/mcp-remediate-guide.md)
|
|
66
71
|
|
|
67
72
|
### 🏛️ Pattern & Policy Management
|
|
68
73
|
Capture organizational knowledge and governance policies that automatically enhance AI recommendations with best practices and compliance requirements. Uses vector search for intelligent semantic matching.
|
|
69
|
-
📖 [Pattern Management](./docs/pattern-management-guide.md) | [Policy Management](./docs/policy-management-guide.md)
|
|
74
|
+
📖 [Pattern Management](./docs/guides/pattern-management-guide.md) | [Policy Management](./docs/guides/policy-management-guide.md)
|
|
70
75
|
|
|
71
76
|
### 📦 Project Setup & Governance
|
|
72
77
|
Generate 25+ governance, legal, and automation files (LICENSE, CODE_OF_CONDUCT, CONTRIBUTING, SECURITY, GitHub workflows, Renovate, OpenSSF Scorecard) for repository standardization.
|
|
73
|
-
📖 [Learn more →](./docs/mcp-project-setup-guide.md)
|
|
78
|
+
📖 [Learn more →](./docs/guides/mcp-project-setup-guide.md)
|
|
74
79
|
|
|
75
80
|
### 💬 Shared Prompts Library
|
|
76
81
|
Access curated prompts as native slash commands (`/dot-ai:prompt-name`) in your coding agent for consistent workflows across projects:
|
|
77
82
|
- **PRD Management**: Create, track, and complete Product Requirements Documents (`prd-create`, `prd-next`, `prd-done`, etc.)
|
|
78
83
|
- **Dockerfile Generation**: Generate production-ready, secure multi-stage Dockerfiles for any project (`generate-dockerfile`)
|
|
79
84
|
|
|
80
|
-
📖 [Learn more →](./docs/mcp-prompts-guide.md)
|
|
85
|
+
📖 [Learn more →](./docs/guides/mcp-prompts-guide.md)
|
|
81
86
|
|
|
82
87
|
### ⚡ AI Integration
|
|
83
88
|
Works with Claude Code, Cursor, VS Code via Model Context Protocol. Supports multiple AI providers (Claude, GPT, Gemini) for flexibility and cost optimization.
|
|
84
|
-
📖 [AI Model Configuration](./docs/mcp-setup.md#ai-model-configuration)
|
|
85
|
-
|
|
86
|
-
## See It In Action
|
|
87
|
-
|
|
88
|
-
[](https://youtu.be/8Yzn-9qQpQI)
|
|
89
|
-
|
|
90
|
-
This video explains the platform engineering problem and demonstrates the Kubernetes deployment recommendation workflow from intent to running applications.
|
|
89
|
+
📖 [AI Model Configuration](./docs/setup/mcp-setup.md#ai-model-configuration)
|
|
91
90
|
|
|
92
91
|
## Quick Start
|
|
93
92
|
|
|
@@ -100,23 +99,24 @@ Get started in 3 steps:
|
|
|
100
99
|
|
|
101
100
|
### Getting Started
|
|
102
101
|
- **[Quick Start Guide](docs/quick-start.md)** - Get started in minutes
|
|
103
|
-
- **[MCP Setup Guide](docs/mcp-setup.md)** - Complete configuration instructions
|
|
104
|
-
- **[Tools Overview](docs/mcp-tools-overview.md)** - All available tools and features
|
|
102
|
+
- **[MCP Setup Guide](docs/setup/mcp-setup.md)** - Complete configuration instructions
|
|
103
|
+
- **[Tools Overview](docs/guides/mcp-tools-overview.md)** - All available tools and features
|
|
105
104
|
|
|
106
105
|
### Feature Guides
|
|
107
|
-
- **[Resource Provisioning](docs/mcp-recommendation-guide.md)** - AI-powered deployment recommendations
|
|
108
|
-
- **[Capability Management](docs/mcp-capability-management-guide.md)** - Semantic resource discovery
|
|
109
|
-
- **[Issue Remediation](docs/mcp-remediate-guide.md)** - AI-powered troubleshooting
|
|
110
|
-
- **[Pattern Management](docs/pattern-management-guide.md)** - Organizational deployment patterns
|
|
111
|
-
- **[Policy Management](docs/policy-management-guide.md)** - Governance and compliance
|
|
112
|
-
- **[Project Setup](docs/mcp-project-setup-guide.md)** - Repository governance automation
|
|
113
|
-
|
|
106
|
+
- **[Resource Provisioning](docs/guides/mcp-recommendation-guide.md)** - AI-powered deployment recommendations
|
|
107
|
+
- **[Capability Management](docs/guides/mcp-capability-management-guide.md)** - Semantic resource discovery
|
|
108
|
+
- **[Issue Remediation](docs/guides/mcp-remediate-guide.md)** - AI-powered troubleshooting
|
|
109
|
+
- **[Pattern Management](docs/guides/pattern-management-guide.md)** - Organizational deployment patterns
|
|
110
|
+
- **[Policy Management](docs/guides/policy-management-guide.md)** - Governance and compliance
|
|
111
|
+
- **[Project Setup](docs/guides/mcp-project-setup-guide.md)** - Repository governance automation
|
|
112
|
+
|
|
113
|
+
<!-- docs-exclude-start -->
|
|
114
114
|
## Support
|
|
115
115
|
|
|
116
116
|
- **[Support Guide](SUPPORT.md)** - How to get help and where to ask questions
|
|
117
117
|
- **GitHub Issues**: [Bug reports and feature requests](https://github.com/vfarcic/dot-ai/issues)
|
|
118
118
|
- **GitHub Discussions**: [Community Q&A and discussions](https://github.com/vfarcic/dot-ai/discussions)
|
|
119
|
-
- **Troubleshooting**: See [Troubleshooting Guide](./docs/mcp-setup.md#troubleshooting) for common problems
|
|
119
|
+
- **Troubleshooting**: See [Troubleshooting Guide](./docs/setup/mcp-setup.md#troubleshooting) for common problems
|
|
120
120
|
|
|
121
121
|
## Contributing & Governance
|
|
122
122
|
|
|
@@ -146,6 +146,7 @@ DevOps AI Toolkit is built on:
|
|
|
146
146
|
- [Vercel AI SDK](https://sdk.vercel.ai/) for unified AI provider interface
|
|
147
147
|
- [Kubernetes](https://kubernetes.io/) for the cloud native foundation
|
|
148
148
|
- [CNCF](https://www.cncf.io/) for the cloud native ecosystem
|
|
149
|
+
<!-- docs-exclude-end -->
|
|
149
150
|
|
|
150
151
|
---
|
|
151
152
|
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Packaging Module - Convert raw Kubernetes manifests to Helm charts or Kustomize overlays
|
|
3
|
+
*
|
|
4
|
+
* Implements AI-driven packaging as specified in PRD #248.
|
|
5
|
+
* Raw manifests are always generated and validated first, then packaged based on outputFormat.
|
|
6
|
+
*/
|
|
7
|
+
import { Logger } from './error-handling';
|
|
8
|
+
import { DotAI } from './index';
|
|
9
|
+
/**
|
|
10
|
+
* Output format types supported by packaging
|
|
11
|
+
*/
|
|
12
|
+
export type OutputFormat = 'raw' | 'helm' | 'kustomize';
|
|
13
|
+
/**
|
|
14
|
+
* File entry in packaging response
|
|
15
|
+
*/
|
|
16
|
+
export interface PackageFile {
|
|
17
|
+
relativePath: string;
|
|
18
|
+
content: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Result of packaging operation
|
|
22
|
+
*/
|
|
23
|
+
export interface PackagingResult {
|
|
24
|
+
files: PackageFile[];
|
|
25
|
+
format: OutputFormat;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Error context for packaging retries
|
|
29
|
+
*/
|
|
30
|
+
interface PackagingErrorContext {
|
|
31
|
+
attempt: number;
|
|
32
|
+
previousOutput: string;
|
|
33
|
+
validationError: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Package raw Kubernetes manifests into Helm chart or Kustomize overlay
|
|
37
|
+
*
|
|
38
|
+
* @param rawManifests - Validated raw Kubernetes YAML manifests
|
|
39
|
+
* @param solution - Solution data with intent, questions, answers
|
|
40
|
+
* @param outputFormat - Target format ('helm' or 'kustomize')
|
|
41
|
+
* @param outputPath - User-specified output path
|
|
42
|
+
* @param dotAI - DotAI instance for AI calls
|
|
43
|
+
* @param logger - Logger instance
|
|
44
|
+
* @param errorContext - Optional error context for retries
|
|
45
|
+
* @param interaction_id - Optional interaction ID for evaluation
|
|
46
|
+
* @returns PackagingResult with files array
|
|
47
|
+
*/
|
|
48
|
+
export declare function packageManifests(rawManifests: string, solution: any, outputFormat: OutputFormat, outputPath: string, dotAI: DotAI, logger: Logger, errorContext?: PackagingErrorContext, interaction_id?: string): Promise<PackagingResult>;
|
|
49
|
+
export {};
|
|
50
|
+
//# sourceMappingURL=packaging.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packaging.d.ts","sourceRoot":"","sources":["../../src/core/packaging.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,MAAM,GAAG,WAAW,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED;;GAEG;AACH,UAAU,qBAAqB;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;CACzB;AAgOD;;;;;;;;;;;;GAYG;AACH,wBAAsB,gBAAgB,CACpC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,GAAG,EACb,YAAY,EAAE,YAAY,EAC1B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,qBAAqB,EACpC,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,eAAe,CAAC,CA+D1B"}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Packaging Module - Convert raw Kubernetes manifests to Helm charts or Kustomize overlays
|
|
4
|
+
*
|
|
5
|
+
* Implements AI-driven packaging as specified in PRD #248.
|
|
6
|
+
* Raw manifests are always generated and validated first, then packaged based on outputFormat.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.packageManifests = packageManifests;
|
|
10
|
+
const shared_prompt_loader_1 = require("./shared-prompt-loader");
|
|
11
|
+
/**
|
|
12
|
+
* Format-specific instructions for Helm chart generation
|
|
13
|
+
*/
|
|
14
|
+
const HELM_FORMAT_INSTRUCTIONS = `
|
|
15
|
+
### Helm Chart Structure
|
|
16
|
+
|
|
17
|
+
Generate the following files:
|
|
18
|
+
|
|
19
|
+
1. **Chart.yaml** - Chart metadata
|
|
20
|
+
- \`apiVersion: v2\`
|
|
21
|
+
- \`name\`: derived from application name
|
|
22
|
+
- \`description\`: based on user intent
|
|
23
|
+
- \`version: 0.1.0\`
|
|
24
|
+
- \`appVersion\`: from image tag if available, otherwise \`1.0.0\`
|
|
25
|
+
|
|
26
|
+
2. **values.yaml** - Default configuration values
|
|
27
|
+
- Include comments explaining each value
|
|
28
|
+
- Group related values logically (e.g., \`image.repository\`, \`image.tag\`)
|
|
29
|
+
- Use the actual values from user answers as defaults
|
|
30
|
+
|
|
31
|
+
3. **templates/*.yaml** - One file per Kubernetes resource type
|
|
32
|
+
- Use \`{{ .Release.Name }}\` for resource names
|
|
33
|
+
- Use \`{{ .Release.Namespace }}\` when namespace is referenced
|
|
34
|
+
- Use \`{{ .Values.xxx }}\` for externalized configuration
|
|
35
|
+
- Ensure label selectors match between related resources
|
|
36
|
+
- Quote string values that might be interpreted as numbers: \`{{ .Values.someValue | quote }}\`
|
|
37
|
+
`;
|
|
38
|
+
/**
|
|
39
|
+
* Format-specific example for Helm chart
|
|
40
|
+
*/
|
|
41
|
+
const HELM_FORMAT_EXAMPLE = `
|
|
42
|
+
### Example Helm Output
|
|
43
|
+
|
|
44
|
+
\`\`\`json
|
|
45
|
+
{
|
|
46
|
+
"files": [
|
|
47
|
+
{
|
|
48
|
+
"relativePath": "Chart.yaml",
|
|
49
|
+
"content": "apiVersion: v2\\nname: my-app\\ndescription: A Helm chart for my-app\\nversion: 0.1.0\\nappVersion: \\"1.0.0\\""
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"relativePath": "values.yaml",
|
|
53
|
+
"content": "# Number of replicas\\nreplicaCount: 3\\n\\n# Container image\\nimage:\\n repository: nginx\\n tag: \\"1.21\\"\\n pullPolicy: IfNotPresent"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"relativePath": "templates/deployment.yaml",
|
|
57
|
+
"content": "apiVersion: apps/v1\\nkind: Deployment\\nmetadata:\\n name: {{ .Release.Name }}\\n namespace: {{ .Release.Namespace }}\\nspec:\\n replicas: {{ .Values.replicaCount }}\\n ..."
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
\`\`\`
|
|
62
|
+
`;
|
|
63
|
+
/**
|
|
64
|
+
* Format-specific instructions for Kustomize generation
|
|
65
|
+
*/
|
|
66
|
+
const KUSTOMIZE_FORMAT_INSTRUCTIONS = `
|
|
67
|
+
### Kustomize Structure
|
|
68
|
+
|
|
69
|
+
Generate a production-ready Kustomize structure with base/ and overlays/ directories:
|
|
70
|
+
|
|
71
|
+
1. **base/kustomization.yaml** - Base kustomization file
|
|
72
|
+
- \`apiVersion: kustomize.config.k8s.io/v1beta1\`
|
|
73
|
+
- \`kind: Kustomization\`
|
|
74
|
+
- List all resource files in \`resources:\` section (e.g., \`- deployment.yaml\`)
|
|
75
|
+
- Do NOT include namespace, patches, or images here - base should be generic/reusable
|
|
76
|
+
|
|
77
|
+
2. **base/*.yaml** - Base Kubernetes manifests
|
|
78
|
+
- One file per Kubernetes resource (deployment.yaml, service.yaml, etc.)
|
|
79
|
+
- Include complete, valid manifests
|
|
80
|
+
- For container images: use ONLY the repository (e.g., \`image: nginx\` or \`image: ghcr.io/org/app\`) WITHOUT any tag - tags are set in overlays
|
|
81
|
+
- Resource names should be consistent across all files
|
|
82
|
+
|
|
83
|
+
3. **overlays/production/kustomization.yaml** - Production overlay (THE KEY FILE FOR CUSTOMIZATION)
|
|
84
|
+
- \`apiVersion: kustomize.config.k8s.io/v1beta1\`
|
|
85
|
+
- \`kind: Kustomization\`
|
|
86
|
+
- Reference base: \`resources: [../../base]\`
|
|
87
|
+
- Use \`namespace:\` field with the user-specified namespace
|
|
88
|
+
- **REQUIRED**: Use \`images:\` section to set image tags from user answers:
|
|
89
|
+
\`\`\`yaml
|
|
90
|
+
images:
|
|
91
|
+
- name: <repository-without-tag>
|
|
92
|
+
newTag: <tag-from-user-answer>
|
|
93
|
+
\`\`\`
|
|
94
|
+
- Use \`replicas:\` section if replicas were customized
|
|
95
|
+
- Use \`patches:\` for other customizations (resources, env vars, etc.)
|
|
96
|
+
|
|
97
|
+
4. **kustomization.yaml** (root) - Points to production overlay for easy deployment
|
|
98
|
+
- Simple file that references the production overlay: \`resources: [overlays/production]\`
|
|
99
|
+
|
|
100
|
+
**WHY THIS STRUCTURE**:
|
|
101
|
+
- \`base/\` contains generic, reusable manifests (like Helm templates)
|
|
102
|
+
- \`overlays/production/kustomization.yaml\` is like \`values.yaml\` - the single file users edit to customize
|
|
103
|
+
- Users can add \`overlays/staging/\`, \`overlays/dev/\` by copying the production overlay
|
|
104
|
+
- To upgrade: change \`newTag\` in the overlay, not the base manifests
|
|
105
|
+
`;
|
|
106
|
+
/**
|
|
107
|
+
* Format-specific example for Kustomize
|
|
108
|
+
*/
|
|
109
|
+
const KUSTOMIZE_FORMAT_EXAMPLE = `
|
|
110
|
+
### Example Kustomize Output
|
|
111
|
+
|
|
112
|
+
\`\`\`json
|
|
113
|
+
{
|
|
114
|
+
"files": [
|
|
115
|
+
{
|
|
116
|
+
"relativePath": "kustomization.yaml",
|
|
117
|
+
"content": "apiVersion: kustomize.config.k8s.io/v1beta1\\nkind: Kustomization\\nresources:\\n - overlays/production"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"relativePath": "overlays/production/kustomization.yaml",
|
|
121
|
+
"content": "apiVersion: kustomize.config.k8s.io/v1beta1\\nkind: Kustomization\\nnamespace: production\\nresources:\\n - ../../base\\nimages:\\n - name: nginx\\n newTag: \\"1.21\\"\\nreplicas:\\n - name: my-app\\n count: 3"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"relativePath": "base/kustomization.yaml",
|
|
125
|
+
"content": "apiVersion: kustomize.config.k8s.io/v1beta1\\nkind: Kustomization\\nresources:\\n - deployment.yaml\\n - service.yaml"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"relativePath": "base/deployment.yaml",
|
|
129
|
+
"content": "apiVersion: apps/v1\\nkind: Deployment\\nmetadata:\\n name: my-app\\nspec:\\n replicas: 1\\n selector:\\n matchLabels:\\n app: my-app\\n template:\\n metadata:\\n labels:\\n app: my-app\\n spec:\\n containers:\\n - name: my-app\\n image: nginx\\n ports:\\n - containerPort: 80"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"relativePath": "base/service.yaml",
|
|
133
|
+
"content": "apiVersion: v1\\nkind: Service\\nmetadata:\\n name: my-app\\nspec:\\n selector:\\n app: my-app\\n ports:\\n - port: 80\\n targetPort: 80"
|
|
134
|
+
}
|
|
135
|
+
]
|
|
136
|
+
}
|
|
137
|
+
\`\`\`
|
|
138
|
+
`;
|
|
139
|
+
/**
|
|
140
|
+
* Get format-specific configuration for prompt template
|
|
141
|
+
*/
|
|
142
|
+
function getFormatConfig(format) {
|
|
143
|
+
switch (format) {
|
|
144
|
+
case 'helm':
|
|
145
|
+
return {
|
|
146
|
+
outputFormat: 'Helm Chart',
|
|
147
|
+
outputFormatDescription: 'a complete Helm chart structure',
|
|
148
|
+
formatSpecificInstructions: HELM_FORMAT_INSTRUCTIONS,
|
|
149
|
+
formatExample: HELM_FORMAT_EXAMPLE
|
|
150
|
+
};
|
|
151
|
+
case 'kustomize':
|
|
152
|
+
return {
|
|
153
|
+
outputFormat: 'Kustomize',
|
|
154
|
+
outputFormatDescription: 'a Kustomize overlay structure',
|
|
155
|
+
formatSpecificInstructions: KUSTOMIZE_FORMAT_INSTRUCTIONS,
|
|
156
|
+
formatExample: KUSTOMIZE_FORMAT_EXAMPLE
|
|
157
|
+
};
|
|
158
|
+
default:
|
|
159
|
+
throw new Error(`Unsupported format for packaging: ${format}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Format questions and answers for prompt
|
|
164
|
+
*/
|
|
165
|
+
function formatQuestionsAndAnswers(solution) {
|
|
166
|
+
const lines = [];
|
|
167
|
+
const questionCategories = ['required', 'basic', 'advanced'];
|
|
168
|
+
for (const category of questionCategories) {
|
|
169
|
+
const questions = solution.questions?.[category] || [];
|
|
170
|
+
for (const q of questions) {
|
|
171
|
+
if (q.answer !== undefined && q.answer !== null) {
|
|
172
|
+
lines.push(`- **${q.question}**: ${q.answer}`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (solution.questions?.open?.answer) {
|
|
177
|
+
lines.push(`- **Open requirements**: ${solution.questions.open.answer}`);
|
|
178
|
+
}
|
|
179
|
+
return lines.length > 0 ? lines.join('\n') : 'No user answers provided.';
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Parse JSON response from AI, handling potential markdown code blocks
|
|
183
|
+
*/
|
|
184
|
+
function parsePackagingResponse(response) {
|
|
185
|
+
// Try to extract JSON from markdown code blocks if present
|
|
186
|
+
let jsonContent = response.trim();
|
|
187
|
+
// Remove markdown code blocks if present
|
|
188
|
+
// Use greedy match (*) not lazy (*?) to handle nested code blocks in content (e.g., README with ```bash examples)
|
|
189
|
+
// The $ anchor ensures we match the LAST closing ```
|
|
190
|
+
const jsonMatch = jsonContent.match(/```(?:json)?\s*([\s\S]*)```\s*$/);
|
|
191
|
+
if (jsonMatch) {
|
|
192
|
+
jsonContent = jsonMatch[1].trim();
|
|
193
|
+
}
|
|
194
|
+
// Parse JSON
|
|
195
|
+
let parsed;
|
|
196
|
+
try {
|
|
197
|
+
parsed = JSON.parse(jsonContent);
|
|
198
|
+
}
|
|
199
|
+
catch (parseError) {
|
|
200
|
+
const preview = jsonContent.slice(0, 200);
|
|
201
|
+
throw new Error(`Failed to parse packaging response as JSON: ${parseError instanceof Error ? parseError.message : String(parseError)}. Content preview: ${preview}...`);
|
|
202
|
+
}
|
|
203
|
+
if (!parsed.files || !Array.isArray(parsed.files)) {
|
|
204
|
+
throw new Error('Invalid packaging response: missing files array');
|
|
205
|
+
}
|
|
206
|
+
// Validate each file entry
|
|
207
|
+
for (const file of parsed.files) {
|
|
208
|
+
if (typeof file.relativePath !== 'string' || typeof file.content !== 'string') {
|
|
209
|
+
throw new Error('Invalid packaging response: each file must have relativePath and content strings');
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return parsed.files;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Package raw Kubernetes manifests into Helm chart or Kustomize overlay
|
|
216
|
+
*
|
|
217
|
+
* @param rawManifests - Validated raw Kubernetes YAML manifests
|
|
218
|
+
* @param solution - Solution data with intent, questions, answers
|
|
219
|
+
* @param outputFormat - Target format ('helm' or 'kustomize')
|
|
220
|
+
* @param outputPath - User-specified output path
|
|
221
|
+
* @param dotAI - DotAI instance for AI calls
|
|
222
|
+
* @param logger - Logger instance
|
|
223
|
+
* @param errorContext - Optional error context for retries
|
|
224
|
+
* @param interaction_id - Optional interaction ID for evaluation
|
|
225
|
+
* @returns PackagingResult with files array
|
|
226
|
+
*/
|
|
227
|
+
async function packageManifests(rawManifests, solution, outputFormat, outputPath, dotAI, logger, errorContext, interaction_id) {
|
|
228
|
+
if (outputFormat === 'raw') {
|
|
229
|
+
// Raw format - no packaging needed
|
|
230
|
+
return {
|
|
231
|
+
files: [{ relativePath: 'manifests.yaml', content: rawManifests }],
|
|
232
|
+
format: 'raw'
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
logger.info('Packaging manifests', {
|
|
236
|
+
format: outputFormat,
|
|
237
|
+
outputPath,
|
|
238
|
+
isRetry: !!errorContext,
|
|
239
|
+
attempt: errorContext?.attempt
|
|
240
|
+
});
|
|
241
|
+
// Get format-specific configuration
|
|
242
|
+
const formatConfig = getFormatConfig(outputFormat);
|
|
243
|
+
// Prepare template variables
|
|
244
|
+
const previousAttempt = errorContext
|
|
245
|
+
? `Previous attempt output:\n\`\`\`json\n${errorContext.previousOutput}\n\`\`\``
|
|
246
|
+
: 'None - this is the first attempt.';
|
|
247
|
+
const errorDetails = errorContext
|
|
248
|
+
? `**Attempt**: ${errorContext.attempt}\n**Validation Error**: ${errorContext.validationError}`
|
|
249
|
+
: 'None - this is the first attempt.';
|
|
250
|
+
// Load and populate prompt template
|
|
251
|
+
const prompt = (0, shared_prompt_loader_1.loadPrompt)('packaging-generation', {
|
|
252
|
+
output_format: formatConfig.outputFormat,
|
|
253
|
+
output_format_description: formatConfig.outputFormatDescription,
|
|
254
|
+
intent: solution.intent || 'Kubernetes deployment',
|
|
255
|
+
solution_description: solution.description || solution.title || 'No description available',
|
|
256
|
+
raw_manifests: rawManifests,
|
|
257
|
+
questions_and_answers: formatQuestionsAndAnswers(solution),
|
|
258
|
+
output_path: outputPath,
|
|
259
|
+
format_specific_instructions: formatConfig.formatSpecificInstructions,
|
|
260
|
+
format_example: formatConfig.formatExample,
|
|
261
|
+
previous_attempt: previousAttempt,
|
|
262
|
+
error_details: errorDetails
|
|
263
|
+
});
|
|
264
|
+
// Call AI for packaging
|
|
265
|
+
const aiProvider = dotAI.ai;
|
|
266
|
+
const response = await aiProvider.sendMessage(prompt, `packaging-${outputFormat}`, {
|
|
267
|
+
user_intent: solution.intent || 'Package Kubernetes manifests',
|
|
268
|
+
interaction_id
|
|
269
|
+
});
|
|
270
|
+
// Parse response
|
|
271
|
+
const files = parsePackagingResponse(response.content);
|
|
272
|
+
logger.info('Packaging completed', {
|
|
273
|
+
format: outputFormat,
|
|
274
|
+
fileCount: files.length,
|
|
275
|
+
files: files.map(f => f.relativePath)
|
|
276
|
+
});
|
|
277
|
+
return {
|
|
278
|
+
files,
|
|
279
|
+
format: outputFormat
|
|
280
|
+
};
|
|
281
|
+
}
|
package/dist/core/schema.d.ts
CHANGED
|
@@ -82,6 +82,12 @@ export interface QuestionGroup {
|
|
|
82
82
|
};
|
|
83
83
|
relevantPolicies?: string[];
|
|
84
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Packaging questions for capability-based solutions (not Helm charts)
|
|
87
|
+
* These are injected programmatically after AI generates questions
|
|
88
|
+
*/
|
|
89
|
+
export declare const OUTPUT_FORMAT_QUESTION: Question;
|
|
90
|
+
export declare const OUTPUT_PATH_QUESTION: Question;
|
|
85
91
|
export interface ResourceSolution {
|
|
86
92
|
type: 'single' | 'combination';
|
|
87
93
|
resources: ResourceSchema[];
|
|
@@ -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
|
@@ -39,7 +39,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
39
39
|
};
|
|
40
40
|
})();
|
|
41
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.ResourceRecommender = exports.ManifestValidator = exports.SchemaParser = void 0;
|
|
42
|
+
exports.ResourceRecommender = exports.ManifestValidator = exports.SchemaParser = exports.OUTPUT_PATH_QUESTION = exports.OUTPUT_FORMAT_QUESTION = void 0;
|
|
43
43
|
const kubernetes_utils_1 = require("./kubernetes-utils");
|
|
44
44
|
const pattern_vector_service_1 = require("./pattern-vector-service");
|
|
45
45
|
const vector_db_service_1 = require("./vector-db-service");
|
|
@@ -48,6 +48,46 @@ 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
50
|
const helm_utils_1 = require("./helm-utils");
|
|
51
|
+
/**
|
|
52
|
+
* Packaging questions for capability-based solutions (not Helm charts)
|
|
53
|
+
* These are injected programmatically after AI generates questions
|
|
54
|
+
*/
|
|
55
|
+
exports.OUTPUT_FORMAT_QUESTION = {
|
|
56
|
+
id: 'outputFormat',
|
|
57
|
+
question: 'How would you like the manifests packaged?',
|
|
58
|
+
type: 'select',
|
|
59
|
+
options: ['raw', 'helm', 'kustomize'],
|
|
60
|
+
placeholder: 'Select output format',
|
|
61
|
+
suggestedAnswer: 'raw',
|
|
62
|
+
validation: { required: true }
|
|
63
|
+
};
|
|
64
|
+
exports.OUTPUT_PATH_QUESTION = {
|
|
65
|
+
id: 'outputPath',
|
|
66
|
+
question: 'Where would you like to save the output?',
|
|
67
|
+
type: 'text',
|
|
68
|
+
placeholder: 'e.g., ./manifests or ./my-app',
|
|
69
|
+
suggestedAnswer: './manifests',
|
|
70
|
+
validation: { required: true }
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Inject packaging questions into a QuestionGroup for capability-based solutions
|
|
74
|
+
* Adds outputFormat and outputPath to required questions if not already present
|
|
75
|
+
*/
|
|
76
|
+
function injectPackagingQuestions(questions) {
|
|
77
|
+
const hasOutputFormat = questions.required.some(q => q.id === 'outputFormat');
|
|
78
|
+
const hasOutputPath = questions.required.some(q => q.id === 'outputPath');
|
|
79
|
+
const packagingQuestions = [];
|
|
80
|
+
if (!hasOutputFormat) {
|
|
81
|
+
packagingQuestions.push({ ...exports.OUTPUT_FORMAT_QUESTION });
|
|
82
|
+
}
|
|
83
|
+
if (!hasOutputPath) {
|
|
84
|
+
packagingQuestions.push({ ...exports.OUTPUT_PATH_QUESTION });
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
...questions,
|
|
88
|
+
required: [...questions.required, ...packagingQuestions]
|
|
89
|
+
};
|
|
90
|
+
}
|
|
51
91
|
/**
|
|
52
92
|
* SchemaParser converts kubectl explain output to structured ResourceSchema
|
|
53
93
|
*/
|
|
@@ -821,7 +861,8 @@ ${resourceDetails}`;
|
|
|
821
861
|
if (!questions.required || !questions.basic || !questions.advanced || !questions.open) {
|
|
822
862
|
throw new Error('Invalid question structure from AI');
|
|
823
863
|
}
|
|
824
|
-
|
|
864
|
+
// Inject packaging questions for capability-based solutions
|
|
865
|
+
return injectPackagingQuestions(questions);
|
|
825
866
|
}
|
|
826
867
|
catch (error) {
|
|
827
868
|
// Re-throw errors about missing resourceName - these are bugs, not generation failures
|
|
@@ -829,8 +870,8 @@ ${resourceDetails}`;
|
|
|
829
870
|
throw error;
|
|
830
871
|
}
|
|
831
872
|
console.warn(`Failed to generate AI questions for solution: ${error}`);
|
|
832
|
-
// Fallback to basic open question
|
|
833
|
-
return {
|
|
873
|
+
// Fallback to basic open question with packaging questions
|
|
874
|
+
return injectPackagingQuestions({
|
|
834
875
|
required: [],
|
|
835
876
|
basic: [],
|
|
836
877
|
advanced: [],
|
|
@@ -838,7 +879,7 @@ ${resourceDetails}`;
|
|
|
838
879
|
question: "Is there anything else about your requirements or constraints that would help us provide better recommendations?",
|
|
839
880
|
placeholder: "e.g., specific security requirements, performance needs, existing infrastructure constraints..."
|
|
840
881
|
}
|
|
841
|
-
};
|
|
882
|
+
});
|
|
842
883
|
}
|
|
843
884
|
}
|
|
844
885
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-manifests.d.ts","sourceRoot":"","sources":["../../src/tools/generate-manifests.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"generate-manifests.d.ts","sourceRoot":"","sources":["../../src/tools/generate-manifests.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,OAAO,EAAE,KAAK,EAA2B,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAyBhD,eAAO,MAAM,2BAA2B,sBAAsB,CAAC;AAC/D,eAAO,MAAM,kCAAkC,+IAA+I,CAAC;AAG/L,eAAO,MAAM,mCAAmC;;;CAG/C,CAAC;AAstBF;;GAEG;AACH,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,EACrD,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,CAoRxD"}
|
|
@@ -40,6 +40,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
40
40
|
exports.GENERATEMANIFESTS_TOOL_INPUT_SCHEMA = exports.GENERATEMANIFESTS_TOOL_DESCRIPTION = exports.GENERATEMANIFESTS_TOOL_NAME = void 0;
|
|
41
41
|
exports.handleGenerateManifestsTool = handleGenerateManifestsTool;
|
|
42
42
|
const zod_1 = require("zod");
|
|
43
|
+
const child_process_1 = require("child_process");
|
|
44
|
+
const util_1 = require("util");
|
|
43
45
|
const error_handling_1 = require("../core/error-handling");
|
|
44
46
|
const index_1 = require("../core/index");
|
|
45
47
|
const cluster_utils_1 = require("../core/cluster-utils");
|
|
@@ -54,6 +56,8 @@ const platform_utils_1 = require("../core/platform-utils");
|
|
|
54
56
|
const crd_availability_1 = require("../core/crd-availability");
|
|
55
57
|
const solution_cr_1 = require("../core/solution-cr");
|
|
56
58
|
const helm_utils_1 = require("../core/helm-utils");
|
|
59
|
+
const packaging_1 = require("../core/packaging");
|
|
60
|
+
const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
|
|
57
61
|
// Tool metadata for direct MCP registration
|
|
58
62
|
exports.GENERATEMANIFESTS_TOOL_NAME = 'generateManifests';
|
|
59
63
|
exports.GENERATEMANIFESTS_TOOL_DESCRIPTION = 'Generate final Kubernetes manifests from fully configured solution (ONLY after completing ALL stages: required, basic, advanced, and open)';
|
|
@@ -133,6 +137,48 @@ function validateYamlSyntax(yamlContent) {
|
|
|
133
137
|
};
|
|
134
138
|
}
|
|
135
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* Run helm lint on a chart directory
|
|
142
|
+
*/
|
|
143
|
+
async function helmLint(chartDir, logger) {
|
|
144
|
+
try {
|
|
145
|
+
// Use execFile with array arguments to prevent command injection
|
|
146
|
+
logger.debug('Running helm lint', { chartDir });
|
|
147
|
+
const { stdout, stderr } = await execFileAsync('helm', ['lint', chartDir]);
|
|
148
|
+
// Parse helm lint output for warnings
|
|
149
|
+
const warnings = [];
|
|
150
|
+
const lines = (stdout + stderr).split('\n');
|
|
151
|
+
for (const line of lines) {
|
|
152
|
+
if (line.includes('[WARNING]')) {
|
|
153
|
+
warnings.push(line.trim());
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
logger.debug('helm lint passed', { warnings: warnings.length });
|
|
157
|
+
return { valid: true, errors: [], warnings };
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
// helm lint exits with non-zero on errors
|
|
161
|
+
const errorOutput = error instanceof Error ? error.stderr || error.message : String(error);
|
|
162
|
+
const errors = [];
|
|
163
|
+
const warnings = [];
|
|
164
|
+
// Parse output for errors and warnings
|
|
165
|
+
const lines = errorOutput.split('\n');
|
|
166
|
+
for (const line of lines) {
|
|
167
|
+
if (line.includes('[ERROR]')) {
|
|
168
|
+
errors.push(line.trim());
|
|
169
|
+
}
|
|
170
|
+
else if (line.includes('[WARNING]')) {
|
|
171
|
+
warnings.push(line.trim());
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// If no specific errors found, use the full output
|
|
175
|
+
if (errors.length === 0) {
|
|
176
|
+
errors.push(errorOutput.trim());
|
|
177
|
+
}
|
|
178
|
+
logger.warn('helm lint failed', { errors, warnings });
|
|
179
|
+
return { valid: false, errors, warnings };
|
|
180
|
+
}
|
|
181
|
+
}
|
|
136
182
|
/**
|
|
137
183
|
* Validate manifests using multi-layer approach
|
|
138
184
|
*/
|
|
@@ -401,6 +447,160 @@ async function handleHelmGeneration(solution, solutionId, dotAI, logger, request
|
|
|
401
447
|
// All attempts failed
|
|
402
448
|
throw new Error(`Failed to generate valid Helm values after ${maxAttempts} attempts. Last errors: ${lastError?.validationResult.errors.join(', ')}`);
|
|
403
449
|
}
|
|
450
|
+
/**
|
|
451
|
+
* Render packaged output to raw YAML for validation
|
|
452
|
+
*/
|
|
453
|
+
async function renderPackageToYaml(packageDir, format, logger) {
|
|
454
|
+
try {
|
|
455
|
+
// Use execFile with array arguments to prevent command injection
|
|
456
|
+
const args = format === 'helm'
|
|
457
|
+
? ['template', 'test-release', packageDir]
|
|
458
|
+
: ['kustomize', packageDir];
|
|
459
|
+
const command = format === 'helm' ? 'helm' : 'kubectl';
|
|
460
|
+
logger.debug('Rendering package to YAML', { format, command, args });
|
|
461
|
+
const { stdout, stderr } = await execFileAsync(command, args);
|
|
462
|
+
if (stderr && !stdout) {
|
|
463
|
+
return { success: false, error: stderr };
|
|
464
|
+
}
|
|
465
|
+
return { success: true, yaml: stdout };
|
|
466
|
+
}
|
|
467
|
+
catch (error) {
|
|
468
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
469
|
+
// Check for terminal infrastructure errors that won't be fixed by AI retrying
|
|
470
|
+
const terminalErrorPatterns = [
|
|
471
|
+
'not found', // command not found
|
|
472
|
+
'command not found', // explicit command not found
|
|
473
|
+
'ENOENT', // file/command doesn't exist
|
|
474
|
+
'permission denied', // permission issues
|
|
475
|
+
'EACCES', // access denied
|
|
476
|
+
];
|
|
477
|
+
const isTerminalError = terminalErrorPatterns.some(pattern => errorMessage.toLowerCase().includes(pattern.toLowerCase()));
|
|
478
|
+
return {
|
|
479
|
+
success: false,
|
|
480
|
+
error: errorMessage,
|
|
481
|
+
isTerminalError // Signal to caller to not retry
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Write package files to a temporary directory
|
|
487
|
+
*/
|
|
488
|
+
function writePackageFiles(files, baseDir) {
|
|
489
|
+
const resolvedBase = path.resolve(baseDir);
|
|
490
|
+
for (const file of files) {
|
|
491
|
+
const filePath = path.join(baseDir, file.relativePath);
|
|
492
|
+
const resolvedPath = path.resolve(filePath);
|
|
493
|
+
// Prevent path traversal attacks
|
|
494
|
+
if (!resolvedPath.startsWith(resolvedBase)) {
|
|
495
|
+
throw new Error(`Invalid file path: ${file.relativePath} would escape base directory`);
|
|
496
|
+
}
|
|
497
|
+
const fileDir = path.dirname(filePath);
|
|
498
|
+
if (!fs.existsSync(fileDir)) {
|
|
499
|
+
fs.mkdirSync(fileDir, { recursive: true });
|
|
500
|
+
}
|
|
501
|
+
fs.writeFileSync(filePath, file.content, 'utf8');
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Package manifests and validate the output
|
|
506
|
+
*/
|
|
507
|
+
async function packageAndValidate(rawManifests, solution, outputFormat, outputPath, solutionId, dotAI, logger, interaction_id) {
|
|
508
|
+
const maxAttempts = 5;
|
|
509
|
+
let packagingError;
|
|
510
|
+
const tmpDir = path.join(process.cwd(), 'tmp');
|
|
511
|
+
const packageDir = path.join(tmpDir, `${solutionId}-${outputFormat}`);
|
|
512
|
+
// Helper to cleanup temp directory
|
|
513
|
+
const cleanupPackageDir = () => {
|
|
514
|
+
if (fs.existsSync(packageDir)) {
|
|
515
|
+
try {
|
|
516
|
+
fs.rmSync(packageDir, { recursive: true });
|
|
517
|
+
}
|
|
518
|
+
catch (cleanupError) {
|
|
519
|
+
logger.warn('Failed to cleanup temp package directory', { packageDir, error: cleanupError });
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
524
|
+
logger.info('Packaging attempt', { attempt, maxAttempts, format: outputFormat });
|
|
525
|
+
try {
|
|
526
|
+
const packagingResult = await (0, packaging_1.packageManifests)(rawManifests, solution, outputFormat, outputPath, dotAI, logger, packagingError, interaction_id);
|
|
527
|
+
// Write files to temp directory
|
|
528
|
+
if (fs.existsSync(packageDir)) {
|
|
529
|
+
fs.rmSync(packageDir, { recursive: true });
|
|
530
|
+
}
|
|
531
|
+
fs.mkdirSync(packageDir, { recursive: true });
|
|
532
|
+
writePackageFiles(packagingResult.files, packageDir);
|
|
533
|
+
// Run helm lint for Helm charts (catches structural issues before rendering)
|
|
534
|
+
if (outputFormat === 'helm') {
|
|
535
|
+
const lintResult = await helmLint(packageDir, logger);
|
|
536
|
+
if (!lintResult.valid) {
|
|
537
|
+
packagingError = {
|
|
538
|
+
attempt,
|
|
539
|
+
previousOutput: JSON.stringify(packagingResult.files.map(f => f.relativePath)),
|
|
540
|
+
validationError: `helm lint failed: ${lintResult.errors.join(', ')}`
|
|
541
|
+
};
|
|
542
|
+
logger.warn('helm lint failed', { attempt, errors: lintResult.errors });
|
|
543
|
+
continue;
|
|
544
|
+
}
|
|
545
|
+
// Log warnings but don't fail on them
|
|
546
|
+
if (lintResult.warnings.length > 0) {
|
|
547
|
+
logger.info('helm lint warnings', { warnings: lintResult.warnings });
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
// Render to raw YAML
|
|
551
|
+
const renderResult = await renderPackageToYaml(packageDir, outputFormat, logger);
|
|
552
|
+
if (!renderResult.success) {
|
|
553
|
+
// Check for terminal infrastructure errors - fail fast, don't retry
|
|
554
|
+
if (renderResult.isTerminalError) {
|
|
555
|
+
const terminalError = new Error(`Infrastructure error (not retryable): ${renderResult.error}`);
|
|
556
|
+
logger.error('Terminal infrastructure error - cannot retry', terminalError, {
|
|
557
|
+
format: outputFormat
|
|
558
|
+
});
|
|
559
|
+
throw terminalError;
|
|
560
|
+
}
|
|
561
|
+
packagingError = {
|
|
562
|
+
attempt,
|
|
563
|
+
previousOutput: JSON.stringify(packagingResult.files.map(f => f.relativePath)),
|
|
564
|
+
validationError: `Failed to render ${outputFormat}: ${renderResult.error}`
|
|
565
|
+
};
|
|
566
|
+
logger.warn('Package render failed', { attempt, error: renderResult.error });
|
|
567
|
+
continue;
|
|
568
|
+
}
|
|
569
|
+
// Validate rendered YAML
|
|
570
|
+
const renderedYamlPath = path.join(tmpDir, `${solutionId}-${outputFormat}-rendered.yaml`);
|
|
571
|
+
if (!renderResult.yaml) {
|
|
572
|
+
throw new Error('Render succeeded but no YAML content returned');
|
|
573
|
+
}
|
|
574
|
+
fs.writeFileSync(renderedYamlPath, renderResult.yaml, 'utf8');
|
|
575
|
+
const validation = await validateManifests(renderedYamlPath);
|
|
576
|
+
if (validation.valid) {
|
|
577
|
+
logger.info('Package validation successful', { format: outputFormat, attempt });
|
|
578
|
+
cleanupPackageDir();
|
|
579
|
+
return { files: packagingResult.files, attempts: attempt };
|
|
580
|
+
}
|
|
581
|
+
packagingError = {
|
|
582
|
+
attempt,
|
|
583
|
+
previousOutput: JSON.stringify(packagingResult.files.map(f => f.relativePath)),
|
|
584
|
+
validationError: validation.errors.join(', ')
|
|
585
|
+
};
|
|
586
|
+
logger.warn('Package validation failed', { attempt, errors: validation.errors });
|
|
587
|
+
}
|
|
588
|
+
catch (error) {
|
|
589
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
590
|
+
logger.error('Packaging attempt failed', error);
|
|
591
|
+
if (attempt === maxAttempts) {
|
|
592
|
+
throw error;
|
|
593
|
+
}
|
|
594
|
+
packagingError = {
|
|
595
|
+
attempt,
|
|
596
|
+
previousOutput: packagingError?.previousOutput || '',
|
|
597
|
+
validationError: errorMessage
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
cleanupPackageDir();
|
|
602
|
+
throw new Error(`Failed to generate valid ${outputFormat} package after ${maxAttempts} attempts. Last error: ${packagingError?.validationError}`);
|
|
603
|
+
}
|
|
404
604
|
/**
|
|
405
605
|
* Direct MCP tool handler for generateManifests functionality
|
|
406
606
|
*/
|
|
@@ -524,17 +724,46 @@ async function handleGenerateManifestsTool(args, dotAI, logger, requestId) {
|
|
|
524
724
|
yamlPath,
|
|
525
725
|
requestId
|
|
526
726
|
});
|
|
527
|
-
//
|
|
528
|
-
|
|
727
|
+
// Extract packaging options from user answers (with defaults)
|
|
728
|
+
const outputFormat = (userAnswers.outputFormat || 'raw');
|
|
729
|
+
const outputPath = userAnswers.outputPath || './manifests';
|
|
529
730
|
const feedbackMessage = (0, index_1.maybeGetFeedbackMessage)();
|
|
731
|
+
// Handle packaging based on outputFormat
|
|
732
|
+
if (outputFormat === 'helm' || outputFormat === 'kustomize') {
|
|
733
|
+
const packagingResult = await packageAndValidate(manifests, solution, outputFormat, outputPath, args.solutionId, dotAI, logger, args.interaction_id);
|
|
734
|
+
const response = {
|
|
735
|
+
success: true,
|
|
736
|
+
status: 'manifests_generated',
|
|
737
|
+
solutionId: args.solutionId,
|
|
738
|
+
outputFormat,
|
|
739
|
+
outputPath,
|
|
740
|
+
files: packagingResult.files,
|
|
741
|
+
validationAttempts: attempt,
|
|
742
|
+
packagingAttempts: packagingResult.attempts,
|
|
743
|
+
timestamp: new Date().toISOString(),
|
|
744
|
+
agentInstructions: `Write the files to "${outputPath}". The output is a ${outputFormat === 'helm' ? 'Helm chart' : 'Kustomize overlay'}. If immediate deployment is desired, call the recommend tool with stage: "deployManifests".`,
|
|
745
|
+
...(feedbackMessage ? { message: feedbackMessage } : {})
|
|
746
|
+
};
|
|
747
|
+
return {
|
|
748
|
+
content: [{
|
|
749
|
+
type: 'text',
|
|
750
|
+
text: JSON.stringify(response, null, 2)
|
|
751
|
+
}]
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
// Raw format - return manifests as-is
|
|
530
755
|
const response = {
|
|
531
756
|
success: true,
|
|
532
757
|
status: 'manifests_generated',
|
|
533
758
|
solutionId: args.solutionId,
|
|
534
|
-
|
|
535
|
-
|
|
759
|
+
outputFormat,
|
|
760
|
+
outputPath,
|
|
761
|
+
files: [
|
|
762
|
+
{ relativePath: 'manifests.yaml', content: manifests }
|
|
763
|
+
],
|
|
536
764
|
validationAttempts: attempt,
|
|
537
765
|
timestamp: new Date().toISOString(),
|
|
766
|
+
agentInstructions: `Write the files to "${outputPath}". If immediate deployment is desired, call the recommend tool with stage: "deployManifests".`,
|
|
538
767
|
...(feedbackMessage ? { message: feedbackMessage } : {})
|
|
539
768
|
};
|
|
540
769
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vfarcic/dot-ai",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.157.0",
|
|
4
4
|
"description": "AI-powered development productivity platform that enhances software development workflows through intelligent automation and AI-driven assistance",
|
|
5
5
|
"mcpName": "io.github.vfarcic/dot-ai",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -84,7 +84,7 @@ Respond with ONLY a JSON object in this exact format:
|
|
|
84
84
|
}
|
|
85
85
|
],
|
|
86
86
|
"overallAssessment": {
|
|
87
|
-
"enhancementPotential": "HIGH|MEDIUM|LOW",
|
|
87
|
+
"enhancementPotential": "<ENUM: HIGH | MEDIUM | LOW>",
|
|
88
88
|
"primaryGaps": ["Most important missing context area 1", "Most important missing context area 2"],
|
|
89
89
|
"recommendedFocus": "The single most valuable clarification opportunity"
|
|
90
90
|
},
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# {{output_format}} Packaging
|
|
2
|
+
|
|
3
|
+
Convert validated Kubernetes manifests into {{output_format_description}}.
|
|
4
|
+
|
|
5
|
+
## User Intent
|
|
6
|
+
{{intent}}
|
|
7
|
+
|
|
8
|
+
## Solution Description
|
|
9
|
+
{{solution_description}}
|
|
10
|
+
|
|
11
|
+
## Raw Kubernetes Manifests (Validated)
|
|
12
|
+
```yaml
|
|
13
|
+
{{raw_manifests}}
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## User Configuration (Questions and Answers)
|
|
17
|
+
{{questions_and_answers}}
|
|
18
|
+
|
|
19
|
+
## Output Path
|
|
20
|
+
{{output_path}}
|
|
21
|
+
|
|
22
|
+
## Instructions
|
|
23
|
+
|
|
24
|
+
Transform the raw Kubernetes manifests into {{output_format_description}}.
|
|
25
|
+
|
|
26
|
+
1. **Analyze Context**: Review the user intent, solution description, and the questions/answers to understand what the user is trying to achieve.
|
|
27
|
+
|
|
28
|
+
2. **Externalize Configuration**: Make values that users might want to change across deployments or environments configurable. Use your judgment based on the context - the questions asked indicate what the user cares about customizing.
|
|
29
|
+
|
|
30
|
+
3. **Convert Manifests**: Transform raw manifests into the appropriate format with references to externalized configuration.
|
|
31
|
+
|
|
32
|
+
4. **Generate Metadata**: Create required metadata files for the package.
|
|
33
|
+
|
|
34
|
+
{{format_specific_instructions}}
|
|
35
|
+
|
|
36
|
+
## Response Format
|
|
37
|
+
|
|
38
|
+
Return a JSON object with exactly this structure:
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"files": [
|
|
43
|
+
{
|
|
44
|
+
"relativePath": "path/to/file.yaml",
|
|
45
|
+
"content": "file content as string"
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**JSON Schema:**
|
|
52
|
+
- `files`: array (required) - List of files to generate
|
|
53
|
+
- `relativePath`: string (required) - File path relative to output directory (e.g., "Chart.yaml", "templates/deployment.yaml")
|
|
54
|
+
- `content`: string (required) - Complete file content
|
|
55
|
+
|
|
56
|
+
{{format_example}}
|
|
57
|
+
|
|
58
|
+
## Previous Attempt (if retry)
|
|
59
|
+
{{previous_attempt}}
|
|
60
|
+
|
|
61
|
+
## Validation Error Details (if retry)
|
|
62
|
+
{{error_details}}
|
|
63
|
+
|
|
64
|
+
If this is a retry, analyze the validation error and fix the specific issue while preserving working parts.
|
|
65
|
+
|
|
66
|
+
**CRITICAL**: Return ONLY the JSON object. NO markdown code blocks, NO explanations, NO additional text before or after the JSON.
|
|
@@ -134,6 +134,8 @@ When multiple resources need the same information, create a single question with
|
|
|
134
134
|
|
|
135
135
|
## Response Format
|
|
136
136
|
|
|
137
|
+
**CRITICAL**: Every question object MUST include a `suggestedAnswer` field - this is required, not optional.
|
|
138
|
+
|
|
137
139
|
Return your response as JSON in this exact format:
|
|
138
140
|
|
|
139
141
|
```json
|
package/assets/images/logo.png
DELETED
|
Binary file
|