@vfarcic/dot-ai 0.138.0 → 0.140.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/dist/core/capability-scan-workflow.d.ts.map +1 -1
  2. package/dist/core/capability-scan-workflow.js +3 -2
  3. package/dist/core/command-executor.d.ts +39 -0
  4. package/dist/core/command-executor.d.ts.map +1 -0
  5. package/dist/core/command-executor.js +111 -0
  6. package/dist/core/deploy-operation.d.ts.map +1 -1
  7. package/dist/core/deploy-operation.js +3 -5
  8. package/dist/core/pattern-vector-service.d.ts +1 -1
  9. package/dist/core/pattern-vector-service.d.ts.map +1 -1
  10. package/dist/core/pattern-vector-service.js +2 -2
  11. package/dist/core/schema.js +1 -1
  12. package/dist/interfaces/mcp.d.ts.map +1 -1
  13. package/dist/interfaces/mcp.js +9 -1
  14. package/dist/tools/answer-question.d.ts.map +1 -1
  15. package/dist/tools/answer-question.js +27 -142
  16. package/dist/tools/choose-solution.d.ts.map +1 -1
  17. package/dist/tools/choose-solution.js +22 -85
  18. package/dist/tools/deploy-manifests.js +1 -1
  19. package/dist/tools/generate-manifests.d.ts.map +1 -1
  20. package/dist/tools/generate-manifests.js +33 -71
  21. package/dist/tools/operate-analysis.d.ts +15 -0
  22. package/dist/tools/operate-analysis.d.ts.map +1 -0
  23. package/dist/tools/operate-analysis.js +238 -0
  24. package/dist/tools/operate-execution.d.ts +18 -0
  25. package/dist/tools/operate-execution.d.ts.map +1 -0
  26. package/dist/tools/operate-execution.js +122 -0
  27. package/dist/tools/operate.d.ts +133 -0
  28. package/dist/tools/operate.d.ts.map +1 -0
  29. package/dist/tools/operate.js +237 -0
  30. package/dist/tools/recommend.d.ts +23 -1
  31. package/dist/tools/recommend.d.ts.map +1 -1
  32. package/dist/tools/recommend.js +14 -116
  33. package/dist/tools/remediate.d.ts +7 -4
  34. package/dist/tools/remediate.d.ts.map +1 -1
  35. package/dist/tools/remediate.js +38 -81
  36. package/dist/tools/version.js +1 -1
  37. package/package.json +1 -1
  38. package/prompts/operate-system.md +322 -0
  39. package/prompts/operate-user.md +25 -0
@@ -2,78 +2,20 @@
2
2
  /**
3
3
  * Choose Solution Tool - Select a solution and return its questions
4
4
  */
5
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
- if (k2 === undefined) k2 = k;
7
- var desc = Object.getOwnPropertyDescriptor(m, k);
8
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
- desc = { enumerable: true, get: function() { return m[k]; } };
10
- }
11
- Object.defineProperty(o, k2, desc);
12
- }) : (function(o, m, k, k2) {
13
- if (k2 === undefined) k2 = k;
14
- o[k2] = m[k];
15
- }));
16
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
- Object.defineProperty(o, "default", { enumerable: true, value: v });
18
- }) : function(o, v) {
19
- o["default"] = v;
20
- });
21
- var __importStar = (this && this.__importStar) || (function () {
22
- var ownKeys = function(o) {
23
- ownKeys = Object.getOwnPropertyNames || function (o) {
24
- var ar = [];
25
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
- return ar;
27
- };
28
- return ownKeys(o);
29
- };
30
- return function (mod) {
31
- if (mod && mod.__esModule) return mod;
32
- var result = {};
33
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
- __setModuleDefault(result, mod);
35
- return result;
36
- };
37
- })();
38
5
  Object.defineProperty(exports, "__esModule", { value: true });
39
6
  exports.CHOOSESOLUTION_TOOL_INPUT_SCHEMA = exports.CHOOSESOLUTION_TOOL_DESCRIPTION = exports.CHOOSESOLUTION_TOOL_NAME = void 0;
40
7
  exports.handleChooseSolutionTool = handleChooseSolutionTool;
41
8
  const zod_1 = require("zod");
42
9
  const error_handling_1 = require("../core/error-handling");
43
- const fs = __importStar(require("fs"));
44
- const path = __importStar(require("path"));
45
- const session_utils_1 = require("../core/session-utils");
10
+ const generic_session_manager_1 = require("../core/generic-session-manager");
46
11
  // Tool metadata for direct MCP registration
