@vfarcic/dot-ai 0.5.1 → 0.6.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 (146) hide show
  1. package/dist/cli.d.ts +3 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/{src/cli.ts → dist/cli.js} +19 -26
  4. package/dist/core/claude.d.ts +42 -0
  5. package/dist/core/claude.d.ts.map +1 -0
  6. package/dist/core/claude.js +229 -0
  7. package/dist/core/deploy-operation.d.ts +38 -0
  8. package/dist/core/deploy-operation.d.ts.map +1 -0
  9. package/dist/core/deploy-operation.js +101 -0
  10. package/dist/core/discovery.d.ts +162 -0
  11. package/dist/core/discovery.d.ts.map +1 -0
  12. package/dist/core/discovery.js +758 -0
  13. package/dist/core/error-handling.d.ts +167 -0
  14. package/dist/core/error-handling.d.ts.map +1 -0
  15. package/dist/core/error-handling.js +399 -0
  16. package/dist/core/index.d.ts +42 -0
  17. package/dist/core/index.d.ts.map +1 -0
  18. package/dist/core/index.js +123 -0
  19. package/dist/core/kubernetes-utils.d.ts +38 -0
  20. package/dist/core/kubernetes-utils.d.ts.map +1 -0
  21. package/dist/core/kubernetes-utils.js +177 -0
  22. package/dist/core/memory.d.ts +45 -0
  23. package/dist/core/memory.d.ts.map +1 -0
  24. package/dist/core/memory.js +113 -0
  25. package/dist/core/schema.d.ts +187 -0
  26. package/dist/core/schema.d.ts.map +1 -0
  27. package/dist/core/schema.js +655 -0
  28. package/dist/core/session-utils.d.ts +29 -0
  29. package/dist/core/session-utils.d.ts.map +1 -0
  30. package/dist/core/session-utils.js +121 -0
  31. package/dist/core/workflow.d.ts +70 -0
  32. package/dist/core/workflow.d.ts.map +1 -0
  33. package/dist/core/workflow.js +161 -0
  34. package/dist/index.d.ts +15 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +32 -0
  37. package/dist/interfaces/cli.d.ts +74 -0
  38. package/dist/interfaces/cli.d.ts.map +1 -0
  39. package/dist/interfaces/cli.js +769 -0
  40. package/dist/interfaces/mcp.d.ts +30 -0
  41. package/dist/interfaces/mcp.d.ts.map +1 -0
  42. package/dist/interfaces/mcp.js +105 -0
  43. package/dist/mcp/server.d.ts +9 -0
  44. package/dist/mcp/server.d.ts.map +1 -0
  45. package/dist/mcp/server.js +151 -0
  46. package/dist/tools/answer-question.d.ts +27 -0
  47. package/dist/tools/answer-question.d.ts.map +1 -0
  48. package/dist/tools/answer-question.js +696 -0
  49. package/dist/tools/choose-solution.d.ts +23 -0
  50. package/dist/tools/choose-solution.d.ts.map +1 -0
  51. package/dist/tools/choose-solution.js +171 -0
  52. package/dist/tools/deploy-manifests.d.ts +25 -0
  53. package/dist/tools/deploy-manifests.d.ts.map +1 -0
  54. package/dist/tools/deploy-manifests.js +74 -0
  55. package/dist/tools/generate-manifests.d.ts +23 -0
  56. package/dist/tools/generate-manifests.d.ts.map +1 -0
  57. package/dist/tools/generate-manifests.js +424 -0
  58. package/dist/tools/index.d.ts +11 -0
  59. package/dist/tools/index.d.ts.map +1 -0
  60. package/dist/tools/index.js +34 -0
  61. package/dist/tools/recommend.d.ts +23 -0
  62. package/dist/tools/recommend.d.ts.map +1 -0
  63. package/dist/tools/recommend.js +332 -0
  64. package/package.json +124 -2
  65. package/.claude/commands/context-load.md +0 -11
  66. package/.claude/commands/context-save.md +0 -16
  67. package/.claude/commands/prd-done.md +0 -115
  68. package/.claude/commands/prd-get.md +0 -25
  69. package/.claude/commands/prd-start.md +0 -87
  70. package/.claude/commands/task-done.md +0 -77
  71. package/.claude/commands/tests-reminder.md +0 -32
  72. package/.claude/settings.local.json +0 -20
  73. package/.eslintrc.json +0 -25
  74. package/.github/workflows/ci.yml +0 -170
  75. package/.prettierrc.json +0 -10
  76. package/.teller.yml +0 -8
  77. package/CLAUDE.md +0 -162
  78. package/assets/images/logo.png +0 -0
  79. package/bin/dot-ai.ts +0 -47
  80. package/bin.js +0 -19
  81. package/destroy.sh +0 -45
  82. package/devbox.json +0 -13
  83. package/devbox.lock +0 -225
  84. package/docs/API.md +0 -449
  85. package/docs/CONTEXT.md +0 -49
  86. package/docs/DEVELOPMENT.md +0 -203
  87. package/docs/NEXT_STEPS.md +0 -97
  88. package/docs/STAGE_BASED_API.md +0 -97
  89. package/docs/cli-guide.md +0 -798
  90. package/docs/design.md +0 -750
  91. package/docs/discovery-engine.md +0 -515
  92. package/docs/error-handling.md +0 -429
  93. package/docs/function-registration.md +0 -157
  94. package/docs/mcp-guide.md +0 -416
  95. package/renovate.json +0 -51
  96. package/setup.sh +0 -111
  97. package/src/core/claude.ts +0 -280
  98. package/src/core/deploy-operation.ts +0 -127
  99. package/src/core/discovery.ts +0 -900
  100. package/src/core/error-handling.ts +0 -562
  101. package/src/core/index.ts +0 -143
  102. package/src/core/kubernetes-utils.ts +0 -218
  103. package/src/core/memory.ts +0 -148
  104. package/src/core/schema.ts +0 -830
  105. package/src/core/session-utils.ts +0 -97
  106. package/src/core/workflow.ts +0 -234
  107. package/src/index.ts +0 -18
  108. package/src/interfaces/cli.ts +0 -872
  109. package/src/interfaces/mcp.ts +0 -183
  110. package/src/mcp/server.ts +0 -131
  111. package/src/tools/answer-question.ts +0 -807
  112. package/src/tools/choose-solution.ts +0 -169
  113. package/src/tools/deploy-manifests.ts +0 -94
  114. package/src/tools/generate-manifests.ts +0 -502
  115. package/src/tools/index.ts +0 -41
  116. package/src/tools/recommend.ts +0 -370
  117. package/tests/__mocks__/@kubernetes/client-node.ts +0 -106
  118. package/tests/build-system.test.ts +0 -345
  119. package/tests/configuration.test.ts +0 -226
  120. package/tests/core/deploy-operation.test.ts +0 -38
  121. package/tests/core/discovery.test.ts +0 -1648
  122. package/tests/core/error-handling.test.ts +0 -632
  123. package/tests/core/schema.test.ts +0 -1658
  124. package/tests/core/session-utils.test.ts +0 -245
  125. package/tests/core.test.ts +0 -439
  126. package/tests/fixtures/configmap-no-labels.yaml +0 -8
  127. package/tests/fixtures/crossplane-app-configuration.yaml +0 -6
  128. package/tests/fixtures/crossplane-providers.yaml +0 -45
  129. package/tests/fixtures/crossplane-rbac.yaml +0 -48
  130. package/tests/fixtures/invalid-configmap.yaml +0 -8
  131. package/tests/fixtures/invalid-deployment.yaml +0 -17
  132. package/tests/fixtures/test-deployment.yaml +0 -28
  133. package/tests/fixtures/valid-configmap.yaml +0 -15
  134. package/tests/infrastructure.test.ts +0 -426
  135. package/tests/interfaces/cli.test.ts +0 -1036
  136. package/tests/interfaces/mcp.test.ts +0 -139
  137. package/tests/kubernetes-utils.test.ts +0 -200
  138. package/tests/mcp/server.test.ts +0 -126
  139. package/tests/setup.ts +0 -31
  140. package/tests/tools/answer-question.test.ts +0 -367
  141. package/tests/tools/choose-solution.test.ts +0 -481
  142. package/tests/tools/deploy-manifests.test.ts +0 -185
  143. package/tests/tools/generate-manifests.test.ts +0 -441
  144. package/tests/tools/index.test.ts +0 -111
  145. package/tests/tools/recommend.test.ts +0 -180
  146. package/tsconfig.json +0 -34
