@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.
- package/dist/core/capability-scan-workflow.d.ts.map +1 -1
- package/dist/core/capability-scan-workflow.js +3 -2
- package/dist/core/command-executor.d.ts +39 -0
- package/dist/core/command-executor.d.ts.map +1 -0
- package/dist/core/command-executor.js +111 -0
- package/dist/core/deploy-operation.d.ts.map +1 -1
- package/dist/core/deploy-operation.js +3 -5
- package/dist/core/pattern-vector-service.d.ts +1 -1
- package/dist/core/pattern-vector-service.d.ts.map +1 -1
- package/dist/core/pattern-vector-service.js +2 -2
- package/dist/core/schema.js +1 -1
- package/dist/interfaces/mcp.d.ts.map +1 -1
- package/dist/interfaces/mcp.js +9 -1
- package/dist/tools/answer-question.d.ts.map +1 -1
- package/dist/tools/answer-question.js +27 -142
- package/dist/tools/choose-solution.d.ts.map +1 -1
- package/dist/tools/choose-solution.js +22 -85
- package/dist/tools/deploy-manifests.js +1 -1
- package/dist/tools/generate-manifests.d.ts.map +1 -1
- package/dist/tools/generate-manifests.js +33 -71
- package/dist/tools/operate-analysis.d.ts +15 -0
- package/dist/tools/operate-analysis.d.ts.map +1 -0
- package/dist/tools/operate-analysis.js +238 -0
- package/dist/tools/operate-execution.d.ts +18 -0
- package/dist/tools/operate-execution.d.ts.map +1 -0
- package/dist/tools/operate-execution.js +122 -0
- package/dist/tools/operate.d.ts +133 -0
- package/dist/tools/operate.d.ts.map +1 -0
- package/dist/tools/operate.js +237 -0
- package/dist/tools/recommend.d.ts +23 -1
- package/dist/tools/recommend.d.ts.map +1 -1
- package/dist/tools/recommend.js +14 -116
- package/dist/tools/remediate.d.ts +7 -4
- package/dist/tools/remediate.d.ts.map +1 -1
- package/dist/tools/remediate.js +38 -81
- package/dist/tools/version.js +1 -1
- package/package.json +1 -1
- package/prompts/operate-system.md +322 -0
- package/prompts/operate-user.md +25 -0
package/dist/tools/recommend.js
CHANGED
|
@@ -2,39 +2,6 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Recommend Tool - AI-powered Kubernetes resource recommendations
|
|
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.RECOMMEND_TOOL_INPUT_SCHEMA = exports.RECOMMEND_TOOL_DESCRIPTION = exports.RECOMMEND_TOOL_NAME = void 0;
|
|
40
7
|
exports.handleRecommendTool = handleRecommendTool;
|
|
@@ -42,10 +9,7 @@ const zod_1 = require("zod");
|
|
|
42
9
|
const error_handling_1 = require("../core/error-handling");
|
|
43
10
|
const schema_1 = require("../core/schema");
|
|
44
11
|
const cluster_utils_1 = require("../core/cluster-utils");
|
|
45
|
-
const
|
|
46
|
-
const path = __importStar(require("path"));
|
|
47
|
-
const crypto = __importStar(require("crypto"));
|
|
48
|
-
const session_utils_1 = require("../core/session-utils");
|
|
12
|
+
const generic_session_manager_1 = require("../core/generic-session-manager");
|
|
49
13
|
const choose_solution_1 = require("./choose-solution");
|
|
50
14
|
const answer_question_1 = require("./answer-question");
|
|
51
15
|
const generate_manifests_1 = require("./generate-manifests");
|
|
@@ -54,7 +18,7 @@ const shared_prompt_loader_1 = require("../core/shared-prompt-loader");
|
|
|
54
18
|
const platform_utils_1 = require("../core/platform-utils");
|
|
55
19
|
// Tool metadata for direct MCP registration
|
|
56
20
|
exports.RECOMMEND_TOOL_NAME = 'recommend';
|
|
57
|
-
exports.RECOMMEND_TOOL_DESCRIPTION = 'Deploy
|
|
21
|
+
exports.RECOMMEND_TOOL_DESCRIPTION = 'Deploy applications, infrastructure, and services using Kubernetes resources with AI recommendations. Supports cloud resources via operators like Crossplane, cluster management via CAPI, and traditional Kubernetes workloads. Describe what you want to deploy. Does NOT handle policy creation, organizational patterns, or resource capabilities - use manageOrgData for those.';
|
|
58
22
|
// Zod schema for MCP registration (unified tool with stage routing)
|
|
59
23
|
exports.RECOMMEND_TOOL_INPUT_SCHEMA = {
|
|
60
24
|
stage: zod_1.z.string().optional().describe('Deployment workflow stage: "recommend" (default), "chooseSolution", "answerQuestion:required", "answerQuestion:basic", "answerQuestion:advanced", "answerQuestion:open", "generateManifests", "deployManifests". Defaults to "recommend" if omitted.'),
|
|
@@ -117,41 +81,7 @@ async function analyzeIntentForClarification(intent, aiProvider, logger, organiz
|
|
|
117
81
|
};
|
|
118
82
|
}
|
|
119
83
|
}
|
|
120
|
-
|
|
121
|
-
* Generate unique solution ID with timestamp and random component
|
|
122
|
-
*/
|
|
123
|
-
function generateSolutionId() {
|
|
124
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, '').split('T');
|
|
125
|
-
const dateTime = timestamp[0] + 'T' + timestamp[1].substring(0, 6);
|
|
126
|
-
const randomHex = crypto.randomBytes(6).toString('hex');
|
|
127
|
-
return `sol_${dateTime}_${randomHex}`;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Write solution data to file atomically (temp file + rename)
|
|
131
|
-
*/
|
|
132
|
-
function writeSolutionFile(sessionDir, solutionId, solutionData) {
|
|
133
|
-
const fileName = `${solutionId}.json`;
|
|
134
|
-
const filePath = path.join(sessionDir, fileName);
|
|
135
|
-
const tempPath = filePath + '.tmp';
|
|
136
|
-
try {
|
|
137
|
-
// Write to temporary file first
|
|
138
|
-
fs.writeFileSync(tempPath, JSON.stringify(solutionData, null, 2));
|
|
139
|
-
// Atomically rename to final location
|
|
140
|
-
fs.renameSync(tempPath, filePath);
|
|
141
|
-
}
|
|
142
|
-
catch (error) {
|
|
143
|
-
// Clean up temp file if it exists
|
|
144
|
-
try {
|
|
145
|
-
if (fs.existsSync(tempPath)) {
|
|
146
|
-
fs.unlinkSync(tempPath);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
catch (cleanupError) {
|
|
150
|
-
// Ignore cleanup errors
|
|
151
|
-
}
|
|
152
|
-
throw new Error(`Failed to write solution file ${fileName}: ${error}`);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
84
|
+
// Session management now handled by GenericSessionManager
|
|
155
85
|
/**
|
|
156
86
|
* Direct MCP tool handler for recommend functionality (unified with stage routing)
|
|
157
87
|
*/
|
|
@@ -184,24 +114,9 @@ async function handleRecommendTool(args, dotAI, logger, requestId) {
|
|
|
184
114
|
// Input validation is handled automatically by MCP SDK with Zod schema
|
|
185
115
|
// args are already validated and typed when we reach this point
|
|
186
116
|
// AI provider is already initialized and validated in dotAI.ai
|
|
187
|
-
//
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
sessionDir = (0, session_utils_1.getAndValidateSessionDirectory)(true); // requireWrite=true
|
|
191
|
-
logger.debug('Session directory validated', { requestId, sessionDir });
|
|
192
|
-
}
|
|
193
|
-
catch (error) {
|
|
194
|
-
throw error_handling_1.ErrorHandler.createError(error_handling_1.ErrorCategory.VALIDATION, error_handling_1.ErrorSeverity.HIGH, `Session directory validation failed: ${error instanceof Error ? error.message : 'Unknown error'}`, {
|
|
195
|
-
operation: 'session_directory_validation',
|
|
196
|
-
component: 'RecommendTool',
|
|
197
|
-
requestId,
|
|
198
|
-
suggestedActions: [
|
|
199
|
-
'Ensure session directory exists and is writable',
|
|
200
|
-
'Set --session-dir parameter or DOT_AI_SESSION_DIR environment variable',
|
|
201
|
-
'Check directory permissions'
|
|
202
|
-
]
|
|
203
|
-
}, error instanceof Error ? error : new Error(String(error)));
|
|
204
|
-
}
|
|
117
|
+
// Initialize session manager
|
|
118
|
+
const sessionManager = new generic_session_manager_1.GenericSessionManager('sol');
|
|
119
|
+
logger.debug('Session manager initialized', { requestId });
|
|
205
120
|
logger.info('Starting resource recommendation process', {
|
|
206
121
|
requestId,
|
|
207
122
|
intent: args.intent,
|
|
@@ -284,10 +199,8 @@ async function handleRecommendTool(args, dotAI, logger, requestId) {
|
|
|
284
199
|
// Limit to top 5 solutions (respecting quality thresholds from AI ranking)
|
|
285
200
|
const topSolutions = solutions.slice(0, 5);
|
|
286
201
|
for (const solution of topSolutions) {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
const solutionFileData = {
|
|
290
|
-
solutionId,
|
|
202
|
+
// Create complete solution data
|
|
203
|
+
const solutionData = {
|
|
291
204
|
intent: args.intent,
|
|
292
205
|
type: solution.type,
|
|
293
206
|
score: solution.score,
|
|
@@ -304,24 +217,10 @@ async function handleRecommendTool(args, dotAI, logger, requestId) {
|
|
|
304
217
|
answers: {}, // Empty initially - will be filled by answerQuestion tool
|
|
305
218
|
timestamp
|
|
306
219
|
};
|
|
307
|
-
//
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
}
|
|
312
|
-
catch (error) {
|
|
313
|
-
throw error_handling_1.ErrorHandler.createError(error_handling_1.ErrorCategory.STORAGE, error_handling_1.ErrorSeverity.HIGH, `Failed to store solution file: ${error instanceof Error ? error.message : 'Unknown error'}`, {
|
|
314
|
-
operation: 'solution_file_creation',
|
|
315
|
-
component: 'RecommendTool',
|
|
316
|
-
requestId,
|
|
317
|
-
input: { solutionId },
|
|
318
|
-
suggestedActions: [
|
|
319
|
-
'Check session directory write permissions',
|
|
320
|
-
'Ensure sufficient disk space',
|
|
321
|
-
'Verify session directory is accessible'
|
|
322
|
-
]
|
|
323
|
-
}, error instanceof Error ? error : new Error(String(error)));
|
|
324
|
-
}
|
|
220
|
+
// Create solution session
|
|
221
|
+
const session = sessionManager.createSession(solutionData);
|
|
222
|
+
const solutionId = session.sessionId;
|
|
223
|
+
logger.debug('Solution session created', { requestId, solutionId, fileName: `${solutionId}.json` });
|
|
325
224
|
// Add to response summary (decision-making data only)
|
|
326
225
|
solutionSummaries.push({
|
|
327
226
|
solutionId,
|
|
@@ -358,10 +257,9 @@ async function handleRecommendTool(args, dotAI, logger, requestId) {
|
|
|
358
257
|
guidance: "🔴 CRITICAL: You MUST present these solutions to the user and ask them to choose. DO NOT automatically call chooseSolution() without user input. Stop here and wait for user selection. IMPORTANT: Show the list of Kubernetes resources (from the 'resources' field) that each solution will use - this helps users understand what gets deployed. ALSO: Include pattern usage information in your response - show which solutions used organizational patterns and which did not.",
|
|
359
258
|
timestamp
|
|
360
259
|
};
|
|
361
|
-
logger.info('Solution
|
|
260
|
+
logger.info('Solution sessions created and response prepared', {
|
|
362
261
|
requestId,
|
|
363
|
-
solutionCount: solutionSummaries.length
|
|
364
|
-
sessionDir
|
|
262
|
+
solutionCount: solutionSummaries.length
|
|
365
263
|
});
|
|
366
264
|
return {
|
|
367
265
|
content: [{
|
|
@@ -24,17 +24,20 @@ export interface RemediateInput {
|
|
|
24
24
|
executedCommands?: string[];
|
|
25
25
|
interaction_id?: string;
|
|
26
26
|
}
|
|
27
|
-
export interface
|
|
28
|
-
sessionId: string;
|
|
27
|
+
export interface RemediateSessionData {
|
|
29
28
|
issue: string;
|
|
30
29
|
mode: 'manual' | 'automatic';
|
|
31
30
|
interaction_id?: string;
|
|
32
31
|
finalAnalysis?: RemediateOutput;
|
|
33
|
-
created: Date;
|
|
34
|
-
updated: Date;
|
|
35
32
|
status: 'investigating' | 'analysis_complete' | 'failed' | 'executed_successfully' | 'executed_with_errors' | 'cancelled';
|
|
36
33
|
executionResults?: ExecutionResult[];
|
|
37
34
|
}
|
|
35
|
+
export type RemediateSession = {
|
|
36
|
+
sessionId: string;
|
|
37
|
+
createdAt: string;
|
|
38
|
+
updatedAt: string;
|
|
39
|
+
data: RemediateSessionData;
|
|
40
|
+
};
|
|
38
41
|
export interface RemediationAction {
|
|
39
42
|
description: string;
|
|
40
43
|
command?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remediate.d.ts","sourceRoot":"","sources":["../../src/tools/remediate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"remediate.d.ts","sourceRoot":"","sources":["../../src/tools/remediate.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/remediate.js
CHANGED
|
@@ -42,11 +42,10 @@ exports.handleRemediateTool = handleRemediateTool;
|
|
|
42
42
|
const zod_1 = require("zod");
|
|
43
43
|
const error_handling_1 = require("../core/error-handling");
|
|
44
44
|
const ai_provider_factory_1 = require("../core/ai-provider-factory");
|
|
45
|
-
const
|
|
45
|
+
const generic_session_manager_1 = require("../core/generic-session-manager");
|
|
46
46
|
const kubectl_tools_1 = require("../core/kubectl-tools");
|
|
47
47
|
const fs = __importStar(require("fs"));
|
|
48
48
|
const path = __importStar(require("path"));
|
|
49
|
-
const crypto = __importStar(require("crypto"));
|
|
50
49
|
// PRD #143 Milestone 1: Hybrid approach - AI can use kubectl_api_resources tool OR continue with JSON dataRequests
|
|
51
50
|
// Tool metadata for direct MCP registration
|
|
52
51
|
exports.REMEDIATE_TOOL_NAME = 'remediate';
|
|
@@ -62,54 +61,16 @@ exports.REMEDIATE_TOOL_INPUT_SCHEMA = {
|
|
|
62
61
|
executedCommands: zod_1.z.array(zod_1.z.string()).optional().describe('Commands that were executed to remediate the issue'),
|
|
63
62
|
interaction_id: zod_1.z.string().optional().describe('INTERNAL ONLY - Do not populate. Used for evaluation dataset generation.')
|
|
64
63
|
};
|
|
65
|
-
|
|
66
|
-
* Generate unique session ID for investigation tracking
|
|
67
|
-
*/
|
|
68
|
-
function generateSessionId() {
|
|
69
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, '').slice(0, 15);
|
|
70
|
-
const random = crypto.randomBytes(8).toString('hex');
|
|
71
|
-
return `rem_${timestamp}_${random}`;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Write session file to session directory
|
|
75
|
-
*/
|
|
76
|
-
function writeSessionFile(sessionDir, sessionId, sessionData) {
|
|
77
|
-
const sessionPath = path.join(sessionDir, `${sessionId}.json`);
|
|
78
|
-
const sessionJson = JSON.stringify(sessionData, null, 2);
|
|
79
|
-
fs.writeFileSync(sessionPath, sessionJson, 'utf8');
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Read session file from session directory
|
|
83
|
-
*/
|
|
84
|
-
function readSessionFile(sessionDir, sessionId) {
|
|
85
|
-
const sessionPath = path.join(sessionDir, `${sessionId}.json`);
|
|
86
|
-
if (!fs.existsSync(sessionPath)) {
|
|
87
|
-
throw new Error(`Session file not found: ${sessionId}`);
|
|
88
|
-
}
|
|
89
|
-
const sessionJson = fs.readFileSync(sessionPath, 'utf8');
|
|
90
|
-
return JSON.parse(sessionJson);
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Update existing session file
|
|
94
|
-
*/
|
|
95
|
-
function updateSessionFile(sessionDir, sessionId, updates) {
|
|
96
|
-
const session = readSessionFile(sessionDir, sessionId);
|
|
97
|
-
const updatedSession = {
|
|
98
|
-
...session,
|
|
99
|
-
...updates,
|
|
100
|
-
updated: new Date()
|
|
101
|
-
};
|
|
102
|
-
writeSessionFile(sessionDir, sessionId, updatedSession);
|
|
103
|
-
}
|
|
64
|
+
// Session management now handled by GenericSessionManager
|
|
104
65
|
/**
|
|
105
66
|
* AI-driven investigation - uses toolLoop for single-phase investigation and analysis
|
|
106
67
|
*/
|
|
107
|
-
async function conductInvestigation(session,
|
|
68
|
+
async function conductInvestigation(session, sessionManager, aiProvider, logger, requestId, isValidation = false, interactionId) {
|
|
108
69
|
const maxIterations = 30; // Increased for thorough models like Mistral
|
|
109
70
|
logger.info('Starting AI investigation with toolLoop', {
|
|
110
71
|
requestId,
|
|
111
72
|
sessionId: session.sessionId,
|
|
112
|
-
issue: session.issue
|
|
73
|
+
issue: session.data.issue
|
|
113
74
|
});
|
|
114
75
|
try {
|
|
115
76
|
// Load investigation system prompt (static, cacheable)
|
|
@@ -125,13 +86,13 @@ async function conductInvestigation(session, sessionDir, aiProvider, logger, req
|
|
|
125
86
|
const operationName = isValidation ? 'remediate-validation' : 'remediate-investigation';
|
|
126
87
|
const result = await aiProvider.toolLoop({
|
|
127
88
|
systemPrompt: systemPrompt,
|
|
128
|
-
userMessage: `Investigate this Kubernetes issue: ${session.issue}`,
|
|
89
|
+
userMessage: `Investigate this Kubernetes issue: ${session.data.issue}`,
|
|
129
90
|
tools: kubectl_tools_1.KUBECTL_INVESTIGATION_TOOLS,
|
|
130
91
|
toolExecutor: kubectl_tools_1.executeKubectlTools,
|
|
131
92
|
maxIterations: maxIterations,
|
|
132
93
|
operation: operationName,
|
|
133
94
|
evaluationContext: {
|
|
134
|
-
user_intent: session.issue
|
|
95
|
+
user_intent: session.data.issue
|
|
135
96
|
},
|
|
136
97
|
interaction_id: interactionId
|
|
137
98
|
});
|
|
@@ -160,7 +121,7 @@ async function conductInvestigation(session, sessionDir, aiProvider, logger, req
|
|
|
160
121
|
remediation: finalAnalysis.remediation,
|
|
161
122
|
validationIntent: finalAnalysis.validationIntent,
|
|
162
123
|
executed: false,
|
|
163
|
-
mode: session.mode
|
|
124
|
+
mode: session.data.mode
|
|
164
125
|
};
|
|
165
126
|
// Add guidance based on issue status
|
|
166
127
|
if (finalAnalysis.issueStatus === 'resolved' || finalAnalysis.issueStatus === 'non_existent') {
|
|
@@ -184,12 +145,12 @@ async function conductInvestigation(session, sessionDir, aiProvider, logger, req
|
|
|
184
145
|
"All actions are designed to be safe kubectl operations (no destructive commands)"
|
|
185
146
|
].join('. ');
|
|
186
147
|
output.guidance = `🔴 CRITICAL: Present the kubectl commands to the user and ask them to choose execution method. DO NOT execute commands without user approval.\n\n${commandsSummary}\n\nRisk Assessment: ${riskSummary}`;
|
|
187
|
-
output.agentInstructions = `1. Show the user the root cause analysis and confidence level\n2. Display the kubectl commands that will be executed\n3. Explain the risk assessment\n4. Present the two execution choices and wait for user selection\n5. When user selects option 1 or 2, call the remediate tool again with: executeChoice: [1 or 2], sessionId: "${session.sessionId}", mode: "${session.mode}"\n6. DO NOT automatically execute any commands until user makes their choice`;
|
|
148
|
+
output.agentInstructions = `1. Show the user the root cause analysis and confidence level\n2. Display the kubectl commands that will be executed\n3. Explain the risk assessment\n4. Present the two execution choices and wait for user selection\n5. When user selects option 1 or 2, call the remediate tool again with: executeChoice: [1 or 2], sessionId: "${session.sessionId}", mode: "${session.data.mode}"\n6. DO NOT automatically execute any commands until user makes their choice`;
|
|
188
149
|
output.nextAction = 'remediate';
|
|
189
150
|
output.message = `AI analysis identified the root cause with ${Math.round(finalAnalysis.confidence * 100)}% confidence. ${finalAnalysis.remediation.actions.length} remediation actions are recommended.`;
|
|
190
151
|
}
|
|
191
152
|
// Update session with final analysis
|
|
192
|
-
|
|
153
|
+
sessionManager.updateSession(session.sessionId, {
|
|
193
154
|
finalAnalysis: output,
|
|
194
155
|
status: 'analysis_complete'
|
|
195
156
|
});
|
|
@@ -207,7 +168,7 @@ async function conductInvestigation(session, sessionDir, aiProvider, logger, req
|
|
|
207
168
|
sessionId: session.sessionId
|
|
208
169
|
});
|
|
209
170
|
// Mark session as failed
|
|
210
|
-
|
|
171
|
+
sessionManager.updateSession(session.sessionId, { status: 'failed' });
|
|
211
172
|
throw error_handling_1.ErrorHandler.createError(error_handling_1.ErrorCategory.AI_SERVICE, error_handling_1.ErrorSeverity.HIGH, `Investigation failed: ${error instanceof Error ? error.message : 'Unknown error'}`, {
|
|
212
173
|
operation: 'investigation_loop',
|
|
213
174
|
component: 'RemediateTool',
|
|
@@ -307,26 +268,29 @@ function parseAIFinalAnalysis(aiResponse) {
|
|
|
307
268
|
/**
|
|
308
269
|
* Execute user choice from previous session
|
|
309
270
|
*/
|
|
310
|
-
async function executeUserChoice(
|
|
271
|
+
async function executeUserChoice(sessionManager, sessionId, choice, logger, requestId, currentInteractionId) {
|
|
311
272
|
try {
|
|
312
273
|
// Load previous session
|
|
313
|
-
const session =
|
|
314
|
-
if (!session
|
|
274
|
+
const session = sessionManager.getSession(sessionId);
|
|
275
|
+
if (!session) {
|
|
276
|
+
throw new Error(`Session file not found: ${sessionId}`);
|
|
277
|
+
}
|
|
278
|
+
if (!session.data.finalAnalysis) {
|
|
315
279
|
throw error_handling_1.ErrorHandler.createError(error_handling_1.ErrorCategory.VALIDATION, error_handling_1.ErrorSeverity.HIGH, 'Session does not have final analysis - cannot execute choice', { operation: 'choice_execution', component: 'RemediateTool', sessionId });
|
|
316
280
|
}
|
|
317
281
|
logger.info('Loaded session for choice execution', {
|
|
318
282
|
requestId,
|
|
319
283
|
sessionId,
|
|
320
284
|
choice,
|
|
321
|
-
actionCount: session.finalAnalysis.remediation.actions.length
|
|
285
|
+
actionCount: session.data.finalAnalysis.remediation.actions.length
|
|
322
286
|
});
|
|
323
287
|
// Handle different choices
|
|
324
288
|
switch (choice) {
|
|
325
289
|
case 1: // Execute automatically via MCP
|
|
326
|
-
return await executeRemediationCommands(session,
|
|
290
|
+
return await executeRemediationCommands(session, sessionManager, logger, requestId, currentInteractionId);
|
|
327
291
|
case 2: { // Execute via agent
|
|
328
292
|
// Use validation intent directly from final analysis
|
|
329
|
-
const validationIntent = session.finalAnalysis.validationIntent || 'Check the status of the affected resources to verify the issue has been resolved';
|
|
293
|
+
const validationIntent = session.data.finalAnalysis.validationIntent || 'Check the status of the affected resources to verify the issue has been resolved';
|
|
330
294
|
return {
|
|
331
295
|
content: [
|
|
332
296
|
{
|
|
@@ -335,7 +299,7 @@ async function executeUserChoice(sessionDir, sessionId, choice, logger, requestI
|
|
|
335
299
|
status: 'success',
|
|
336
300
|
sessionId: sessionId,
|
|
337
301
|
message: 'Ready for agent execution',
|
|
338
|
-
remediation: session.finalAnalysis.remediation,
|
|
302
|
+
remediation: session.data.finalAnalysis.remediation,
|
|
339
303
|
instructions: {
|
|
340
304
|
nextSteps: [
|
|
341
305
|
'STEP 1: Execute the kubectl commands shown in the remediation section using your Bash tool',
|
|
@@ -365,9 +329,9 @@ async function executeUserChoice(sessionDir, sessionId, choice, logger, requestI
|
|
|
365
329
|
/**
|
|
366
330
|
* Execute remediation commands via kubectl
|
|
367
331
|
*/
|
|
368
|
-
async function executeRemediationCommands(session,
|
|
332
|
+
async function executeRemediationCommands(session, sessionManager, logger, requestId, currentInteractionId) {
|
|
369
333
|
const results = [];
|
|
370
|
-
const finalAnalysis = session.finalAnalysis;
|
|
334
|
+
const finalAnalysis = session.data.finalAnalysis;
|
|
371
335
|
let overallSuccess = true;
|
|
372
336
|
logger.info('Starting remediation command execution', {
|
|
373
337
|
requestId,
|
|
@@ -437,9 +401,8 @@ async function executeRemediationCommands(session, sessionDir, logger, requestId
|
|
|
437
401
|
const executedCommands = results.map(r => r.action);
|
|
438
402
|
const validationInput = {
|
|
439
403
|
issue: validationIntent,
|
|
440
|
-
sessionDir: sessionDir,
|
|
441
404
|
executedCommands: executedCommands,
|
|
442
|
-
interaction_id: currentInteractionId || session.interaction_id // Use current interaction_id for validation
|
|
405
|
+
interaction_id: currentInteractionId || session.data.interaction_id // Use current interaction_id for validation
|
|
443
406
|
};
|
|
444
407
|
// Recursive call to main function for validation
|
|
445
408
|
const validationResponse = await handleRemediateTool(validationInput);
|
|
@@ -521,7 +484,7 @@ async function executeRemediationCommands(session, sessionDir, logger, requestId
|
|
|
521
484
|
}
|
|
522
485
|
}
|
|
523
486
|
// Update session with execution results
|
|
524
|
-
|
|
487
|
+
sessionManager.updateSession(session.sessionId, {
|
|
525
488
|
status: overallSuccess ? 'executed_successfully' : 'executed_with_errors',
|
|
526
489
|
executionResults: results
|
|
527
490
|
});
|
|
@@ -587,9 +550,9 @@ async function handleRemediateTool(args) {
|
|
|
587
550
|
const requestId = `remediate_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
588
551
|
const logger = new error_handling_1.ConsoleLogger('RemediateTool');
|
|
589
552
|
try {
|
|
590
|
-
//
|
|
591
|
-
const
|
|
592
|
-
logger.debug('Session
|
|
553
|
+
// Initialize session manager
|
|
554
|
+
const sessionManager = new generic_session_manager_1.GenericSessionManager('rem');
|
|
555
|
+
logger.debug('Session manager initialized', { requestId });
|
|
593
556
|
// Validate input
|
|
594
557
|
const validatedInput = validateRemediateInput(args);
|
|
595
558
|
// Handle choice execution if provided
|
|
@@ -599,34 +562,28 @@ async function handleRemediateTool(args) {
|
|
|
599
562
|
choice: validatedInput.executeChoice,
|
|
600
563
|
sessionId: validatedInput.sessionId
|
|
601
564
|
});
|
|
602
|
-
return await executeUserChoice(
|
|
565
|
+
return await executeUserChoice(sessionManager, validatedInput.sessionId, validatedInput.executeChoice, logger, requestId, validatedInput.interaction_id);
|
|
603
566
|
}
|
|
604
567
|
// Validate that we have an issue for new investigations
|
|
605
568
|
if (!validatedInput.issue) {
|
|
606
569
|
throw error_handling_1.ErrorHandler.createError(error_handling_1.ErrorCategory.VALIDATION, error_handling_1.ErrorSeverity.HIGH, 'Issue description is required for new investigations', { operation: 'input_validation', component: 'RemediateTool' });
|
|
607
570
|
}
|
|
608
|
-
//
|
|
609
|
-
const
|
|
610
|
-
const session = {
|
|
611
|
-
sessionId,
|
|
571
|
+
// Create initial session using session manager
|
|
572
|
+
const session = sessionManager.createSession({
|
|
612
573
|
issue: validatedInput.issue,
|
|
613
574
|
mode: validatedInput.mode || 'manual',
|
|
614
575
|
interaction_id: validatedInput.interaction_id,
|
|
615
|
-
created: new Date(),
|
|
616
|
-
updated: new Date(),
|
|
617
576
|
status: 'investigating'
|
|
618
|
-
};
|
|
619
|
-
|
|
620
|
-
writeSessionFile(sessionDir, sessionId, session);
|
|
621
|
-
logger.info('Investigation session created', { requestId, sessionId });
|
|
577
|
+
});
|
|
578
|
+
logger.info('Investigation session created', { requestId, sessionId: session.sessionId });
|
|
622
579
|
// Initialize AI provider (will validate API key automatically)
|
|
623
580
|
const aiProvider = (0, ai_provider_factory_1.createAIProvider)();
|
|
624
581
|
// Conduct AI-driven investigation (detect if this is post-execution validation)
|
|
625
582
|
const isValidation = validatedInput.executedCommands && validatedInput.executedCommands.length > 0;
|
|
626
|
-
const finalAnalysis = await conductInvestigation(session,
|
|
583
|
+
const finalAnalysis = await conductInvestigation(session, sessionManager, aiProvider, logger, requestId, isValidation, validatedInput.interaction_id);
|
|
627
584
|
logger.info('Remediation analysis completed', {
|
|
628
585
|
requestId,
|
|
629
|
-
sessionId,
|
|
586
|
+
sessionId: session.sessionId,
|
|
630
587
|
rootCause: finalAnalysis.analysis.rootCause,
|
|
631
588
|
actionCount: finalAnalysis.remediation.actions.length,
|
|
632
589
|
riskLevel: finalAnalysis.remediation.risk
|
|
@@ -635,7 +592,7 @@ async function handleRemediateTool(args) {
|
|
|
635
592
|
if (finalAnalysis.status === 'success') {
|
|
636
593
|
logger.info('Issue resolved/non-existent - returning success without execution decision', {
|
|
637
594
|
requestId,
|
|
638
|
-
sessionId,
|
|
595
|
+
sessionId: session.sessionId,
|
|
639
596
|
status: finalAnalysis.status
|
|
640
597
|
});
|
|
641
598
|
// Return MCP-compliant response for resolved issues
|
|
@@ -652,7 +609,7 @@ async function handleRemediateTool(args) {
|
|
|
652
609
|
const executionDecision = makeExecutionDecision(validatedInput.mode || 'manual', finalAnalysis.analysis.confidence, finalAnalysis.remediation.risk, validatedInput.confidenceThreshold, validatedInput.maxRiskLevel);
|
|
653
610
|
logger.info('Execution decision made', {
|
|
654
611
|
requestId,
|
|
655
|
-
sessionId,
|
|
612
|
+
sessionId: session.sessionId,
|
|
656
613
|
mode: validatedInput.mode,
|
|
657
614
|
shouldExecute: executionDecision.shouldExecute,
|
|
658
615
|
reason: executionDecision.reason,
|
|
@@ -685,9 +642,9 @@ async function handleRemediateTool(args) {
|
|
|
685
642
|
// Execute remediation actions if automatic mode approves it
|
|
686
643
|
if (executionDecision.shouldExecute) {
|
|
687
644
|
// Update session object with final analysis for execution
|
|
688
|
-
session.finalAnalysis = finalAnalysis;
|
|
645
|
+
session.data.finalAnalysis = finalAnalysis;
|
|
689
646
|
// Execute commands and return the complete result (includes post-execution validation)
|
|
690
|
-
return await executeRemediationCommands(session,
|
|
647
|
+
return await executeRemediationCommands(session, sessionManager, logger, requestId, validatedInput.interaction_id);
|
|
691
648
|
}
|
|
692
649
|
// Return MCP-compliant response
|
|
693
650
|
return {
|
package/dist/tools/version.js
CHANGED
|
@@ -85,7 +85,7 @@ async function getVectorDBStatus() {
|
|
|
85
85
|
// Test patterns collection
|
|
86
86
|
const patternsStatus = await testCollectionStatus('patterns', () => {
|
|
87
87
|
const patternVectorDB = new index_1.VectorDBService({ collectionName: 'patterns' });
|
|
88
|
-
const patternService = new index_1.PatternVectorService(patternVectorDB, embeddingService);
|
|
88
|
+
const patternService = new index_1.PatternVectorService('patterns', patternVectorDB, embeddingService);
|
|
89
89
|
return patternService.getPatternsCount();
|
|
90
90
|
});
|
|
91
91
|
// Test policies collection
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vfarcic/dot-ai",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.140.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",
|