47
12
  exports.CHOOSESOLUTION_TOOL_NAME = 'chooseSolution';
48
13
  exports.CHOOSESOLUTION_TOOL_DESCRIPTION = 'Select a solution by ID and return its questions for configuration';
49
14
  // Zod schema for MCP registration
50
15
  exports.CHOOSESOLUTION_TOOL_INPUT_SCHEMA = {
51
- solutionId: zod_1.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 choose (e.g., sol_2025-07-01T154349_1e1e242592ff)')
16
+ solutionId: zod_1.z.string().regex(/^sol-\d+-[a-f0-9]{8}$/).describe('The solution ID to choose (e.g., sol-1762983784617-9ddae2b8)')
52
17
  };
53
- /**
54
- * Load solution file by ID
55
- */
56
- function loadSolutionFile(solutionId, sessionDir) {
57
- const solutionPath = path.join(sessionDir, `${solutionId}.json`);
58
- if (!fs.existsSync(solutionPath)) {
59
- throw new Error(`Solution file not found: ${solutionPath}. Available files: ${fs.readdirSync(sessionDir).filter(f => f.endsWith('.json')).join(', ')}`);
60
- }
61
- try {
62
- const content = fs.readFileSync(solutionPath, 'utf8');
63
- const solution = JSON.parse(content);
64
- // Validate solution structure
65
- if (!solution.solutionId || !solution.questions) {
66
- throw new Error(`Invalid solution file structure: ${solutionId}. Missing required fields: solutionId or questions`);
67
- }
68
- return solution;
69
- }
70
- catch (error) {
71
- if (error instanceof SyntaxError) {
72
- throw new Error(`Invalid JSON in solution file: ${solutionId}. ${error.message}`);
73
- }
74
- throw error;
75
- }
76
- }
18
+ // Session management now handled by GenericSessionManager
77
19
  /**
78
20
  * Direct MCP tool handler for chooseSolution functionality
79
21
  */
