UNPKG

@vfarcic/dot-ai

Version:

Universal Kubernetes application deployment agent with CLI and MCP interfaces

230 lines (229 loc) 8.32 kB
"use strict"; /** * Claude Integration Module * * Handles AI communication, YAML generation, and learning integration */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ClaudeIntegration = void 0; const sdk_1 = __importDefault(require("@anthropic-ai/sdk")); class ClaudeIntegration { client = null; apiKey; conversationHistory = []; interactions = []; constructor(apiKey) { this.apiKey = apiKey; this.validateApiKey(); if (this.apiKey) { this.client = new sdk_1.default({ apiKey: this.apiKey, }); } } validateApiKey() { // Allow test-friendly initialization if (this.apiKey === 'test-key' || this.apiKey === 'mock-key') { return; // Allow test keys } if (!this.apiKey) { throw new Error('API key is required for Claude integration'); } if (this.apiKey.length === 0) { throw new Error('Invalid API key: API key cannot be empty'); } } async sendMessage(message) { if (!this.client) { throw new Error('Claude client not initialized due to missing API key'); } if (this.apiKey === 'invalid-key') { throw new Error('Authentication failed: Invalid API key'); } try { // Add message to conversation history this.conversationHistory.push({ role: 'user', content: message }); // Use real Claude API if we have a real API key, otherwise fall back to mocks if (this.apiKey.startsWith('sk-ant-') && this.client) { // Make real API call to Claude const completion = await this.client.messages.create({ model: 'claude-3-5-sonnet-20241022', max_tokens: 4000, messages: [{ role: 'user', content: message }] }); const content = completion.content[0].type === 'text' ? completion.content[0].text : ''; const response = { content, usage: { input_tokens: completion.usage.input_tokens, output_tokens: completion.usage.output_tokens } }; this.conversationHistory.push({ role: 'assistant', content: response.content }); return response; } // For testing purposes, return mock responses if (message.toLowerCase().includes('deploy a web application')) { const response = { content: 'I can help you deploy a web application to Kubernetes. Let me guide you through the process of creating the necessary YAML manifests for your deployment.', usage: { input_tokens: 10, output_tokens: 25 } }; this.conversationHistory.push({ role: 'assistant', content: response.content }); return response; } if (message.toLowerCase().includes('recommended resources') && this.conversationHistory.some(msg => msg.content.toLowerCase().includes('nginx'))) { const response = { content: 'For nginx deployment, I recommend starting with 2 replicas, 500m CPU and 512Mi memory per pod. You can adjust these based on your traffic patterns.', usage: { input_tokens: 8, output_tokens: 30 } }; this.conversationHistory.push({ role: 'assistant', content: response.content }); return response; } // Default mock response const response = { content: 'I understand you want help with Kubernetes deployment. Could you provide more specific details about what you\'d like to deploy?', usage: { input_tokens: message.length / 4, output_tokens: 20 } }; this.conversationHistory.push({ role: 'assistant', content: response.content }); return response; } catch (error) { throw new Error(`Claude API error: ${error}`); } } async generateYAML(resourceType, config) { if (!this.client) { throw new Error('Claude client not initialized'); } // Mock YAML generation for testing if (resourceType === 'deployment' && config.app === 'nginx') { return { yaml: `apiVersion: apps/v1 kind: Deployment metadata: name: ${config.app} labels: app: ${config.app} spec: replicas: ${config.replicas || 1} selector: matchLabels: app: ${config.app} template: metadata: labels: app: ${config.app} spec: containers: - name: ${config.app} image: ${config.image} ports: - containerPort: 80`, explanation: `This deployment creates ${config.replicas || 1} replica(s) of ${config.app} using the ${config.image} image. The container exposes port 80 for web traffic.` }; } // Default YAML response return { yaml: `apiVersion: apps/v1 kind: ${resourceType.charAt(0).toUpperCase() + resourceType.slice(1)} metadata: name: example-${resourceType} spec: # Generated configuration would go here`, explanation: `This is a basic ${resourceType} manifest. You should customize it based on your specific requirements.` }; } async recordInteraction(interaction) { const recordedInteraction = { ...interaction, timestamp: new Date() }; this.interactions.push(recordedInteraction); } async getSuccessfulPatterns() { return this.interactions.filter(interaction => interaction.success); } getConversationHistory() { return [...this.conversationHistory]; } clearConversationHistory() { this.conversationHistory = []; } async generateManifest(spec) { if (!this.client) { throw new Error('Claude client not initialized'); } // Simulate manifest generation const yamlContent = ` apiVersion: apps/v1 kind: Deployment metadata: name: ${spec.name || 'app'} spec: replicas: ${spec.replicas || 1} selector: matchLabels: app: ${spec.name || 'app'} template: metadata: labels: app: ${spec.name || 'app'} spec: containers: - name: app image: ${spec.image || 'nginx:latest'} ports: - containerPort: 80 `; return yamlContent.trim(); } async analyzeError(error, _context) { if (!this.client) { throw new Error('Claude client not initialized'); } // Simulate error analysis return `Error analysis: ${error}. Suggested fix: Check the configuration and try again.`; } async suggestImprovements(_manifest) { if (!this.client) { throw new Error('Claude client not initialized'); } // Simulate improvement suggestions return [ 'Add resource limits and requests', 'Consider adding health checks', 'Add labels for better organization' ]; } async processUserInput(input, context) { if (!this.client) { throw new Error('Claude client not initialized'); } // Simulate interactive workflow processing if (input.toLowerCase().includes('deploy') && context?.interactive) { return { phase: 'Planning', questions: ['What type of database do you need?'] }; } if (context?.responses) { return { phase: 'Validation', nextSteps: ['Review generated manifest'] }; } // Default response return { phase: 'Discovery', suggestions: ['Start by exploring your cluster resources'] }; } isInitialized() { return this.client !== null; } } exports.ClaudeIntegration = ClaudeIntegration;