@@ -1,502 +0,0 @@
1
- /**
2
- * Generate Manifests Tool - AI-driven manifest generation with validation loop
3
- */
4
-
5
- import { z } from 'zod';
6
- import { ErrorHandler, ErrorCategory, ErrorSeverity } from '../core/error-handling';
7
- import { ClaudeIntegration } from '../core/claude';
8
- import { DotAI } from '../core/index';
9
- import { Logger } from '../core/error-handling';
10
- import * as fs from 'fs';
11
- import * as path from 'path';
12
- import * as yaml from 'js-yaml';
13
- import { spawn } from 'child_process';
14
- import { getAndValidateSessionDirectory } from '../core/session-utils';
15
-
16
- // Tool metadata for direct MCP registration
17
- export const GENERATEMANIFESTS_TOOL_NAME = 'generateManifests';
18
- export const GENERATEMANIFESTS_TOOL_DESCRIPTION = 'Generate final Kubernetes manifests from fully configured solution (ONLY after completing ALL stages: required, basic, advanced, and open)';
19
-
20
- // Zod schema for MCP registration
21
- export const GENERATEMANIFESTS_TOOL_INPUT_SCHEMA = {
22
- solutionId: z.string().regex(/^sol_[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{6}_[a-f0-9]+$/).describe('The solution ID to generate manifests for (e.g., sol_2025-07-01T154349_1e1e242592ff)')
23
- };
24
-
25
-
26
- interface ValidationResult {
27
- success: boolean;
28
- yamlSyntaxValid: boolean;
29
- kubectlOutput?: string;
30
- exitCode?: number;
31
- stderr?: string;
32
- stdout?: string;
33
- error?: string;
34
- }
35
-
36
- interface ErrorContext {
37
- attempt: number;
38
- previousManifests: string;
39
- yamlSyntaxValid: boolean;
40
- kubectlOutput?: string;
41
- exitCode?: number;
42
- stderr?: string;
43
- stdout?: string;
44
- }
45
-
46
-
47
-
48
- /**
49
- * Load solution file and validate structure
50
- */
51
- function loadSolutionFile(solutionId: string, sessionDir: string): any {
52
- const solutionPath = path.join(sessionDir, `${solutionId}.json`);
53
-
54
- if (!fs.existsSync(solutionPath)) {
55
- throw new Error(`Solution file not found: ${solutionPath}. Available files: ${fs.readdirSync(sessionDir).filter(f => f.endsWith('.json')).join(', ')}`);
56
- }
57
-
58
- try {
59
- const content = fs.readFileSync(solutionPath, 'utf8');
60
- const solution = JSON.parse(content);
61
-
62
- if (!solution.solutionId || !solution.questions) {
63
- throw new Error(`Invalid solution file structure: ${solutionId}. Missing required fields: solutionId or questions`);
64
- }
65
-
66
- return solution;
67
- } catch (error) {
68
- if (error instanceof SyntaxError) {
69
- throw new Error(`Invalid JSON in solution file: ${solutionId}`);
70
- }
71
- throw error;
72
- }
73
- }
74
-
75
-
76
- /**
77
- * Retrieve schemas for resources specified in the solution
78
- */
79
- async function retrieveResourceSchemas(solution: any, dotAI: DotAI, logger: Logger): Promise<any> {
80
- try {
81
- // Extract resource references from solution
82
- const resourceRefs = (solution.resources || []).map((resource: any) => ({
83
- kind: resource.kind,
84
- apiVersion: resource.apiVersion,
85
- group: resource.group
86
- }));
87
-
88
- if (resourceRefs.length === 0) {
89
- logger.warn('No resources found in solution for schema retrieval');
90
- return {};
91
- }
92
-
93
- logger.info('Retrieving schemas for solution resources', {
94
- resourceCount: resourceRefs.length,
95
- resources: resourceRefs.map((r: any) => `${r.kind}@${r.apiVersion}`)
96
- });
97
-
98
- const schemas: any = {};
99
-
100
- // Retrieve schema for each resource
101
- for (const resourceRef of resourceRefs) {
102
- try {
103
- const resourceKey = `${resourceRef.kind}.${resourceRef.apiVersion}`;
104
- logger.debug('Retrieving schema', { resourceKey });
105
-
106
- // Use discovery engine to explain the resource
107
- const explanation = await dotAI.discovery.explainResource(resourceRef.kind);
108
-
109
- schemas[resourceKey] = {
110
- kind: resourceRef.kind,
111
- apiVersion: resourceRef.apiVersion,
112
- schema: explanation,
113
- timestamp: new Date().toISOString()
114
- };
115
-
116
- logger.debug('Schema retrieved successfully', {
117
- resourceKey,
118
- schemaLength: explanation.length
119
- });
120
-
121
- } catch (error) {
122
- logger.error('Failed to retrieve schema for resource', error as Error, {
123
- resource: resourceRef
124
- });
125
-
126
- // Fail fast - if we can't get schemas, manifest generation will likely fail
127
- throw new Error(`Failed to retrieve schema for ${resourceRef.kind}: ${error instanceof Error ? error.message : String(error)}`);
128
- }
129
- }
130
-
131
- logger.info('All resource schemas retrieved successfully', {
132
- schemaCount: Object.keys(schemas).length
133
- });
134
-
135
- return schemas;
136
-
137
- } catch (error) {
138
- logger.error('Schema retrieval failed', error as Error);
139
- throw new Error(`Failed to retrieve resource schemas: ${error instanceof Error ? error.message : String(error)}`);
140
- }
141
- }
142
-
143
- /**
144
- * Validate YAML syntax
145
- */
146
- function validateYamlSyntax(yamlContent: string): { valid: boolean; error?: string } {
147
- try {
148
- yaml.loadAll(yamlContent);
149
- return { valid: true };
150
- } catch (error) {
151
- return {
152
- valid: false,
153
- error: error instanceof Error ? error.message : 'Unknown YAML syntax error'
154
- };
155
- }
156
- }
157
-
158
- /**
159
- * Run kubectl dry-run validation
160
- */
161
- async function runKubectlDryRun(yamlPath: string): Promise<ValidationResult> {
162
- return new Promise((resolve) => {
163
- const kubectl = spawn('kubectl', ['apply', '--dry-run=server', '-f', yamlPath], {
164
- stdio: ['ignore', 'pipe', 'pipe']
165
- });
166
-
167
- let stdout = '';
168
- let stderr = '';
169
-
170
- kubectl.stdout.on('data', (data) => {
171
- stdout += data.toString();
172
- });
173
-
174
- kubectl.stderr.on('data', (data) => {
175
- stderr += data.toString();
176
- });
177
-
178
- kubectl.on('close', (code) => {
179
- resolve({
180
- success: code === 0,
181
- yamlSyntaxValid: true, // If we get here, YAML was parseable
182
- kubectlOutput: stderr || stdout,
183
- exitCode: code || 0,
184
- stderr,
185
- stdout
186
- });
187
- });
188
-
189
- kubectl.on('error', (error) => {
190
- resolve({
191
- success: false,
192
- yamlSyntaxValid: true,
193
- error: `Failed to run kubectl: ${error.message}`,
194
- kubectlOutput: `kubectl command failed: ${error.message}`,
195
- exitCode: -1,
196
- stderr: error.message,
197
- stdout: ''
198
- });
199
- });
200
- });
201
- }
202
-
203
- /**
204
- * Validate manifests using multi-layer approach
205
- */
206
- async function validateManifests(yamlPath: string): Promise<ValidationResult> {
207
- // First check if file exists
208
- if (!fs.existsSync(yamlPath)) {
209
- return {
210
- success: false,
211
- yamlSyntaxValid: false,
212
- error: `Manifest file not found: ${yamlPath}`
213
- };
214
- }
215
-
216
- // Read YAML content
217
- const yamlContent = fs.readFileSync(yamlPath, 'utf8');
218
-
219
- // 1. YAML syntax validation
220
- const syntaxCheck = validateYamlSyntax(yamlContent);
221
- if (!syntaxCheck.valid) {
222
- return {
223
- success: false,
224
- yamlSyntaxValid: false,
225
- error: `YAML syntax error: ${syntaxCheck.error}`,
226
- kubectlOutput: `YAML parsing failed: ${syntaxCheck.error}`
227
- };
228
- }
229
-
230
- // 2. kubectl dry-run validation
231
- return await runKubectlDryRun(yamlPath);
232
- }
233
-
234
- /**
235
- * Generate manifests using AI with Claude integration
236
- */
237
- async function generateManifestsWithAI(
238
- solution: any,
239
- dotAI: DotAI,
240
- logger: Logger,
241
- errorContext?: ErrorContext
242
- ): Promise<string> {
243
-
244
- // Load prompt template
245
- const promptPath = path.join(process.cwd(), 'prompts', 'manifest-generation.md');
246
- const template = fs.readFileSync(promptPath, 'utf8');
247
-
248
- // Retrieve schemas for solution resources
249
- const resourceSchemas = await retrieveResourceSchemas(solution, dotAI, logger);
250
-
251
- // Prepare template variables
252
- const solutionData = JSON.stringify(solution, null, 2);
253
- const previousAttempt = errorContext ? `
254
- ### Generated Manifests:
255
- \`\`\`yaml
256
- ${errorContext.previousManifests}
257
- \`\`\`
258
- ` : 'None - this is the first attempt.';
259
-
260
- const errorDetails = errorContext ? `
261
- **Attempt**: ${errorContext.attempt}
262
- **YAML Syntax Valid**: ${errorContext.yamlSyntaxValid}
263
- **kubectl Output**: ${errorContext.kubectlOutput}
264
- **Exit Code**: ${errorContext.exitCode}
265
- **Error Details**: ${errorContext.stderr}
266
- ` : 'None - this is the first attempt.';
267
-
268
- // Replace template variables
269
- const schemasData = JSON.stringify(resourceSchemas, null, 2);
270
- const aiPrompt = template
271
- .replace('{solution}', solutionData)
272
- .replace('{schemas}', schemasData)
273
- .replace('{previous_attempt}', previousAttempt)
274
- .replace('{error_details}', errorDetails);
275
-
276
- const isRetry = !!errorContext;
277
- logger.info('Generating manifests with AI', {
278
- isRetry,
279
- attempt: errorContext?.attempt,
280
- hasErrorContext: !!errorContext,
281
- solutionId: solution.solutionId
282
- });
283
-
284
- // Initialize Claude integration
285
- const apiKey = process.env.ANTHROPIC_API_KEY || 'test-key';
286
- const claudeIntegration = new ClaudeIntegration(apiKey);
287
-
288
- // Send prompt to Claude
289
- const response = await claudeIntegration.sendMessage(aiPrompt);
290
-
291
- // Extract YAML content from response
292
- let manifestContent = response.content;
293
-
294
- // Try to extract YAML from code blocks if wrapped
295
- const yamlBlockMatch = manifestContent.match(/```(?:yaml|yml)?\s*([\s\S]*?)\s*```/);
296
- if (yamlBlockMatch) {
297
- manifestContent = yamlBlockMatch[1];
298
- }
299
-
300
- // Clean up any leading/trailing whitespace
301
- manifestContent = manifestContent.trim();
302
-
303
- logger.info('AI manifest generation completed', {
304
- manifestLength: manifestContent.length,
305
- isRetry,
306
- solutionId: solution.solutionId
307
- });
308
-
309
- return manifestContent;
310
- }
311
-
312
- /**
313
- * Direct MCP tool handler for generateManifests functionality
314
- */
315
- export async function handleGenerateManifestsTool(
316
- args: { solutionId: string },
317
- dotAI: DotAI,
318
- logger: Logger,
319
- requestId: string
320
- ): Promise<{ content: { type: 'text'; text: string }[] }> {
321
- return await ErrorHandler.withErrorHandling(
322
- async () => {
323
- const maxAttempts = 10;
324
-
325
- logger.debug('Handling generateManifests request', {
326
- requestId,
327
- solutionId: args?.solutionId
328
- });
329
-
330
- // Input validation is handled automatically by MCP SDK with Zod schema
331
- // args are already validated and typed when we reach this point
332
-
333
- // Get session directory from environment
334
- let sessionDir: string;
335
- try {
336
- sessionDir = getAndValidateSessionDirectory(args, true); // requireWrite=true for manifest generation
337
- logger.debug('Session directory resolved and validated', { sessionDir });
338
- } catch (error) {
339
- throw ErrorHandler.createError(
340
- ErrorCategory.VALIDATION,
341
- ErrorSeverity.HIGH,
342
- error instanceof Error ? error.message : 'Session directory validation failed',
343
- {
344
- operation: 'session_directory_validation',
345
- component: 'GenerateManifestsTool',
346
- requestId,
347
- suggestedActions: [
348
- 'Ensure session directory exists and is writable',
349
- 'Check directory permissions',
350
- 'Verify the directory path is correct',
351
- 'Verify DOT_AI_SESSION_DIR environment variable is correctly set'
352
- ]
353
- }
354
- );
355
- }
356
-
357
- // Load solution file
358
- let solution: any;
359
- try {
360
- solution = loadSolutionFile(args.solutionId, sessionDir);
361
- logger.debug('Solution file loaded successfully', {
362
- solutionId: args.solutionId,
363
- hasQuestions: !!solution.questions,
364
- primaryResources: solution.resources
365
- });
366
- } catch (error) {
367
- throw ErrorHandler.createError(
368
- ErrorCategory.STORAGE,
369
- ErrorSeverity.HIGH,
370
- error instanceof Error ? error.message : 'Failed to load solution file',
371
- {
372
- operation: 'solution_file_load',
373
- component: 'GenerateManifestsTool',
374
- requestId,
375
- input: { solutionId: args.solutionId, sessionDir },
376
- suggestedActions: [
377
- 'Check that the solution ID is correct',
378
- 'Verify the solution file exists in the session directory',
379
- 'Ensure the solution was fully configured with all stages complete',
380
- 'List available solution files in the session directory'
381
- ]
382
- }
383
- );
384
- }
385
-
386
- // Prepare file path for manifests
387
- const yamlPath = path.join(sessionDir, `${args.solutionId}.yaml`);
388
-
389
- // AI generation and validation loop
390
- let lastError: ErrorContext | undefined;
391
-
392
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
393
- logger.info('AI manifest generation attempt', {
394
- attempt,
395
- maxAttempts,
396
- isRetry: attempt > 1,
397
- requestId
398
- });
399
-
400
- try {
401
- // Generate manifests with AI
402
- const manifests = await generateManifestsWithAI(
403
- solution,
404
- dotAI,
405
- logger,
406
- lastError
407
- );
408
-
409
- // Save manifests to file
410
- fs.writeFileSync(yamlPath, manifests, 'utf8');
411
- logger.info('Manifests saved to file', { yamlPath, attempt, requestId });
412
-
413
- // Save a copy of this attempt for debugging
414
- const attemptPath = yamlPath.replace('.yaml', `_attempt_${attempt.toString().padStart(2, '0')}.yaml`);
415
- fs.writeFileSync(attemptPath, manifests, 'utf8');
416
- logger.info('Saved manifest attempt for debugging', {
417
- attempt,
418
- attemptPath,
419
- requestId
420
- });
421
-
422
- // Validate manifests
423
- const validation = await validateManifests(yamlPath);
424
-
425
- if (validation.success) {
426
- logger.info('Manifest validation successful', {
427
- attempt,
428
- yamlPath,
429
- requestId
430
- });
431
-
432
- // Success! Return the validated manifests
433
- const response = {
434
- success: true,
435
- status: 'manifests_generated',
436
- solutionId: args.solutionId,
437
- manifests: manifests,
438
- yamlPath: yamlPath,
439
- validationAttempts: attempt,
440
- timestamp: new Date().toISOString()
441
- };
442
-
443
- return {
444
- content: [{
445
- type: 'text' as const,
446
- text: JSON.stringify(response, null, 2)
447
- }]
448
- };
449
- }
450
-
451
- // Validation failed, prepare error context for next attempt
452
- lastError = {
453
- attempt,
454
- previousManifests: manifests,
455
- yamlSyntaxValid: validation.yamlSyntaxValid,
456
- kubectlOutput: validation.kubectlOutput,
457
- exitCode: validation.exitCode,
458
- stderr: validation.stderr,
459
- stdout: validation.stdout
460
- };
461
-
462
- logger.warn('Manifest validation failed', {
463
- attempt,
464
- maxAttempts,
465
- yamlSyntaxValid: validation.yamlSyntaxValid,
466
- kubectlOutput: validation.kubectlOutput,
467
- requestId
468
- });
469
-
470
- } catch (error) {
471
- logger.error('Error during manifest generation attempt', error as Error);
472
-
473
- // If this is the last attempt, throw the error
474
- if (attempt === maxAttempts) {
475
- throw error;
476
- }
477
-
478
- // Prepare error context for retry
479
- lastError = {
480
- attempt,
481
- previousManifests: lastError?.previousManifests || '',
482
- yamlSyntaxValid: false,
483
- kubectlOutput: error instanceof Error ? error.message : 'Unknown error',
484
- exitCode: -1,
485
- stderr: error instanceof Error ? error.message : 'Unknown error',
486
- stdout: ''
487
- };
488
- }
489
- }
490
-
491
- // If we reach here, all attempts failed
492
- throw new Error(`Failed to generate valid manifests after ${maxAttempts} attempts. Last error: ${lastError?.kubectlOutput}`);
493
- },
494
- {
495
- operation: 'generate_manifests',
496
- component: 'GenerateManifestsTool',
497
- requestId,
498
- input: args
499
- }
500
- );
501
- }
502
-
@@ -1,41 +0,0 @@
1
- /**
2
- * Tool Exports Index
3
- *
4
- * Centralized exports for all available tools (direct handlers)
5
- */
6
-
7
- // Export direct tool handlers for use in MCP server and CLI
8
- export {
9
- RECOMMEND_TOOL_NAME,
10
- RECOMMEND_TOOL_DESCRIPTION,
11
- RECOMMEND_TOOL_INPUT_SCHEMA,
12
- handleRecommendTool
13
- } from './recommend';
14
-
15
- export {
16
- CHOOSESOLUTION_TOOL_NAME,
17
- CHOOSESOLUTION_TOOL_DESCRIPTION,
18
- CHOOSESOLUTION_TOOL_INPUT_SCHEMA,
19
- handleChooseSolutionTool
20
- } from './choose-solution';
21
-
22
- export {
23
- ANSWERQUESTION_TOOL_NAME,
24
- ANSWERQUESTION_TOOL_DESCRIPTION,
25
- ANSWERQUESTION_TOOL_INPUT_SCHEMA,
26
- handleAnswerQuestionTool
27
- } from './answer-question';
28
-
29
- export {
30
- GENERATEMANIFESTS_TOOL_NAME,
31
- GENERATEMANIFESTS_TOOL_DESCRIPTION,
32
- GENERATEMANIFESTS_TOOL_INPUT_SCHEMA,
33
- handleGenerateManifestsTool
34
- } from './generate-manifests';
35
-
36
- export {
37
- DEPLOYMANIFESTS_TOOL_NAME,
38
- DEPLOYMANIFESTS_TOOL_DESCRIPTION,
39
- DEPLOYMANIFESTS_TOOL_INPUT_SCHEMA,
40
- handleDeployManifestsTool
41
- } from './deploy-manifests';