@vfarcic/dot-ai 0.5.0 → 0.5.1
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/.claude/commands/context-load.md +11 -0
- package/.claude/commands/context-save.md +16 -0
- package/.claude/commands/prd-done.md +115 -0
- package/.claude/commands/prd-get.md +25 -0
- package/.claude/commands/prd-start.md +87 -0
- package/.claude/commands/task-done.md +77 -0
- package/.claude/commands/tests-reminder.md +32 -0
- package/.claude/settings.local.json +20 -0
- package/.eslintrc.json +25 -0
- package/.github/workflows/ci.yml +170 -0
- package/.prettierrc.json +10 -0
- package/.teller.yml +8 -0
- package/CLAUDE.md +162 -0
- package/assets/images/logo.png +0 -0
- package/bin/dot-ai.ts +47 -0
- package/destroy.sh +45 -0
- package/devbox.json +13 -0
- package/devbox.lock +225 -0
- package/docs/API.md +449 -0
- package/docs/CONTEXT.md +49 -0
- package/docs/DEVELOPMENT.md +203 -0
- package/docs/NEXT_STEPS.md +97 -0
- package/docs/STAGE_BASED_API.md +97 -0
- package/docs/cli-guide.md +798 -0
- package/docs/design.md +750 -0
- package/docs/discovery-engine.md +515 -0
- package/docs/error-handling.md +429 -0
- package/docs/function-registration.md +157 -0
- package/docs/mcp-guide.md +416 -0
- package/package.json +2 -121
- package/renovate.json +51 -0
- package/setup.sh +111 -0
- package/{dist/cli.js → src/cli.ts} +26 -19
- package/src/core/claude.ts +280 -0
- package/src/core/deploy-operation.ts +127 -0
- package/src/core/discovery.ts +900 -0
- package/src/core/error-handling.ts +562 -0
- package/src/core/index.ts +143 -0
- package/src/core/kubernetes-utils.ts +218 -0
- package/src/core/memory.ts +148 -0
- package/src/core/schema.ts +830 -0
- package/src/core/session-utils.ts +97 -0
- package/src/core/workflow.ts +234 -0
- package/src/index.ts +18 -0
- package/src/interfaces/cli.ts +872 -0
- package/src/interfaces/mcp.ts +183 -0
- package/src/mcp/server.ts +131 -0
- package/src/tools/answer-question.ts +807 -0
- package/src/tools/choose-solution.ts +169 -0
- package/src/tools/deploy-manifests.ts +94 -0
- package/src/tools/generate-manifests.ts +502 -0
- package/src/tools/index.ts +41 -0
- package/src/tools/recommend.ts +370 -0
- package/tests/__mocks__/@kubernetes/client-node.ts +106 -0
- package/tests/build-system.test.ts +345 -0
- package/tests/configuration.test.ts +226 -0
- package/tests/core/deploy-operation.test.ts +38 -0
- package/tests/core/discovery.test.ts +1648 -0
- package/tests/core/error-handling.test.ts +632 -0
- package/tests/core/schema.test.ts +1658 -0
- package/tests/core/session-utils.test.ts +245 -0
- package/tests/core.test.ts +439 -0
- package/tests/fixtures/configmap-no-labels.yaml +8 -0
- package/tests/fixtures/crossplane-app-configuration.yaml +6 -0
- package/tests/fixtures/crossplane-providers.yaml +45 -0
- package/tests/fixtures/crossplane-rbac.yaml +48 -0
- package/tests/fixtures/invalid-configmap.yaml +8 -0
- package/tests/fixtures/invalid-deployment.yaml +17 -0
- package/tests/fixtures/test-deployment.yaml +28 -0
- package/tests/fixtures/valid-configmap.yaml +15 -0
- package/tests/infrastructure.test.ts +426 -0
- package/tests/interfaces/cli.test.ts +1036 -0
- package/tests/interfaces/mcp.test.ts +139 -0
- package/tests/kubernetes-utils.test.ts +200 -0
- package/tests/mcp/server.test.ts +126 -0
- package/tests/setup.ts +31 -0
- package/tests/tools/answer-question.test.ts +367 -0
- package/tests/tools/choose-solution.test.ts +481 -0
- package/tests/tools/deploy-manifests.test.ts +185 -0
- package/tests/tools/generate-manifests.test.ts +441 -0
- package/tests/tools/index.test.ts +111 -0
- package/tests/tools/recommend.test.ts +180 -0
- package/tsconfig.json +34 -0
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/core/claude.d.ts +0 -42
- package/dist/core/claude.d.ts.map +0 -1
- package/dist/core/claude.js +0 -229
- package/dist/core/deploy-operation.d.ts +0 -38
- package/dist/core/deploy-operation.d.ts.map +0 -1
- package/dist/core/deploy-operation.js +0 -101
- package/dist/core/discovery.d.ts +0 -162
- package/dist/core/discovery.d.ts.map +0 -1
- package/dist/core/discovery.js +0 -758
- package/dist/core/error-handling.d.ts +0 -167
- package/dist/core/error-handling.d.ts.map +0 -1
- package/dist/core/error-handling.js +0 -399
- package/dist/core/index.d.ts +0 -42
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js +0 -123
- package/dist/core/kubernetes-utils.d.ts +0 -38
- package/dist/core/kubernetes-utils.d.ts.map +0 -1
- package/dist/core/kubernetes-utils.js +0 -177
- package/dist/core/memory.d.ts +0 -45
- package/dist/core/memory.d.ts.map +0 -1
- package/dist/core/memory.js +0 -113
- package/dist/core/schema.d.ts +0 -187
- package/dist/core/schema.d.ts.map +0 -1
- package/dist/core/schema.js +0 -655
- package/dist/core/session-utils.d.ts +0 -29
- package/dist/core/session-utils.d.ts.map +0 -1
- package/dist/core/session-utils.js +0 -121
- package/dist/core/workflow.d.ts +0 -70
- package/dist/core/workflow.d.ts.map +0 -1
- package/dist/core/workflow.js +0 -161
- package/dist/index.d.ts +0 -15
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -32
- package/dist/interfaces/cli.d.ts +0 -74
- package/dist/interfaces/cli.d.ts.map +0 -1
- package/dist/interfaces/cli.js +0 -769
- package/dist/interfaces/mcp.d.ts +0 -30
- package/dist/interfaces/mcp.d.ts.map +0 -1
- package/dist/interfaces/mcp.js +0 -105
- package/dist/mcp/server.d.ts +0 -9
- package/dist/mcp/server.d.ts.map +0 -1
- package/dist/mcp/server.js +0 -151
- package/dist/tools/answer-question.d.ts +0 -27
- package/dist/tools/answer-question.d.ts.map +0 -1
- package/dist/tools/answer-question.js +0 -696
- package/dist/tools/choose-solution.d.ts +0 -23
- package/dist/tools/choose-solution.d.ts.map +0 -1
- package/dist/tools/choose-solution.js +0 -171
- package/dist/tools/deploy-manifests.d.ts +0 -25
- package/dist/tools/deploy-manifests.d.ts.map +0 -1
- package/dist/tools/deploy-manifests.js +0 -74
- package/dist/tools/generate-manifests.d.ts +0 -23
- package/dist/tools/generate-manifests.d.ts.map +0 -1
- package/dist/tools/generate-manifests.js +0 -424
- package/dist/tools/index.d.ts +0 -11
- package/dist/tools/index.d.ts.map +0 -1
- package/dist/tools/index.js +0 -34
- package/dist/tools/recommend.d.ts +0 -23
- package/dist/tools/recommend.d.ts.map +0 -1
- package/dist/tools/recommend.js +0 -332
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Choose Solution Tool - Select a solution and return its questions
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { ErrorHandler, ErrorCategory, ErrorSeverity } from '../core/error-handling';
|
|
7
|
+
import { DotAI } from '../core/index';
|
|
8
|
+
import { Logger } from '../core/error-handling';
|
|
9
|
+
import * as fs from 'fs';
|
|
10
|
+
import * as path from 'path';
|
|
11
|
+
import { getAndValidateSessionDirectory } from '../core/session-utils';
|
|
12
|
+
|
|
13
|
+
// Tool metadata for direct MCP registration
|
|
14
|
+
export const CHOOSESOLUTION_TOOL_NAME = 'chooseSolution';
|
|
15
|
+
export const CHOOSESOLUTION_TOOL_DESCRIPTION = 'Select a solution by ID and return its questions for configuration';
|
|
16
|
+
|
|
17
|
+
// Zod schema for MCP registration
|
|
18
|
+
export const CHOOSESOLUTION_TOOL_INPUT_SCHEMA = {
|
|
19
|
+
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 choose (e.g., sol_2025-07-01T154349_1e1e242592ff)')
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Load solution file by ID
|
|
26
|
+
*/
|
|
27
|
+
function loadSolutionFile(solutionId: string, sessionDir: string): any {
|
|
28
|
+
const solutionPath = path.join(sessionDir, `${solutionId}.json`);
|
|
29
|
+
|
|
30
|
+
if (!fs.existsSync(solutionPath)) {
|
|
31
|
+
throw new Error(`Solution file not found: ${solutionPath}. Available files: ${fs.readdirSync(sessionDir).filter(f => f.endsWith('.json')).join(', ')}`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
const content = fs.readFileSync(solutionPath, 'utf8');
|
|
36
|
+
const solution = JSON.parse(content);
|
|
37
|
+
|
|
38
|
+
// Validate solution structure
|
|
39
|
+
if (!solution.solutionId || !solution.questions) {
|
|
40
|
+
throw new Error(`Invalid solution file structure: ${solutionId}. Missing required fields: solutionId or questions`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return solution;
|
|
44
|
+
} catch (error) {
|
|
45
|
+
if (error instanceof SyntaxError) {
|
|
46
|
+
throw new Error(`Invalid JSON in solution file: ${solutionId}. ${error.message}`);
|
|
47
|
+
}
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Direct MCP tool handler for chooseSolution functionality
|
|
54
|
+
*/
|
|
55
|
+
export async function handleChooseSolutionTool(
|
|
56
|
+
args: { solutionId: string },
|
|
57
|
+
dotAI: DotAI,
|
|
58
|
+
logger: Logger,
|
|
59
|
+
requestId: string
|
|
60
|
+
): Promise<{ content: { type: 'text'; text: string }[] }> {
|
|
61
|
+
return await ErrorHandler.withErrorHandling(
|
|
62
|
+
async () => {
|
|
63
|
+
logger.debug('Handling chooseSolution request', { requestId, solutionId: args?.solutionId });
|
|
64
|
+
|
|
65
|
+
// Input validation is handled automatically by MCP SDK with Zod schema
|
|
66
|
+
// args are already validated and typed when we reach this point
|
|
67
|
+
|
|
68
|
+
// Get session directory from environment
|
|
69
|
+
let sessionDir: string;
|
|
70
|
+
try {
|
|
71
|
+
sessionDir = getAndValidateSessionDirectory(args, false); // requireWrite=false
|
|
72
|
+
logger.debug('Session directory resolved and validated', { sessionDir });
|
|
73
|
+
} catch (error) {
|
|
74
|
+
throw ErrorHandler.createError(
|
|
75
|
+
ErrorCategory.VALIDATION,
|
|
76
|
+
ErrorSeverity.HIGH,
|
|
77
|
+
error instanceof Error ? error.message : 'Session directory validation failed',
|
|
78
|
+
{
|
|
79
|
+
operation: 'session_directory_validation',
|
|
80
|
+
component: 'ChooseSolutionTool',
|
|
81
|
+
requestId,
|
|
82
|
+
suggestedActions: [
|
|
83
|
+
'Ensure session directory exists and is readable',
|
|
84
|
+
'Check directory permissions',
|
|
85
|
+
'Verify the directory path is correct',
|
|
86
|
+
'Verify DOT_AI_SESSION_DIR environment variable is correctly set'
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Load solution file
|
|
93
|
+
let solution: any;
|
|
94
|
+
try {
|
|
95
|
+
solution = loadSolutionFile(args.solutionId, sessionDir);
|
|
96
|
+
logger.debug('Solution file loaded successfully', {
|
|
97
|
+
solutionId: args.solutionId,
|
|
98
|
+
hasQuestions: !!solution.questions,
|
|
99
|
+
questionCategories: {
|
|
100
|
+
required: solution.questions?.required?.length || 0,
|
|
101
|
+
basic: solution.questions?.basic?.length || 0,
|
|
102
|
+
advanced: solution.questions?.advanced?.length || 0,
|
|
103
|
+
hasOpen: !!solution.questions?.open
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
} catch (error) {
|
|
107
|
+
throw ErrorHandler.createError(
|
|
108
|
+
ErrorCategory.STORAGE,
|
|
109
|
+
ErrorSeverity.HIGH,
|
|
110
|
+
error instanceof Error ? error.message : 'Failed to load solution file',
|
|
111
|
+
{
|
|
112
|
+
operation: 'solution_file_load',
|
|
113
|
+
component: 'ChooseSolutionTool',
|
|
114
|
+
requestId,
|
|
115
|
+
input: { solutionId: args.solutionId, sessionDir },
|
|
116
|
+
suggestedActions: [
|
|
117
|
+
'Check that the solution ID is correct',
|
|
118
|
+
'Verify the solution file exists in the session directory',
|
|
119
|
+
'Ensure the solution was created by a recent recommend tool call',
|
|
120
|
+
'List available solution files in the session directory'
|
|
121
|
+
]
|
|
122
|
+
}
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Prepare response with solution details and questions
|
|
127
|
+
const response = {
|
|
128
|
+
status: 'stage_questions',
|
|
129
|
+
solutionId: solution.solutionId,
|
|
130
|
+
currentStage: 'required',
|
|
131
|
+
questions: solution.questions.required || [],
|
|
132
|
+
nextStage: 'basic',
|
|
133
|
+
message: 'Please provide the required configuration for your application.',
|
|
134
|
+
nextAction: 'answerQuestion',
|
|
135
|
+
guidance: 'Answer questions in this stage or skip to proceed to the next stage. Do NOT try to generate manifests yet.',
|
|
136
|
+
timestamp: new Date().toISOString()
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
logger.info('Choose solution completed successfully', {
|
|
140
|
+
solutionId: args.solutionId,
|
|
141
|
+
sessionDir,
|
|
142
|
+
questionCategories: {
|
|
143
|
+
required: solution.questions.required?.length || 0,
|
|
144
|
+
basic: solution.questions.basic?.length || 0,
|
|
145
|
+
advanced: solution.questions.advanced?.length || 0,
|
|
146
|
+
hasOpen: !!solution.questions.open
|
|
147
|
+
},
|
|
148
|
+
totalQuestions: (solution.questions.required?.length || 0) +
|
|
149
|
+
(solution.questions.basic?.length || 0) +
|
|
150
|
+
(solution.questions.advanced?.length || 0) +
|
|
151
|
+
(solution.questions.open ? 1 : 0)
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
return {
|
|
155
|
+
content: [{
|
|
156
|
+
type: 'text' as const,
|
|
157
|
+
text: JSON.stringify(response, null, 2)
|
|
158
|
+
}]
|
|
159
|
+
};
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
operation: 'choose_solution',
|
|
163
|
+
component: 'ChooseSolutionTool',
|
|
164
|
+
requestId,
|
|
165
|
+
input: args
|
|
166
|
+
}
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deploy Manifests Tool - Apply Kubernetes manifests with readiness checking
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { ErrorHandler } from '../core/error-handling';
|
|
7
|
+
import { DeployOperation } from '../core/deploy-operation';
|
|
8
|
+
import { DotAI } from '../core/index';
|
|
9
|
+
import { Logger } from '../core/error-handling';
|
|
10
|
+
|
|
11
|
+
// Tool metadata for direct MCP registration
|
|
12
|
+
export const DEPLOYMANIFESTS_TOOL_NAME = 'deployManifests';
|
|
13
|
+
export const DEPLOYMANIFESTS_TOOL_DESCRIPTION = 'Deploy Kubernetes manifests from generated solution with kubectl apply --wait';
|
|
14
|
+
|
|
15
|
+
// Zod schema for MCP registration
|
|
16
|
+
export const DEPLOYMANIFESTS_TOOL_INPUT_SCHEMA = {
|
|
17
|
+
solutionId: 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)'),
|
|
18
|
+
timeout: z.number().min(1).max(600).optional().describe('Deployment timeout in seconds (default: 30)')
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Direct MCP tool handler for deployManifests functionality
|
|
24
|
+
*/
|
|
25
|
+
export async function handleDeployManifestsTool(
|
|
26
|
+
args: { solutionId: string; timeout?: number },
|
|
27
|
+
dotAI: DotAI,
|
|
28
|
+
logger: Logger,
|
|
29
|
+
requestId: string
|
|
30
|
+
): Promise<{ content: { type: 'text'; text: string }[] }> {
|
|
31
|
+
return await ErrorHandler.withErrorHandling(
|
|
32
|
+
async () => {
|
|
33
|
+
logger.debug('Handling deployManifests request', {
|
|
34
|
+
requestId,
|
|
35
|
+
solutionId: args?.solutionId,
|
|
36
|
+
timeout: args?.timeout
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Input validation is handled automatically by MCP SDK with Zod schema
|
|
40
|
+
// args are already validated and typed when we reach this point
|
|
41
|
+
|
|
42
|
+
const deployOp = new DeployOperation();
|
|
43
|
+
|
|
44
|
+
const deployOptions = {
|
|
45
|
+
solutionId: args.solutionId,
|
|
46
|
+
timeout: args.timeout || 30
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
logger.info('Starting deployment operation', {
|
|
50
|
+
solutionId: args.solutionId,
|
|
51
|
+
timeout: deployOptions.timeout,
|
|
52
|
+
requestId
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const result = await deployOp.deploy(deployOptions);
|
|
56
|
+
|
|
57
|
+
logger.info('Deployment operation completed', {
|
|
58
|
+
success: result.success,
|
|
59
|
+
solutionId: result.solutionId,
|
|
60
|
+
manifestPath: result.manifestPath,
|
|
61
|
+
readinessTimeout: result.readinessTimeout,
|
|
62
|
+
requestId
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Prepare response with deployment status
|
|
66
|
+
const response = {
|
|
67
|
+
success: result.success,
|
|
68
|
+
solutionId: result.solutionId,
|
|
69
|
+
manifestPath: result.manifestPath,
|
|
70
|
+
readinessTimeout: result.readinessTimeout,
|
|
71
|
+
message: result.message,
|
|
72
|
+
kubectlOutput: result.kubectlOutput,
|
|
73
|
+
// Additional deployment status info
|
|
74
|
+
deploymentComplete: result.success && !result.readinessTimeout,
|
|
75
|
+
requiresStatusCheck: result.success && result.readinessTimeout,
|
|
76
|
+
timestamp: new Date().toISOString()
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
content: [{
|
|
81
|
+
type: 'text' as const,
|
|
82
|
+
text: JSON.stringify(response, null, 2)
|
|
83
|
+
}]
|
|
84
|
+
};
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
operation: 'deploy_manifests',
|
|
88
|
+
component: 'DeployManifestsTool',
|
|
89
|
+
requestId,
|
|
90
|
+
input: args
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|