@@ -82,29 +24,26 @@ async function handleChooseSolutionTool(args, dotAI, logger, requestId) {
82
24
  logger.debug('Handling chooseSolution request', { requestId, solutionId: args?.solutionId });
83
25
  // Input validation is handled automatically by MCP SDK with Zod schema
84
26
  // args are already validated and typed when we reach this point
85
- // Get session directory from environment
86
- let sessionDir;
87
- try {
88
- sessionDir = (0, session_utils_1.getAndValidateSessionDirectory)(false); // requireWrite=false
89
- logger.debug('Session directory resolved and validated', { sessionDir });
90
- }
91
- catch (error) {
92
- throw error_handling_1.ErrorHandler.createError(error_handling_1.ErrorCategory.VALIDATION, error_handling_1.ErrorSeverity.HIGH, error instanceof Error ? error.message : 'Session directory validation failed', {
93
- operation: 'session_directory_validation',
27
+ // Initialize session manager
28
+ const sessionManager = new generic_session_manager_1.GenericSessionManager('sol');
29
+ logger.debug('Session manager initialized', { requestId });
30
+ // Load solution session
31
+ const session = sessionManager.getSession(args.solutionId);
32
+ if (!session) {
33
+ throw error_handling_1.ErrorHandler.createError(error_handling_1.ErrorCategory.VALIDATION, error_handling_1.ErrorSeverity.HIGH, `Solution not found: ${args.solutionId}`, {
34
+ operation: 'solution_loading',
94
35
  component: 'ChooseSolutionTool',
95
36
  requestId,
37
+ input: { solutionId: args.solutionId },
96
38
  suggestedActions: [
97
- 'Ensure session directory exists and is readable',
98
- 'Check directory permissions',
99
- 'Verify the directory path is correct',
100
- 'Verify DOT_AI_SESSION_DIR environment variable is correctly set'
39
+ 'Verify the solution ID is correct',
40
+ 'Ensure the solution was created by the recommend tool',
41
+ 'Check that the session has not expired'
101
42
  ]
102
43
  });
103
44
  }
104
- // Load solution file
105
- let solution;
45
+ const solution = session.data;
106
46
  try {
107
- solution = loadSolutionFile(args.solutionId, sessionDir);
108
47
  logger.debug('Solution file loaded successfully', {
109
48
  solutionId: args.solutionId,
110
49
  hasQuestions: !!solution.questions,
@@ -117,23 +56,22 @@ async function handleChooseSolutionTool(args, dotAI, logger, requestId) {
117
56
  });
118
57
  }
119
58
  catch (error) {
120
- 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 file', {
121
- operation: 'solution_file_load',
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',
122
61
  component: 'ChooseSolutionTool',
123
62
  requestId,
124
- input: { solutionId: args.solutionId, sessionDir },
63
+ input: { solutionId: args.solutionId },
125
64
  suggestedActions: [
126
65
  'Check that the solution ID is correct',
127
- 'Verify the solution file exists in the session directory',
128
- 'Ensure the solution was created by a recent recommend tool call',
129
- 'List available solution files in the session directory'
66
+ 'Verify the solution session exists',
67
+ 'Ensure the solution was created by a recent recommend tool call'
130
68
  ]
131
69
  });
132
70
  }
133
71
  // Prepare response with solution details and questions
134
72
  const response = {
135
73
  status: 'stage_questions',
136
- solutionId: solution.solutionId,
74
+ solutionId: args.solutionId,
137
75
  currentStage: 'required',
138
76
  questions: solution.questions.required || [],
139
77
  nextStage: 'basic',
@@ -144,7 +82,6 @@ async function handleChooseSolutionTool(args, dotAI, logger, requestId) {
144
82
  };
145
83
  logger.info('Choose solution completed successfully', {
146
84
  solutionId: args.solutionId,
147
- sessionDir,
148
85
  questionCategories: {
149
86
  required: solution.questions.required?.length || 0,
150
87
  basic: solution.questions.basic?.length || 0,
@@ -14,7 +14,7 @@ exports.DEPLOYMANIFESTS_TOOL_NAME = 'deployManifests';
14
14
  exports.DEPLOYMANIFESTS_TOOL_DESCRIPTION = 'Deploy Kubernetes manifests from generated solution with kubectl apply --wait';
15
15
  // Zod schema for MCP registration
16
16
  exports.DEPLOYMANIFESTS_TOOL_INPUT_SCHEMA = {
17
- solutionId: zod_1.z.string().regex(/^sol_[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{6}_[a-f0-9]+$/).describe('Solution ID to deploy (e.g., sol_2025-07-01T154349_1e1e242592ff)'),
17
+ solutionId: zod_1.z.string().regex(/^sol-\d+-[a-f0-9]{8}$/).describe('Solution ID to deploy (e.g., sol-1762983784617-9ddae2b8)'),
18
18
  timeout: zod_1.z.number().min(1).max(600).optional().describe('Deployment timeout in seconds (default: 30)')
19
19
  };
20
20
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"generate-manifests.d.ts","sourceRoot":"","sources":["../../src/tools/generate-manifests.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;AAYhD,eAAO,MAAM,2BAA2B,sBAAsB,CAAC;AAC/D,eAAO,MAAM,kCAAkC,+IAA+I,CAAC;AAG/L,eAAO,MAAM,mCAAmC;;;CAG/C,CAAC;AAyRF;;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,CAsMxD"}
1
+ {"version":3,"file":"generate-manifests.d.ts","sourceRoot":"","sources":["../../src/tools/generate-manifests.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;AAahD,eAAO,MAAM,2BAA2B,sBAAsB,CAAC;AAC/D,eAAO,MAAM,kCAAkC,+IAA+I,CAAC;AAG/L,eAAO,MAAM,mCAAmC;;;CAG/C,CAAC;AA2PF;;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,CAwLxD"}
@@ -46,7 +46,7 @@ const fs = __importStar(require("fs"));
46
46
  const path = __importStar(require("path"));
47
47
  const shared_prompt_loader_1 = require("../core/shared-prompt-loader");
48
48
  const yaml = __importStar(require("js-yaml"));
49
- const session_utils_1 = require("../core/session-utils");
49
+ const generic_session_manager_1 = require("../core/generic-session-manager");
50
50
  const solution_utils_1 = require("../core/solution-utils");
51
51
  const platform_utils_1 = require("../core/platform-utils");
52
52
  // Tool metadata for direct MCP registration
@@ -54,32 +54,9 @@ exports.GENERATEMANIFESTS_TOOL_NAME = 'generateManifests';
54
54
  exports.GENERATEMANIFESTS_TOOL_DESCRIPTION = 'Generate final Kubernetes manifests from fully configured solution (ONLY after completing ALL stages: required, basic, advanced, and open)';
55
55
  // Zod schema for MCP registration
56
56
  exports.GENERATEMANIFESTS_TOOL_INPUT_SCHEMA = {
57
- solutionId: zod_1.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)'),
57
+ solutionId: zod_1.z.string().regex(/^sol-\d+-[a-f0-9]{8}$/).describe('The solution ID to generate manifests for (e.g., sol-1762983784617-9ddae2b8)'),
58
58
  interaction_id: zod_1.z.string().optional().describe('INTERNAL ONLY - Do not populate. Used for evaluation dataset generation.')
59
59
  };
60
- /**
61
- * Load solution file and validate structure
62
- */
63
- function loadSolutionFile(solutionId, sessionDir) {
64
- const solutionPath = path.join(sessionDir, `${solutionId}.json`);
65
- if (!fs.existsSync(solutionPath)) {
66
- throw new Error(`Solution file not found: ${solutionPath}. Available files: ${fs.readdirSync(sessionDir).filter(f => f.endsWith('.json')).join(', ')}`);
67
- }
68
- try {
69
- const content = fs.readFileSync(solutionPath, 'utf8');
70
- const solution = JSON.parse(content);
71
- if (!solution.solutionId || !solution.questions) {
72
- throw new Error(`Invalid solution file structure: ${solutionId}. Missing required fields: solutionId or questions`);
73
- }
74
- return solution;
75
- }
76
- catch (error) {
77
- if (error instanceof SyntaxError) {
78
- throw new Error(`Invalid JSON in solution file: ${solutionId}`);
79
- }
80
- throw error;
81
- }
82
- }
83
60
  /**
84
61
  * Retrieve schemas for resources specified in the solution
85
62
  */
@@ -181,7 +158,7 @@ async function validateManifests(yamlPath) {
181
158
  /**
182
159
  * Generate manifests using AI provider
183
160
  */
184
- async function generateManifestsWithAI(solution, dotAI, logger, errorContext, dotAiLabels, interaction_id) {
161
+ async function generateManifestsWithAI(solution, solutionId, dotAI, logger, errorContext, dotAiLabels, interaction_id) {
185
162
  // Retrieve schemas for solution resources
186
163
  const resourceSchemas = await retrieveResourceSchemas(solution, dotAI, logger);
187
164
  // Prepare template variables
@@ -212,7 +189,7 @@ ${errorContext.previousManifests}
212
189
  isRetry,
213
190
  attempt: errorContext?.attempt,
214
191
  hasErrorContext: !!errorContext,
215
- solutionId: solution.solutionId
192
+ solutionId
216
193
  });
217
194
  // Get AI provider from dotAI
218
195
  const aiProvider = dotAI.ai;
@@ -227,17 +204,16 @@ ${errorContext.previousManifests}
227
204
  logger.info('AI manifest generation completed', {
228
205
  manifestLength: manifestContent.length,
229
206
  isRetry,
230
- solutionId: solution.solutionId
207
+ solutionId
231
208
  });
232
209
  return manifestContent;
233
210
  }
234
211
  /**
235
212
  * Generate dot-ai application metadata ConfigMap
236
213
  */
237
- function generateMetadataConfigMap(solution, userAnswers, logger) {
214
+ function generateMetadataConfigMap(solution, solutionId, userAnswers, logger) {
238
215
  const appName = userAnswers.name;
239
216
  const namespace = userAnswers.namespace || 'default';
240
- const solutionId = solution.solutionId;
241
217
  const originalIntent = solution.intent;
242
218
  // Validate required fields (will throw if missing)
243
219
  const dotAiLabels = (0, solution_utils_1.addDotAiLabels)(undefined, userAnswers, solution);
@@ -294,53 +270,39 @@ async function handleGenerateManifestsTool(args, dotAI, logger, requestId) {
294
270
  });
295
271
  // Input validation is handled automatically by MCP SDK with Zod schema
296
272
  // args are already validated and typed when we reach this point
297
- // Get session directory from environment
298
- let sessionDir;
299
- try {
300
- sessionDir = (0, session_utils_1.getAndValidateSessionDirectory)(true); // requireWrite=true for manifest generation
301
- logger.debug('Session directory resolved and validated', { sessionDir });
302
- }
303
- catch (error) {
304
- throw error_handling_1.ErrorHandler.createError(error_handling_1.ErrorCategory.VALIDATION, error_handling_1.ErrorSeverity.HIGH, error instanceof Error ? error.message : 'Session directory validation failed', {
305
- operation: 'session_directory_validation',
306
- component: 'GenerateManifestsTool',
307
- requestId,
308
- suggestedActions: [
309
- 'Ensure session directory exists and is writable',
310
- 'Check directory permissions',
311
- 'Verify the directory path is correct',
312
- 'Verify DOT_AI_SESSION_DIR environment variable is correctly set'
313
- ]
314
- });
315
- }
273
+ // Initialize session manager
274
+ const sessionManager = new generic_session_manager_1.GenericSessionManager('sol');
275
+ logger.debug('Session manager initialized', { requestId });
316
276
  // Ensure cluster connectivity before proceeding
317
277
  await (0, cluster_utils_1.ensureClusterConnection)(dotAI, logger, requestId, 'GenerateManifestsTool');
318
- // Load solution file
319
- let solution;
320
- try {
321
- solution = loadSolutionFile(args.solutionId, sessionDir);
322
- logger.debug('Solution file loaded successfully', {
323
- solutionId: args.solutionId,
324
- hasQuestions: !!solution.questions,
325
- primaryResources: solution.resources
326
- });
327
- }
328
- catch (error) {
329
- 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 file', {
330
- operation: 'solution_file_load',
278
+ // Load solution session
279
+ const session = sessionManager.getSession(args.solutionId);
280
+ if (!session) {
281
+ throw error_handling_1.ErrorHandler.createError(error_handling_1.ErrorCategory.VALIDATION, error_handling_1.ErrorSeverity.HIGH, `Solution not found: ${args.solutionId}`, {
282
+ operation: 'solution_loading',
331
283
  component: 'GenerateManifestsTool',
332
284
  requestId,
333
- input: { solutionId: args.solutionId, sessionDir },
285
+ input: { solutionId: args.solutionId },
334
286
  suggestedActions: [
335
- 'Check that the solution ID is correct',
336
- 'Verify the solution file exists in the session directory',
337
- 'Ensure the solution was fully configured with all stages complete',
338
- 'List available solution files in the session directory'
287
+ 'Verify the solution ID is correct',
288
+ 'Ensure the solution was created by the recommend tool',
289
+ 'Ensure all configuration stages were completed',
290
+ 'Check that the session has not expired'
339
291
  ]
340
292
  });
341
293
  }
342
- // Prepare file path for manifests
343
- const yamlPath = path.join(sessionDir, `${args.solutionId}.yaml`);
294
+ const solution = session.data;
295
+ logger.debug('Solution loaded successfully', {
296
+ solutionId: args.solutionId,
297
+ hasQuestions: !!solution.questions,
298
+ primaryResources: solution.resources
299
+ });
300
+ // Prepare file path for manifests (store in tmp directory)
301
+ const tmpDir = path.join(process.cwd(), 'tmp');
302
+ if (!fs.existsSync(tmpDir)) {
303
+ fs.mkdirSync(tmpDir, { recursive: true });
304
+ }
305
+ const yamlPath = path.join(tmpDir, `${args.solutionId}.yaml`);
344
306
  // AI generation and validation loop
345
307
  let lastError;
346
308
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
@@ -355,9 +317,9 @@ async function handleGenerateManifestsTool(args, dotAI, logger, requestId) {
355
317
  const userAnswers = (0, solution_utils_1.extractUserAnswers)(solution);
356
318
  const dotAiLabels = (0, solution_utils_1.addDotAiLabels)(undefined, userAnswers, solution);
357
319
  // Generate manifests with AI (including labels)
358
- const aiManifests = await generateManifestsWithAI(solution, dotAI, logger, lastError, dotAiLabels, args.interaction_id);
320
+ const aiManifests = await generateManifestsWithAI(solution, args.solutionId, dotAI, logger, lastError, dotAiLabels, args.interaction_id);
359
321
  // Generate metadata ConfigMap
360
- const metadataConfigMap = generateMetadataConfigMap(solution, userAnswers, logger);
322
+ const metadataConfigMap = generateMetadataConfigMap(solution, args.solutionId, userAnswers, logger);
361
323
  // Combine ConfigMap with AI-generated manifests
362
324
  const manifests = metadataConfigMap + '---\n' + aiManifests;
363
325
  // Save manifests to file
@@ -0,0 +1,15 @@
1
+ import { GenericSessionManager } from '../core/generic-session-manager';
2
+ import { Logger } from '../core/error-handling';
3
+ import { OperateSessionData } from './operate';
4
+ /**
5
+ * Analyzes user intent and generates operational proposal using AI tool loop
6
+ *
7
+ * @param intent - User's operational intent (e.g., "update my-api to v2.0")
8
+ * @param logger - Logger instance
9
+ * @param sessionManager - Session manager instance
10
+ * @param sessionId - Optional session ID for refinement
11
+ * @param interaction_id - Optional interaction ID for eval datasets
12
+ * @returns Operation output with proposed changes
13
+ */
14
+ export declare function analyzeIntent(intent: string, logger: Logger, sessionManager: GenericSessionManager<OperateSessionData>, sessionId?: string, interaction_id?: string): Promise<any>;
15
+ //# sourceMappingURL=operate-analysis.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operate-analysis.d.ts","sourceRoot":"","sources":["../../src/tools/operate-analysis.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAGxE,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAEL,kBAAkB,EAMnB,MAAM,WAAW,CAAC;AAEnB;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,qBAAqB,CAAC,kBAAkB,CAAC,EACzD,SAAS,CAAC,EAAE,MAAM,EAClB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,GAAG,CAAC,CAgDd"}
@@ -0,0 +1,238 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.analyzeIntent = analyzeIntent;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const kubectl_tools_1 = require("../core/kubectl-tools");
10
+ const ai_provider_factory_1 = require("../core/ai-provider-factory");
11
+ const operate_1 = require("./operate");
12
+ /**
13
+ * Analyzes user intent and generates operational proposal using AI tool loop
14
+ *
15
+ * @param intent - User's operational intent (e.g., "update my-api to v2.0")
16
+ * @param logger - Logger instance
17
+ * @param sessionManager - Session manager instance
18
+ * @param sessionId - Optional session ID for refinement
19
+ * @param interaction_id - Optional interaction ID for eval datasets
20
+ * @returns Operation output with proposed changes
21
+ */
22
+ async function analyzeIntent(intent, logger, sessionManager, sessionId, interaction_id) {
23
+ logger.info('Starting operate analysis', { intent, sessionId });
24
+ // 1. Embed context (patterns, policies, capabilities)
25
+ const context = await (0, operate_1.embedContext)(intent, logger);
26
+ // 2. Load prompts (static system + dynamic user message)
27
+ const systemPrompt = loadSystemPrompt();
28
+ const userMessage = buildUserMessage(intent, context);
29
+ // 3. Execute AI tool loop with kubectl tools
30
+ const aiResult = await executeToolLoop(systemPrompt, userMessage, logger, interaction_id);
31
+ // 4. Parse AI response into structured format
32
+ const proposedChanges = parseAIResponse(aiResult, logger);
33
+ // 5. Create and save session
34
+ const session = await saveAnalysisSession(intent, context, proposedChanges, sessionManager, sessionId, interaction_id, logger);
35
+ logger.info('Operate analysis complete', { sessionId: session.sessionId });
36
+ // 6. Return formatted output for user
37
+ return {
38
+ status: 'awaiting_user_approval',
39
+ sessionId: session.sessionId,
40
+ analysis: {
41
+ summary: proposedChanges.analysis,
42
+ currentState: proposedChanges.currentState,
43
+ proposedChanges: session.data.proposedChanges,
44
+ commands: session.data.commands,
45
+ dryRunValidation: session.data.dryRunValidation,
46
+ patternsApplied: session.data.patternsApplied,
47
+ capabilitiesUsed: session.data.capabilitiesUsed,
48
+ policiesChecked: session.data.policiesChecked,
49
+ risks: session.data.risks,
50
+ validationIntent: session.data.validationIntent
51
+ },
52
+ message: 'Operational proposal generated successfully. Review changes and execute with operate(sessionId, executeChoice=1).',
53
+ nextAction: `Review the proposed changes and call operate({ sessionId: "${session.sessionId}", executeChoice: 1 }) to execute.`
54
+ };
55
+ }
56
+ /**
57
+ * Loads static system prompt from prompts/operate-system.md
58
+ * This prompt is cacheable across all operate calls
59
+ */
60
+ function loadSystemPrompt() {
61
+ const promptPath = path_1.default.join(process.cwd(), 'prompts', 'operate-system.md');
62
+ return fs_1.default.readFileSync(promptPath, 'utf8');
63
+ }
64
+ /**
65
+ * Builds dynamic user message with intent and embedded context
66
+ * Uses template from prompts/operate-user.md and formatting functions from operate.ts
67
+ */
68
+ function buildUserMessage(intent, context) {
69
+ const templatePath = path_1.default.join(process.cwd(), 'prompts', 'operate-user.md');
70
+ const template = fs_1.default.readFileSync(templatePath, 'utf8');
71
+ // Format context sections using shared formatting functions
72
+ const patternsText = (0, operate_1.formatPatterns)(context.patterns);
73
+ const policiesText = (0, operate_1.formatPolicies)(context.policies);
74
+ const capabilitiesText = (0, operate_1.formatCapabilities)(context.capabilities);
75
+ // Replace template placeholders (use double braces to match template syntax)
76
+ return template
77
+ .replace('{{intent}}', intent)
78
+ .replace('{{patterns}}', patternsText)
79
+ .replace('{{policies}}', policiesText)
80
+ .replace('{{capabilities}}', capabilitiesText);
81
+ }
82
+ /**
83
+ * Executes AI tool loop with kubectl investigation tools
84
+ * AI autonomously inspects cluster and validates changes with dry-run
85
+ *
86
+ * @param systemPrompt - Static instructions (cacheable)
87
+ * @param userMessage - Dynamic content with intent and context
88
+ * @param logger - Logger instance
89
+ * @param interaction_id - Optional interaction ID for eval datasets
90
+ * @returns AI's final response
91
+ * @throws Error if AI fails to converge within 30 iterations
92
+ */
93
+ async function executeToolLoop(systemPrompt, userMessage, logger, interaction_id) {
94
+ logger.debug('Starting AI tool loop for operate analysis');
95
+ const aiProvider = (0, ai_provider_factory_1.createAIProvider)();
96
+ const result = await aiProvider.toolLoop({
97
+ systemPrompt,
98
+ userMessage,
99
+ tools: kubectl_tools_1.KUBECTL_INVESTIGATION_TOOLS,
100
+ toolExecutor: kubectl_tools_1.executeKubectlTools,
101
+ maxIterations: 30,
102
+ operation: 'operate-analysis',
103
+ evaluationContext: {
104
+ user_intent: userMessage.substring(0, 200) // First 200 chars as context
105
+ },
106
+ interaction_id
107
+ });
108
+ logger.debug('AI tool loop completed', {
109
+ iterations: result.iterations,
110
+ toolCallsExecuted: result.toolCallsExecuted.length,
111
+ responseLength: result.finalMessage.length
112
+ });
113
+ return result.finalMessage;
114
+ }
115
+ /**
116
+ * Parses AI response into structured ProposedChanges format
117
+ * Enforces strict JSON parsing with validation
118
+ *
119
+ * @param response - AI's final response
120
+ * @param logger - Logger instance
121
+ * @returns Parsed proposed changes
122
+ * @throws Error if response is not valid JSON or missing required fields
123
+ */
124
+ function parseAIResponse(response, logger) {
125
+ logger.debug('Parsing AI response');
126
+ // Extract JSON from code block
127
+ const jsonMatch = response.match(/```json\n([\s\S]+?)\n```/);
128
+ if (!jsonMatch) {
129
+ const truncatedResponse = response.substring(0, 500);
130
+ logger.error(`AI response missing JSON code block. Response: ${truncatedResponse}`);
131
+ throw new Error('AI did not return structured JSON response. Expected ```json code block with proposal.');
132
+ }
133
+ try {
134
+ const parsed = JSON.parse(jsonMatch[1]);
135
+ // Validate required fields
136
+ if (!parsed.analysis || typeof parsed.analysis !== 'string') {
137
+ throw new Error('AI response missing required "analysis" field (string)');
138
+ }
139
+ if (!parsed.commands || !Array.isArray(parsed.commands)) {
140
+ throw new Error('AI response missing required "commands" array');
141
+ }
142
+ if (parsed.commands.length === 0) {
143
+ throw new Error('AI response has empty "commands" array - no operations proposed');
144
+ }
145
+ if (!parsed.dryRunValidation || typeof parsed.dryRunValidation !== 'object') {
146
+ throw new Error('AI response missing required "dryRunValidation" object');
147
+ }
148
+ // Trust AI's claim but log for audit trail
149
+ logger.info('AI dry-run validation status', {
150
+ validation: parsed.dryRunValidation,
151
+ status: parsed.dryRunValidation.status
152
+ });
153
+ // Ensure proposedChanges structure exists
154
+ if (!parsed.proposedChanges) {
155
+ parsed.proposedChanges = { create: [], update: [], delete: [] };
156
+ }
157
+ // Validate proposedChanges structure
158
+ const changes = parsed.proposedChanges;
159
+ if (!Array.isArray(changes.create))
160
+ changes.create = [];
161
+ if (!Array.isArray(changes.update))
162
+ changes.update = [];
163
+ if (!Array.isArray(changes.delete))
164
+ changes.delete = [];
165
+ // Ensure metadata arrays exist
166
+ if (!Array.isArray(parsed.patternsApplied))
167
+ parsed.patternsApplied = [];
168
+ if (!Array.isArray(parsed.capabilitiesUsed))
169
+ parsed.capabilitiesUsed = [];
170
+ if (!Array.isArray(parsed.policiesChecked))
171
+ parsed.policiesChecked = [];
172
+ // Ensure risks object exists
173
+ if (!parsed.risks) {
174
+ parsed.risks = { level: 'low', description: 'No specific risks identified' };
175
+ }
176
+ // Ensure validationIntent exists
177
+ if (!parsed.validationIntent || typeof parsed.validationIntent !== 'string') {
178
+ parsed.validationIntent = 'Validate that the operation completed successfully';
179
+ }
180
+ logger.debug('AI response parsed successfully', {
181
+ commandCount: parsed.commands.length,
182
+ createCount: changes.create.length,
183
+ updateCount: changes.update.length,
184
+ deleteCount: changes.delete.length
185
+ });
186
+ return parsed;
187
+ }
188
+ catch (error) {
189
+ const errorMsg = error instanceof Error ? error.message : String(error);
190
+ logger.error(`Failed to parse AI response: ${errorMsg}`);
191
+ throw new Error(`Invalid AI response format: ${errorMsg}`);
192
+ }
193
+ }
194
+ /**
195
+ * Saves analysis session to disk using GenericSessionManager
196
+ *
197
+ * @param intent - User's operational intent
198
+ * @param context - Embedded context
199
+ * @param proposedChanges - Parsed AI proposal
200
+ * @param sessionManager - Session manager instance
201
+ * @param sessionId - Optional existing session ID for updates
202
+ * @param interaction_id - Optional interaction ID for eval datasets
203
+ * @param logger - Logger instance
204
+ * @returns Saved session
205
+ */
206
+ async function saveAnalysisSession(intent, context, proposedChanges, sessionManager, sessionId, interaction_id, logger) {
207
+ const sessionData = {
208
+ intent,
209
+ interaction_id,
210
+ context,
211
+ proposedChanges: proposedChanges.proposedChanges,
212
+ commands: proposedChanges.commands,
213
+ dryRunValidation: proposedChanges.dryRunValidation,
214
+ patternsApplied: proposedChanges.patternsApplied,
215
+ capabilitiesUsed: proposedChanges.capabilitiesUsed,
216
+ policiesChecked: proposedChanges.policiesChecked,
217
+ risks: proposedChanges.risks,
218
+ validationIntent: proposedChanges.validationIntent,
219
+ status: 'analysis_complete'
220
+ };
221
+ if (sessionId) {
222
+ // Update existing session (refinement case)
223
+ logger.debug('Updating existing operate session', { sessionId });
224
+ await sessionManager.replaceSession(sessionId, sessionData);
225
+ const session = sessionManager.getSession(sessionId);
226
+ if (!session) {
227
+ throw new Error(`Failed to retrieve session ${sessionId} after update`);
228
+ }
229
+ return session;
230
+ }
231
+ else {
232
+ // Create new session
233
+ logger.debug('Creating new operate session');
234
+ const session = await sessionManager.createSession(sessionData);
235
+ logger.info('Operate session created', { sessionId: session.sessionId });
236
+ return session;
237
+ }
238
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Operate Execution Workflow
3
+ *
4
+ * Executes approved operational changes using shared command executor
5
+ * and validates results using remediate tool
6
+ */
7
+ import { Logger } from '../core/error-handling';
8
+ import { GenericSessionManager } from '../core/generic-session-manager';
9
+ import { OperateSessionData, OperateOutput } from './operate';
10
+ /**
11
+ * Executes approved operational changes
12
+ * @param sessionId - Session ID with approved changes
13
+ * @param logger - Logger instance
14
+ * @param sessionManager - Session manager instance
15
+ * @returns Operation output with execution results
16
+ */
17
+ export declare function executeOperations(sessionId: string, logger: Logger, sessionManager: GenericSessionManager<OperateSessionData>): Promise<OperateOutput>;
18
+ //# sourceMappingURL=operate-execution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operate-execution.d.ts","sourceRoot":"","sources":["../../src/tools/operate-execution.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAA8C,MAAM,wBAAwB,CAAC;AAC5F,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAExE,OAAO,EAAE,kBAAkB,EAAmB,aAAa,EAAE,MAAM,WAAW,CAAC;AAG/E;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,qBAAqB,CAAC,kBAAkB,CAAC,GACxD,OAAO,CAAC,aAAa,CAAC,CAwIxB"}