@vfarcic/dot-ai 0.103.0 → 0.104.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/README.md +14 -0
- package/dist/core/nushell-runtime.d.ts +39 -0
- package/dist/core/nushell-runtime.d.ts.map +1 -0
- package/dist/core/nushell-runtime.js +103 -0
- package/dist/core/platform-operations.d.ts +76 -0
- package/dist/core/platform-operations.d.ts.map +1 -0
- package/dist/core/platform-operations.js +317 -0
- package/dist/interfaces/mcp.d.ts.map +1 -1
- package/dist/interfaces/mcp.js +9 -1
- package/dist/tools/build-platform.d.ts +25 -0
- package/dist/tools/build-platform.d.ts.map +1 -0
- package/dist/tools/build-platform.js +277 -0
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +6 -1
- package/dist/tools/version.d.ts +7 -0
- package/dist/tools/version.d.ts.map +1 -1
- package/dist/tools/version.js +34 -5
- package/package.json +3 -2
- package/prompts/map-intent-to-operation.md +104 -0
- package/prompts/parse-script-operations.md +72 -0
- package/scripts/ack.nu +195 -0
- package/scripts/anthropic.nu +24 -0
- package/scripts/argo-workflows.nu +47 -0
- package/scripts/argocd.nu +85 -0
- package/scripts/aso.nu +74 -0
- package/scripts/atlas.nu +15 -0
- package/scripts/backstage.nu +349 -0
- package/scripts/cert-manager.nu +13 -0
- package/scripts/cnpg.nu +14 -0
- package/scripts/common.nu +116 -0
- package/scripts/crossplane.nu +718 -0
- package/scripts/dot.nu +32 -0
- package/scripts/external-secrets.nu +110 -0
- package/scripts/gatekeeper.nu +19 -0
- package/scripts/github.nu +42 -0
- package/scripts/image.nu +67 -0
- package/scripts/ingress.nu +149 -0
- package/scripts/kro.nu +11 -0
- package/scripts/kubernetes.nu +609 -0
- package/scripts/kubevela.nu +22 -0
- package/scripts/kyverno.nu +16 -0
- package/scripts/mcp.nu +139 -0
- package/scripts/port.nu +71 -0
- package/scripts/prometheus.nu +21 -0
- package/scripts/registry.nu +55 -0
- package/scripts/storage.nu +210 -0
- package/scripts/tests.nu +12 -0
- package/scripts/toolhive.nu +21 -0
- package/scripts/velero.nu +45 -0
package/README.md
CHANGED
|
@@ -22,6 +22,11 @@ DevOps AI Toolkit is an AI-powered development productivity platform that enhanc
|
|
|
22
22
|
- **SRE Teams**: Automate root cause analysis and generate executable remediation commands
|
|
23
23
|
- **Support Teams**: Handle incident response with AI-guided investigation and repair workflows
|
|
24
24
|
|
|
25
|
+
### Platform Building
|
|
26
|
+
- **Platform Engineers**: Install and configure platform tools conversationally without memorizing script paths and commands
|
|
27
|
+
- **New Team Members**: Build platform infrastructure through zero-knowledge guided workflows
|
|
28
|
+
- **DevOps Teams**: Create and manage Kubernetes clusters through natural language interactions
|
|
29
|
+
|
|
25
30
|
### Documentation Testing
|
|
26
31
|
- **Documentation Maintainers**: Automatically validate documentation accuracy and catch outdated content
|
|
27
32
|
- **Technical Writers**: Identify which sections need updates and prioritize work effectively
|
|
@@ -79,6 +84,15 @@ Result: Finds sqls.devopstoolkit.live as perfect match ✨
|
|
|
79
84
|
|
|
80
85
|
📖 [Learn more →](./docs/mcp-remediate-guide.md)
|
|
81
86
|
|
|
87
|
+
### Platform Building
|
|
88
|
+
🗣️ **Natural Language Operations**: Install tools and create clusters through conversation without memorizing commands
|
|
89
|
+
🔍 **Dynamic Discovery**: Automatically discovers 21+ available platform operations from infrastructure scripts
|
|
90
|
+
🤖 **AI-Powered Intent Mapping**: Understands variations like "Install Argo CD", "Set up ArgoCD", "Deploy Argo CD"
|
|
91
|
+
💬 **Conversational Configuration**: Guides through parameter collection step-by-step with sensible defaults
|
|
92
|
+
🎯 **Zero-Knowledge Onboarding**: New users successfully build platforms without documentation
|
|
93
|
+
|
|
94
|
+
📖 [Learn more →](./docs/mcp-build-platform-guide.md)
|
|
95
|
+
|
|
82
96
|
### Documentation Testing & Validation
|
|
83
97
|
📖 **Automated Testing**: Validates documentation by executing commands and testing examples
|
|
84
98
|
🔍 **Two-Phase Validation**: Tests both functionality (does it work?) and semantic accuracy (are descriptions truthful?)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nushell Runtime Checker
|
|
3
|
+
*
|
|
4
|
+
* Detects Nushell installation and provides installation guidance.
|
|
5
|
+
*/
|
|
6
|
+
export interface NushellVersionInfo {
|
|
7
|
+
installed: boolean;
|
|
8
|
+
version: string | null;
|
|
9
|
+
error?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare class NushellRuntime {
|
|
12
|
+
/**
|
|
13
|
+
* Check if Nushell is installed on the system
|
|
14
|
+
*/
|
|
15
|
+
checkInstalled(): Promise<boolean>;
|
|
16
|
+
/**
|
|
17
|
+
* Get the installed Nushell version
|
|
18
|
+
* Returns null if Nushell is not installed
|
|
19
|
+
*/
|
|
20
|
+
getVersion(): Promise<string | null>;
|
|
21
|
+
/**
|
|
22
|
+
* Get comprehensive version information
|
|
23
|
+
*/
|
|
24
|
+
getVersionInfo(): Promise<NushellVersionInfo>;
|
|
25
|
+
/**
|
|
26
|
+
* Get the official installation documentation URL
|
|
27
|
+
*/
|
|
28
|
+
getInstallationUrl(): string;
|
|
29
|
+
/**
|
|
30
|
+
* Validate Nushell installation and return detailed status
|
|
31
|
+
*/
|
|
32
|
+
validateRuntime(): Promise<{
|
|
33
|
+
ready: boolean;
|
|
34
|
+
message: string;
|
|
35
|
+
versionInfo?: NushellVersionInfo;
|
|
36
|
+
installationUrl?: string;
|
|
37
|
+
}>;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=nushell-runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nushell-runtime.d.ts","sourceRoot":"","sources":["../../src/core/nushell-runtime.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAOD,qBAAa,cAAc;IACzB;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;IASxC;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAW1C;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,kBAAkB,CAAC;IA2BnD;;OAEG;IACH,kBAAkB,IAAI,MAAM;IAI5B;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC;QAC/B,KAAK,EAAE,OAAO,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,kBAAkB,CAAC;QACjC,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;CA2BH"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Nushell Runtime Checker
|
|
4
|
+
*
|
|
5
|
+
* Detects Nushell installation and provides installation guidance.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.NushellRuntime = void 0;
|
|
9
|
+
const child_process_1 = require("child_process");
|
|
10
|
+
const util_1 = require("util");
|
|
11
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
12
|
+
/**
|
|
13
|
+
* Official Nushell installation documentation
|
|
14
|
+
*/
|
|
15
|
+
const INSTALL_URL = 'https://www.nushell.sh/book/installation.html';
|
|
16
|
+
class NushellRuntime {
|
|
17
|
+
/**
|
|
18
|
+
* Check if Nushell is installed on the system
|
|
19
|
+
*/
|
|
20
|
+
async checkInstalled() {
|
|
21
|
+
try {
|
|
22
|
+
await execAsync('nu --version');
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get the installed Nushell version
|
|
31
|
+
* Returns null if Nushell is not installed
|
|
32
|
+
*/
|
|
33
|
+
async getVersion() {
|
|
34
|
+
try {
|
|
35
|
+
const { stdout } = await execAsync('nu --version');
|
|
36
|
+
// Parse version from output like "0.95.0" or "nushell 0.95.0"
|
|
37
|
+
const versionMatch = stdout.trim().match(/(\d+\.\d+\.\d+)/);
|
|
38
|
+
return versionMatch ? versionMatch[1] : null;
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get comprehensive version information
|
|
46
|
+
*/
|
|
47
|
+
async getVersionInfo() {
|
|
48
|
+
const installed = await this.checkInstalled();
|
|
49
|
+
if (!installed) {
|
|
50
|
+
return {
|
|
51
|
+
installed: false,
|
|
52
|
+
version: null,
|
|
53
|
+
error: 'Nushell is not installed'
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const version = await this.getVersion();
|
|
57
|
+
if (!version) {
|
|
58
|
+
return {
|
|
59
|
+
installed: true,
|
|
60
|
+
version: null,
|
|
61
|
+
error: 'Unable to determine Nushell version'
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
installed: true,
|
|
66
|
+
version
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Get the official installation documentation URL
|
|
71
|
+
*/
|
|
72
|
+
getInstallationUrl() {
|
|
73
|
+
return INSTALL_URL;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Validate Nushell installation and return detailed status
|
|
77
|
+
*/
|
|
78
|
+
async validateRuntime() {
|
|
79
|
+
const versionInfo = await this.getVersionInfo();
|
|
80
|
+
if (!versionInfo.installed) {
|
|
81
|
+
return {
|
|
82
|
+
ready: false,
|
|
83
|
+
message: `Nushell is not installed. Please install Nushell from: ${INSTALL_URL}`,
|
|
84
|
+
versionInfo,
|
|
85
|
+
installationUrl: INSTALL_URL
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
if (!versionInfo.version) {
|
|
89
|
+
return {
|
|
90
|
+
ready: false,
|
|
91
|
+
message: `Unable to determine Nushell version. Please ensure Nushell is properly installed from: ${INSTALL_URL}`,
|
|
92
|
+
versionInfo,
|
|
93
|
+
installationUrl: INSTALL_URL
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
ready: true,
|
|
98
|
+
message: `Nushell ${versionInfo.version} is ready`,
|
|
99
|
+
versionInfo
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
exports.NushellRuntime = NushellRuntime;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform Operations Discovery
|
|
3
|
+
*
|
|
4
|
+
* Discovers available Nu shell script operations and maps user intent to operations
|
|
5
|
+
* using AI-powered parsing and matching.
|
|
6
|
+
*/
|
|
7
|
+
import { ClaudeIntegration } from './claude';
|
|
8
|
+
import { Logger } from './error-handling';
|
|
9
|
+
export interface OperationCommand {
|
|
10
|
+
name: string;
|
|
11
|
+
command: string[];
|
|
12
|
+
}
|
|
13
|
+
export interface Operation {
|
|
14
|
+
name: string;
|
|
15
|
+
description: string;
|
|
16
|
+
operations: OperationCommand[];
|
|
17
|
+
}
|
|
18
|
+
export interface MatchedOperation {
|
|
19
|
+
tool: string;
|
|
20
|
+
operation: string;
|
|
21
|
+
command: string[];
|
|
22
|
+
description: string;
|
|
23
|
+
}
|
|
24
|
+
export interface IntentMapping {
|
|
25
|
+
matched: boolean;
|
|
26
|
+
operation?: MatchedOperation;
|
|
27
|
+
reason?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface ParameterMetadata {
|
|
30
|
+
name: string;
|
|
31
|
+
type: 'string' | 'number' | 'boolean' | 'choice';
|
|
32
|
+
required: boolean;
|
|
33
|
+
description: string;
|
|
34
|
+
default?: any;
|
|
35
|
+
choices?: string[];
|
|
36
|
+
}
|
|
37
|
+
export interface PlatformSession {
|
|
38
|
+
sessionId: string;
|
|
39
|
+
intent: string;
|
|
40
|
+
matchedOperation: MatchedOperation;
|
|
41
|
+
parameters: ParameterMetadata[];
|
|
42
|
+
answers: Record<string, any>;
|
|
43
|
+
currentStep: 'collectParameters' | 'confirm' | 'execute' | 'complete';
|
|
44
|
+
createdAt: string;
|
|
45
|
+
updatedAt: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Discover available operations from Nu shell scripts using AI parsing
|
|
49
|
+
*/
|
|
50
|
+
export declare function discoverOperations(claudeIntegration: ClaudeIntegration, logger: Logger): Promise<Operation[]>;
|
|
51
|
+
/**
|
|
52
|
+
* Map user intent to a specific operation using AI
|
|
53
|
+
*/
|
|
54
|
+
export declare function mapIntentToOperation(intent: string, operations: Operation[], claudeIntegration: ClaudeIntegration, logger: Logger): Promise<IntentMapping>;
|
|
55
|
+
/**
|
|
56
|
+
* Get parameters for a specific operation using Nushell's structured JSON output
|
|
57
|
+
*/
|
|
58
|
+
export declare function getOperationParameters(command: string[], logger: Logger): Promise<ParameterMetadata[]>;
|
|
59
|
+
/**
|
|
60
|
+
* Create and persist a platform session
|
|
61
|
+
*/
|
|
62
|
+
export declare function createSession(sessionId: string, intent: string, matchedOperation: MatchedOperation, parameters: ParameterMetadata[], logger: Logger): Promise<PlatformSession>;
|
|
63
|
+
/**
|
|
64
|
+
* Load a platform session from file
|
|
65
|
+
*/
|
|
66
|
+
export declare function loadSession(sessionId: string, logger: Logger): PlatformSession | null;
|
|
67
|
+
/**
|
|
68
|
+
* Execute a platform operation with collected parameters
|
|
69
|
+
*/
|
|
70
|
+
export declare function executeOperation(session: PlatformSession, answers: Record<string, any>, logger: Logger): Promise<{
|
|
71
|
+
success: boolean;
|
|
72
|
+
message?: string;
|
|
73
|
+
error?: string;
|
|
74
|
+
missingParameters?: string[];
|
|
75
|
+
}>;
|
|
76
|
+
//# sourceMappingURL=platform-operations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform-operations.d.ts","sourceRoot":"","sources":["../../src/core/platform-operations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Platform Operations Discovery
|
|
4
|
+
*
|
|
5
|
+
* Discovers available Nu shell script operations and maps user intent to operations
|
|
6
|
+
* using AI-powered parsing and matching.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.discoverOperations = discoverOperations;
|
|
43
|
+
exports.mapIntentToOperation = mapIntentToOperation;
|
|
44
|
+
exports.getOperationParameters = getOperationParameters;
|
|
45
|
+
exports.createSession = createSession;
|
|
46
|
+
exports.loadSession = loadSession;
|
|
47
|
+
exports.executeOperation = executeOperation;
|
|
48
|
+
const child_process_1 = require("child_process");
|
|
49
|
+
const util_1 = require("util");
|
|
50
|
+
const fs = __importStar(require("fs"));
|
|
51
|
+
const path = __importStar(require("path"));
|
|
52
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
53
|
+
/**
|
|
54
|
+
* Get the scripts directory path, works in both development and installed npm package
|
|
55
|
+
*/
|
|
56
|
+
function getScriptsDir() {
|
|
57
|
+
// In CommonJS (after TypeScript compilation), __dirname is available
|
|
58
|
+
// Go up from dist/core/ to project root, then into scripts/
|
|
59
|
+
return path.join(__dirname, '..', '..', 'scripts');
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Strip markdown code blocks from AI response
|
|
63
|
+
*/
|
|
64
|
+
function stripMarkdownCodeBlocks(content) {
|
|
65
|
+
let jsonContent = content.trim();
|
|
66
|
+
if (jsonContent.startsWith('```json')) {
|
|
67
|
+
jsonContent = jsonContent.replace(/^```json\s*/, '').replace(/\s*```$/, '');
|
|
68
|
+
}
|
|
69
|
+
else if (jsonContent.startsWith('```')) {
|
|
70
|
+
jsonContent = jsonContent.replace(/^```\s*/, '').replace(/\s*```$/, '');
|
|
71
|
+
}
|
|
72
|
+
return jsonContent;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Discover available operations from Nu shell scripts using AI parsing
|
|
76
|
+
*/
|
|
77
|
+
async function discoverOperations(claudeIntegration, logger) {
|
|
78
|
+
try {
|
|
79
|
+
// Execute Nu script help command
|
|
80
|
+
const scriptPath = path.join(getScriptsDir(), 'dot.nu');
|
|
81
|
+
const { stdout, stderr } = await execAsync(`nu ${scriptPath} --help`);
|
|
82
|
+
if (stderr) {
|
|
83
|
+
logger.warn?.('Nu script help command produced stderr', { stderr });
|
|
84
|
+
}
|
|
85
|
+
// Load AI prompt template for parsing help output
|
|
86
|
+
const promptPath = path.join(process.cwd(), 'prompts', 'parse-script-operations.md');
|
|
87
|
+
const promptTemplate = fs.readFileSync(promptPath, 'utf8');
|
|
88
|
+
// Replace template variable with actual help output
|
|
89
|
+
const prompt = promptTemplate.replace('{helpOutput}', stdout);
|
|
90
|
+
// Send to Claude for AI-powered parsing
|
|
91
|
+
const response = await claudeIntegration.sendMessage(prompt);
|
|
92
|
+
// Strip markdown code blocks and parse JSON
|
|
93
|
+
const jsonContent = stripMarkdownCodeBlocks(response.content);
|
|
94
|
+
const operations = JSON.parse(jsonContent);
|
|
95
|
+
logger.info?.('Discovered operations from Nu scripts', {
|
|
96
|
+
count: operations.length
|
|
97
|
+
});
|
|
98
|
+
return operations;
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
logger.error?.('Failed to discover operations', error);
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Map user intent to a specific operation using AI
|
|
107
|
+
*/
|
|
108
|
+
async function mapIntentToOperation(intent, operations, claudeIntegration, logger) {
|
|
109
|
+
try {
|
|
110
|
+
// Load AI prompt template for intent mapping
|
|
111
|
+
const promptPath = path.join(process.cwd(), 'prompts', 'map-intent-to-operation.md');
|
|
112
|
+
const promptTemplate = fs.readFileSync(promptPath, 'utf8');
|
|
113
|
+
// Replace template variables
|
|
114
|
+
const prompt = promptTemplate
|
|
115
|
+
.replace('{intent}', intent)
|
|
116
|
+
.replace('{operations}', JSON.stringify(operations, null, 2));
|
|
117
|
+
// Send to Claude for AI-powered intent matching
|
|
118
|
+
const response = await claudeIntegration.sendMessage(prompt);
|
|
119
|
+
// Strip markdown code blocks and parse JSON
|
|
120
|
+
const jsonContent = stripMarkdownCodeBlocks(response.content);
|
|
121
|
+
const mapping = JSON.parse(jsonContent);
|
|
122
|
+
// Validate that AI returned required fields
|
|
123
|
+
if (mapping.matched && mapping.operation) {
|
|
124
|
+
if (!mapping.operation.command || !Array.isArray(mapping.operation.command)) {
|
|
125
|
+
throw new Error(`AI did not return valid command array. Response: ${JSON.stringify(mapping)}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
logger.info?.('Mapped user intent to operation', {
|
|
129
|
+
intent,
|
|
130
|
+
matched: mapping.matched,
|
|
131
|
+
operation: mapping.operation?.tool,
|
|
132
|
+
command: mapping.operation?.command
|
|
133
|
+
});
|
|
134
|
+
return mapping;
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
logger.error?.('Failed to map intent to operation', error);
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Get parameters for a specific operation using Nushell's structured JSON output
|
|
143
|
+
*/
|
|
144
|
+
async function getOperationParameters(command, logger) {
|
|
145
|
+
try {
|
|
146
|
+
// Build the full command name that Nushell expects
|
|
147
|
+
const commandName = `main ${command.join(' ')}`;
|
|
148
|
+
// Execute Nu script to get structured command metadata
|
|
149
|
+
const scriptPath = path.join(getScriptsDir(), 'dot.nu');
|
|
150
|
+
const nuCommand = `source ${scriptPath}; scope commands | where name == "${commandName}" | to json`;
|
|
151
|
+
const { stdout, stderr } = await execAsync(`nu -c '${nuCommand}'`);
|
|
152
|
+
if (stderr) {
|
|
153
|
+
logger.warn?.('Nu scope commands produced stderr', { stderr });
|
|
154
|
+
}
|
|
155
|
+
// Parse JSON response
|
|
156
|
+
const commands = JSON.parse(stdout);
|
|
157
|
+
if (!commands || commands.length === 0) {
|
|
158
|
+
logger.warn?.('No command metadata found', { commandName });
|
|
159
|
+
return [];
|
|
160
|
+
}
|
|
161
|
+
const commandMetadata = commands[0];
|
|
162
|
+
const signatures = commandMetadata.signatures?.any || [];
|
|
163
|
+
// Filter and transform parameter data
|
|
164
|
+
const parameters = [];
|
|
165
|
+
for (const param of signatures) {
|
|
166
|
+
// Skip input/output parameters
|
|
167
|
+
if (param.parameter_type === 'input' || param.parameter_type === 'output') {
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
// Skip help parameter
|
|
171
|
+
if (param.parameter_name === 'help') {
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
// Map Nushell types to our types
|
|
175
|
+
let type = 'string';
|
|
176
|
+
if (param.syntax_shape === 'bool') {
|
|
177
|
+
type = 'boolean';
|
|
178
|
+
}
|
|
179
|
+
else if (param.syntax_shape === 'int') {
|
|
180
|
+
type = 'number';
|
|
181
|
+
}
|
|
182
|
+
else if (param.syntax_shape === 'string') {
|
|
183
|
+
type = 'string';
|
|
184
|
+
}
|
|
185
|
+
// Determine if required (positional parameters are typically required)
|
|
186
|
+
const required = param.parameter_type === 'positional' && !param.is_optional;
|
|
187
|
+
parameters.push({
|
|
188
|
+
name: param.parameter_name,
|
|
189
|
+
type,
|
|
190
|
+
required,
|
|
191
|
+
description: param.description || '',
|
|
192
|
+
default: param.parameter_default
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
logger.info?.('Retrieved operation parameters', {
|
|
196
|
+
command: commandName,
|
|
197
|
+
parameterCount: parameters.length
|
|
198
|
+
});
|
|
199
|
+
return parameters;
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
logger.error?.('Failed to get operation parameters', error);
|
|
203
|
+
throw error;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Create and persist a platform session
|
|
208
|
+
*/
|
|
209
|
+
async function createSession(sessionId, intent, matchedOperation, parameters, logger) {
|
|
210
|
+
try {
|
|
211
|
+
const session = {
|
|
212
|
+
sessionId,
|
|
213
|
+
intent,
|
|
214
|
+
matchedOperation,
|
|
215
|
+
parameters,
|
|
216
|
+
answers: {},
|
|
217
|
+
currentStep: 'collectParameters',
|
|
218
|
+
createdAt: new Date().toISOString(),
|
|
219
|
+
updatedAt: new Date().toISOString()
|
|
220
|
+
};
|
|
221
|
+
// Ensure session directory exists
|
|
222
|
+
const sessionDir = path.join(process.cwd(), 'tmp', 'sessions', 'platform');
|
|
223
|
+
if (!fs.existsSync(sessionDir)) {
|
|
224
|
+
fs.mkdirSync(sessionDir, { recursive: true });
|
|
225
|
+
}
|
|
226
|
+
// Write session file
|
|
227
|
+
const sessionPath = path.join(sessionDir, `${sessionId}.json`);
|
|
228
|
+
fs.writeFileSync(sessionPath, JSON.stringify(session, null, 2), 'utf8');
|
|
229
|
+
logger.info?.('Created platform session', { sessionId, intent });
|
|
230
|
+
return session;
|
|
231
|
+
}
|
|
232
|
+
catch (error) {
|
|
233
|
+
logger.error?.('Failed to create platform session', error);
|
|
234
|
+
throw error;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Load a platform session from file
|
|
239
|
+
*/
|
|
240
|
+
function loadSession(sessionId, logger) {
|
|
241
|
+
try {
|
|
242
|
+
const sessionPath = path.join(process.cwd(), 'tmp', 'sessions', 'platform', `${sessionId}.json`);
|
|
243
|
+
if (!fs.existsSync(sessionPath)) {
|
|
244
|
+
logger.warn?.('Session file not found', { sessionId });
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
const sessionData = fs.readFileSync(sessionPath, 'utf8');
|
|
248
|
+
const session = JSON.parse(sessionData);
|
|
249
|
+
logger.info?.('Loaded platform session', { sessionId });
|
|
250
|
+
return session;
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
logger.error?.('Failed to load platform session', error);
|
|
254
|
+
throw error;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Execute a platform operation with collected parameters
|
|
259
|
+
*/
|
|
260
|
+
async function executeOperation(session, answers, logger) {
|
|
261
|
+
try {
|
|
262
|
+
// Validate required parameters
|
|
263
|
+
const missingRequired = session.parameters
|
|
264
|
+
.filter(p => p.required && !(p.name in answers))
|
|
265
|
+
.map(p => p.name);
|
|
266
|
+
if (missingRequired.length > 0) {
|
|
267
|
+
return {
|
|
268
|
+
success: false,
|
|
269
|
+
error: `Missing required parameters: ${missingRequired.join(', ')}`,
|
|
270
|
+
missingParameters: missingRequired
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
// Merge answers with defaults for optional parameters
|
|
274
|
+
const finalAnswers = { ...answers };
|
|
275
|
+
for (const param of session.parameters) {
|
|
276
|
+
if (!(param.name in finalAnswers) && param.default !== undefined) {
|
|
277
|
+
finalAnswers[param.name] = param.default;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
// Build Nu script command
|
|
281
|
+
const scriptPath = path.join(getScriptsDir(), 'dot.nu');
|
|
282
|
+
const command = session.matchedOperation.command;
|
|
283
|
+
// Build command arguments
|
|
284
|
+
const args = [];
|
|
285
|
+
for (const param of session.parameters) {
|
|
286
|
+
const value = finalAnswers[param.name];
|
|
287
|
+
if (value !== undefined) {
|
|
288
|
+
args.push(`--${param.name}`);
|
|
289
|
+
args.push(String(value));
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
const fullCommand = `nu ${scriptPath} ${command.join(' ')} ${args.join(' ')}`;
|
|
293
|
+
logger.info?.('Executing platform operation', {
|
|
294
|
+
sessionId: session.sessionId,
|
|
295
|
+
command: fullCommand
|
|
296
|
+
});
|
|
297
|
+
const { stdout, stderr } = await execAsync(fullCommand);
|
|
298
|
+
if (stderr) {
|
|
299
|
+
logger.warn?.('Operation produced stderr', { stderr });
|
|
300
|
+
}
|
|
301
|
+
logger.info?.('Platform operation completed', {
|
|
302
|
+
sessionId: session.sessionId,
|
|
303
|
+
stdout: stdout.substring(0, 500) // Log first 500 chars
|
|
304
|
+
});
|
|
305
|
+
return {
|
|
306
|
+
success: true,
|
|
307
|
+
message: `Successfully executed ${session.matchedOperation.tool} ${session.matchedOperation.operation}`
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
catch (error) {
|
|
311
|
+
logger.error?.('Failed to execute platform operation', error);
|
|
312
|
+
return {
|
|
313
|
+
success: false,
|
|
314
|
+
error: error instanceof Error ? error.message : String(error)
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/interfaces/mcp.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/interfaces/mcp.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AA8CtC,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,UAAU,GAAG,WAAW,CAAC;CACxC;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,UAAU,CAAC,CAAkC;IACrD,OAAO,CAAC,aAAa,CAAC,CAAgC;IACtD,OAAO,CAAC,YAAY,CAAmB;IACvC,OAAO,CAAC,aAAa,CAAgB;gBAEzB,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe;IAsCjD;;OAEG;IACH,OAAO,CAAC,YAAY;IAsBpB;;OAEG;IACH,OAAO,CAAC,aAAa;IA4HrB;;OAEG;IACH,OAAO,CAAC,eAAe;IAqCvB,OAAO,CAAC,iBAAiB;IAInB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAkBd,mBAAmB;YAMnB,kBAAkB;YAiFlB,gBAAgB;IAexB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB3B,OAAO,IAAI,OAAO;CAGnB"}
|
package/dist/interfaces/mcp.js
CHANGED
|
@@ -19,6 +19,7 @@ const version_1 = require("../tools/version");
|
|
|
19
19
|
const test_docs_1 = require("../tools/test-docs");
|
|
20
20
|
const organizational_data_1 = require("../tools/organizational-data");
|
|
21
21
|
const remediate_1 = require("../tools/remediate");
|
|
22
|
+
const build_platform_1 = require("../tools/build-platform");
|
|
22
23
|
const prompts_1 = require("../tools/prompts");
|
|
23
24
|
const rest_registry_1 = require("./rest-registry");
|
|
24
25
|
const rest_api_1 = require("./rest-api");
|
|
@@ -116,6 +117,12 @@ class MCPServer {
|
|
|
116
117
|
this.logger.info(`Processing ${remediate_1.REMEDIATE_TOOL_NAME} tool request`, { requestId });
|
|
117
118
|
return await (0, remediate_1.handleRemediateTool)(args);
|
|
118
119
|
}, 'Troubleshooting', ['remediation', 'troubleshooting', 'kubernetes', 'analysis']);
|
|
120
|
+
// Register buildPlatform tool
|
|
121
|
+
this.registerTool(build_platform_1.BUILD_PLATFORM_TOOL_NAME, build_platform_1.BUILD_PLATFORM_TOOL_DESCRIPTION, build_platform_1.BUILD_PLATFORM_TOOL_INPUT_SCHEMA, async (args) => {
|
|
122
|
+
const requestId = this.generateRequestId();
|
|
123
|
+
this.logger.info(`Processing ${build_platform_1.BUILD_PLATFORM_TOOL_NAME} tool request`, { requestId });
|
|
124
|
+
return await (0, build_platform_1.handleBuildPlatformTool)(args, this.dotAI, this.logger, requestId);
|
|
125
|
+
}, 'Platform', ['platform', 'kubernetes', 'installation', 'infrastructure']);
|
|
119
126
|
this.logger.info('Registered all tools with McpServer', {
|
|
120
127
|
tools: [
|
|
121
128
|
recommend_1.RECOMMEND_TOOL_NAME,
|
|
@@ -123,8 +130,9 @@ class MCPServer {
|
|
|
123
130
|
test_docs_1.TESTDOCS_TOOL_NAME,
|
|
124
131
|
organizational_data_1.ORGANIZATIONAL_DATA_TOOL_NAME,
|
|
125
132
|
remediate_1.REMEDIATE_TOOL_NAME,
|
|
133
|
+
build_platform_1.BUILD_PLATFORM_TOOL_NAME,
|
|
126
134
|
],
|
|
127
|
-
totalTools:
|
|
135
|
+
totalTools: 6,
|
|
128
136
|
});
|
|
129
137
|
}
|
|
130
138
|
/**
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build Platform Tool for MCP Server
|
|
3
|
+
*
|
|
4
|
+
* AI-powered tool that enables users to build and manage Kubernetes platforms
|
|
5
|
+
* through natural language intent. Handles script discovery, parameter collection,
|
|
6
|
+
* and execution transparently.
|
|
7
|
+
*
|
|
8
|
+
* Phase 1: Basic invocation and Nushell runtime validation
|
|
9
|
+
*/
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
import { Logger } from '../core/error-handling';
|
|
12
|
+
import { DotAI } from '../core/index';
|
|
13
|
+
export declare const BUILD_PLATFORM_TOOL_NAME = "buildPlatform";
|
|
14
|
+
export declare const BUILD_PLATFORM_TOOL_DESCRIPTION = "AI-powered platform operations tool for building and managing Kubernetes platforms. Use this to: (1) LIST/DISCOVER what tools and operations are available - use stage=\"list\" when user asks \"what can I install\", \"show available tools\", \"list platform capabilities\", (2) INSTALL/CREATE platform components like Argo CD, Crossplane, cert-manager, Kubernetes clusters through natural language intent. Handles tool installation, cluster creation, and platform configuration conversationally.";
|
|
15
|
+
export declare const BUILD_PLATFORM_TOOL_INPUT_SCHEMA: {
|
|
16
|
+
stage: z.ZodOptional<z.ZodString>;
|
|
17
|
+
intent: z.ZodOptional<z.ZodString>;
|
|
18
|
+
sessionId: z.ZodOptional<z.ZodString>;
|
|
19
|
+
answers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Main tool handler - Phase 1 & 2: Script discovery and intent mapping
|
|
23
|
+
*/
|
|
24
|
+
export declare function handleBuildPlatformTool(args: any, dotAI: DotAI, logger: Logger, requestId: string): Promise<any>;
|
|
25
|
+
//# sourceMappingURL=build-platform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-platform.d.ts","sourceRoot":"","sources":["../../src/tools/build-platform.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAGhD,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAItC,eAAO,MAAM,wBAAwB,kBAAkB,CAAC;AACxD,eAAO,MAAM,+BAA+B,mfAA2e,CAAC;AAuBxhB,eAAO,MAAM,gCAAgC;;;;;CAY5C,CAAC;AAEF;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,GAAG,EACT,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,GAAG,CAAC,CAgQd"}
|