@vfarcic/dot-ai 1.9.0 → 1.10.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/tools/generate-manifests.d.ts.map +1 -1
- package/dist/tools/generate-manifests.js +42 -10
- package/dist/tools/push-to-git.d.ts +43 -0
- package/dist/tools/push-to-git.d.ts.map +1 -0
- package/dist/tools/push-to-git.js +335 -0
- package/dist/tools/recommend.d.ts +20 -1
- package/dist/tools/recommend.d.ts.map +1 -1
- package/dist/tools/recommend.js +26 -5
- package/package.json +1 -1
- package/scripts/dot-ai.nu +3 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-manifests.d.ts","sourceRoot":"","sources":["../../src/tools/generate-manifests.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB,OAAO,EAAE,KAAK,EAA0B,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAgBhD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"generate-manifests.d.ts","sourceRoot":"","sources":["../../src/tools/generate-manifests.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB,OAAO,EAAE,KAAK,EAA0B,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAgBhD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAuH5D,eAAO,MAAM,2BAA2B,sBAAsB,CAAC;AAC/D,eAAO,MAAM,kCAAkC,+IAC+F,CAAC;AAG/I,eAAO,MAAM,mCAAmC;;;CAa/C,CAAC;AAs8BF;;;GAGG;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,EACjB,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC;IAAE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CAAC,CAkXxD"}
|
|
@@ -61,22 +61,33 @@ const request_context_1 = require("../interfaces/request-context");
|
|
|
61
61
|
const rbac_1 = require("../core/rbac");
|
|
62
62
|
// PRD #359: All helm operations via unified plugin registry
|
|
63
63
|
/**
|
|
64
|
-
* PRD #392 Milestone 2: Build agent instructions
|
|
65
|
-
*
|
|
66
|
-
*
|
|
64
|
+
* PRD #392 Milestone 2 + PRD #395: Build unified agent instructions.
|
|
65
|
+
* Presents save locally, deploy to cluster, and push to Git as equal options.
|
|
66
|
+
* RBAC determines whether deploy is available.
|
|
67
67
|
*/
|
|
68
|
-
async function
|
|
69
|
-
const
|
|
70
|
-
|
|
68
|
+
async function buildAgentInstructions(outputPath, outputFormat) {
|
|
69
|
+
const formatNote = outputFormat === 'helm'
|
|
70
|
+
? ' (Helm chart)'
|
|
71
|
+
: outputFormat === 'kustomize'
|
|
72
|
+
? ' (Kustomize overlay)'
|
|
73
|
+
: '';
|
|
74
|
+
const parts = [
|
|
75
|
+
`Manifests generated${formatNote}. Present the user with these options:`,
|
|
76
|
+
`1. **Save locally**: Write the files to "${outputPath}" — no further server call needed, you already have the file contents.`,
|
|
77
|
+
];
|
|
71
78
|
const identity = (0, request_context_1.getCurrentIdentity)();
|
|
72
79
|
const rbacResult = await (0, rbac_1.checkToolAccess)(identity, {
|
|
73
80
|
toolName: 'recommend',
|
|
74
81
|
verb: 'apply',
|
|
75
82
|
});
|
|
76
83
|
if (rbacResult.allowed) {
|
|
77
|
-
|
|
84
|
+
parts.push('2. **Deploy to cluster**: Call the recommend tool with stage: "deployManifests" to apply directly.');
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
parts.push("2. **Deploy to cluster**: Not available — requires 'apply' permission on 'recommend'.");
|
|
78
88
|
}
|
|
79
|
-
|
|
89
|
+
parts.push('3. **Push to Git** (GitOps): Call the recommend tool with stage: "pushToGit", providing repoUrl and targetPath. Recommended for Argo CD/Flux workflows.');
|
|
90
|
+
return parts.join('\n');
|
|
80
91
|
}
|
|
81
92
|
/**
|
|
82
93
|
* Ensure tmp directory exists
|
|
@@ -115,6 +126,24 @@ function buildHelmCommandForDisplay(chart, releaseName, namespace, valuesPath) {
|
|
|
115
126
|
return parts.join(' ');
|
|
116
127
|
}
|
|
117
128
|
const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
|
|
129
|
+
// PRD #395: Unified nextActions — save locally, deploy, or push to Git as equal options
|
|
130
|
+
const NEXT_ACTIONS = [
|
|
131
|
+
{
|
|
132
|
+
action: 'saveLocally',
|
|
133
|
+
description: 'Save files locally (no server call needed — files are in the response)',
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
action: 'deployManifests',
|
|
137
|
+
description: 'Apply directly to cluster',
|
|
138
|
+
stage: 'deployManifests',
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
action: 'pushToGit',
|
|
142
|
+
description: 'Push to Git repository for GitOps (Argo CD, Flux)',
|
|
143
|
+
stage: 'pushToGit',
|
|
144
|
+
requiredParams: ['repoUrl', 'targetPath'],
|
|
145
|
+
},
|
|
146
|
+
];
|
|
118
147
|
// Tool metadata for direct MCP registration
|
|
119
148
|
exports.GENERATEMANIFESTS_TOOL_NAME = 'generateManifests';
|
|
120
149
|
exports.GENERATEMANIFESTS_TOOL_DESCRIPTION = 'Generate final Kubernetes manifests from fully configured solution (ONLY after completing ALL stages: required, basic, advanced, and open)';
|
|
@@ -544,6 +573,7 @@ async function handleHelmGeneration(solution, solutionId, dotAI, logger, request
|
|
|
544
573
|
namespace: namespace,
|
|
545
574
|
validationAttempts: attempt,
|
|
546
575
|
timestamp: new Date().toISOString(),
|
|
576
|
+
nextActions: [NEXT_ACTIONS[0], NEXT_ACTIONS[1]], // saveLocally + deployManifests for Helm (pushToGit not yet supported)
|
|
547
577
|
...(visualizationUrl ? { visualizationUrl } : {}),
|
|
548
578
|
};
|
|
549
579
|
// Build content blocks - JSON for REST API, agent instruction for MCP agents
|
|
@@ -935,7 +965,8 @@ async function handleGenerateManifestsTool(args, dotAI, logger, requestId, plugi
|
|
|
935
965
|
validationAttempts: attempt,
|
|
936
966
|
packagingAttempts: packagingResult.attempts,
|
|
937
967
|
timestamp: new Date().toISOString(),
|
|
938
|
-
|
|
968
|
+
nextActions: NEXT_ACTIONS,
|
|
969
|
+
agentInstructions: await buildAgentInstructions(outputPath, outputFormat),
|
|
939
970
|
...(visualizationUrl ? { visualizationUrl } : {}),
|
|
940
971
|
};
|
|
941
972
|
// Build content blocks - JSON for REST API, agent instruction for MCP agents
|
|
@@ -977,7 +1008,8 @@ async function handleGenerateManifestsTool(args, dotAI, logger, requestId, plugi
|
|
|
977
1008
|
files: [{ relativePath: 'manifests.yaml', content: manifests }],
|
|
978
1009
|
validationAttempts: attempt,
|
|
979
1010
|
timestamp: new Date().toISOString(),
|
|
980
|
-
|
|
1011
|
+
nextActions: NEXT_ACTIONS,
|
|
1012
|
+
agentInstructions: await buildAgentInstructions(outputPath, outputFormat),
|
|
981
1013
|
...(visualizationUrl ? { visualizationUrl } : {}),
|
|
982
1014
|
};
|
|
983
1015
|
// Build content blocks - JSON for REST API, agent instruction for MCP agents
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Push to Git Tool - Push generated manifests to a Git repository
|
|
3
|
+
*
|
|
4
|
+
* PRD #395: Git Push Recommend Integration
|
|
5
|
+
*
|
|
6
|
+
* This stage allows users to push generated manifests directly to a Git
|
|
7
|
+
* repository, enabling GitOps workflows with Argo CD, Flux, etc.
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { DotAI } from '../core/index';
|
|
11
|
+
import { Logger } from '../core/error-handling';
|
|
12
|
+
import { GenericSessionManager } from '../core/generic-session-manager';
|
|
13
|
+
import type { SolutionData } from './recommend';
|
|
14
|
+
export declare const PUSHTOGIT_TOOL_NAME = "pushToGit";
|
|
15
|
+
export declare const PUSHTOGIT_TOOL_DESCRIPTION = "Push generated manifests to a Git repository for GitOps workflows (Argo CD, Flux). Use after generateManifests stage.";
|
|
16
|
+
export declare const PUSHTOGIT_TOOL_INPUT_SCHEMA: {
|
|
17
|
+
solutionId: z.ZodString;
|
|
18
|
+
repoUrl: z.ZodString;
|
|
19
|
+
targetPath: z.ZodString;
|
|
20
|
+
branch: z.ZodOptional<z.ZodString>;
|
|
21
|
+
commitMessage: z.ZodOptional<z.ZodString>;
|
|
22
|
+
authorName: z.ZodOptional<z.ZodString>;
|
|
23
|
+
authorEmail: z.ZodOptional<z.ZodString>;
|
|
24
|
+
interaction_id: z.ZodOptional<z.ZodString>;
|
|
25
|
+
};
|
|
26
|
+
interface PushToGitArgs {
|
|
27
|
+
solutionId: string;
|
|
28
|
+
repoUrl: string;
|
|
29
|
+
targetPath: string;
|
|
30
|
+
branch?: string;
|
|
31
|
+
commitMessage?: string;
|
|
32
|
+
authorName?: string;
|
|
33
|
+
authorEmail?: string;
|
|
34
|
+
interaction_id?: string;
|
|
35
|
+
}
|
|
36
|
+
export declare function handlePushToGitTool(args: PushToGitArgs, dotAI: DotAI, logger: Logger, requestId: string, sessionManager?: GenericSessionManager<SolutionData>): Promise<{
|
|
37
|
+
content: {
|
|
38
|
+
type: 'text';
|
|
39
|
+
text: string;
|
|
40
|
+
}[];
|
|
41
|
+
}>;
|
|
42
|
+
export {};
|
|
43
|
+
//# sourceMappingURL=push-to-git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push-to-git.d.ts","sourceRoot":"","sources":["../../src/tools/push-to-git.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAUxB,OAAO,EAAE,KAAK,EAA0B,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAShD,eAAO,MAAM,mBAAmB,cAAc,CAAC;AAC/C,eAAO,MAAM,0BAA0B,0HACkF,CAAC;AAE1H,eAAO,MAAM,2BAA2B;;;;;;;;;CAwBvC,CAAC;AAEF,UAAU,aAAa;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAaD,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,aAAa,EACnB,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,cAAc,CAAC,EAAE,qBAAqB,CAAC,YAAY,CAAC,GACnD,OAAO,CAAC;IAAE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CAAC,CAiUxD"}
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Push to Git Tool - Push generated manifests to a Git repository
|
|
4
|
+
*
|
|
5
|
+
* PRD #395: Git Push Recommend Integration
|
|
6
|
+
*
|
|
7
|
+
* This stage allows users to push generated manifests directly to a Git
|
|
8
|
+
* repository, enabling GitOps workflows with Argo CD, Flux, etc.
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
27
|
+
var ownKeys = function(o) {
|
|
28
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
29
|
+
var ar = [];
|
|
30
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
31
|
+
return ar;
|
|
32
|
+
};
|
|
33
|
+
return ownKeys(o);
|
|
34
|
+
};
|
|
35
|
+
return function (mod) {
|
|
36
|
+
if (mod && mod.__esModule) return mod;
|
|
37
|
+
var result = {};
|
|
38
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
39
|
+
__setModuleDefault(result, mod);
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
})();
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.PUSHTOGIT_TOOL_INPUT_SCHEMA = exports.PUSHTOGIT_TOOL_DESCRIPTION = exports.PUSHTOGIT_TOOL_NAME = void 0;
|
|
45
|
+
exports.handlePushToGitTool = handlePushToGitTool;
|
|
46
|
+
const zod_1 = require("zod");
|
|
47
|
+
const fs = __importStar(require("fs"));
|
|
48
|
+
const os = __importStar(require("os"));
|
|
49
|
+
const path = __importStar(require("path"));
|
|
50
|
+
const crypto_1 = require("crypto");
|
|
51
|
+
const error_handling_1 = require("../core/error-handling");
|
|
52
|
+
const index_1 = require("../core/index");
|
|
53
|
+
const generic_session_manager_1 = require("../core/generic-session-manager");
|
|
54
|
+
const git_utils_1 = require("../core/git-utils");
|
|
55
|
+
const visualization_1 = require("../core/visualization");
|
|
56
|
+
exports.PUSHTOGIT_TOOL_NAME = 'pushToGit';
|
|
57
|
+
exports.PUSHTOGIT_TOOL_DESCRIPTION = 'Push generated manifests to a Git repository for GitOps workflows (Argo CD, Flux). Use after generateManifests stage.';
|
|
58
|
+
exports.PUSHTOGIT_TOOL_INPUT_SCHEMA = {
|
|
59
|
+
solutionId: zod_1.z
|
|
60
|
+
.string()
|
|
61
|
+
.regex(/^sol-\d+-[a-f0-9]{8}$/)
|
|
62
|
+
.describe('The solution ID to push manifests for'),
|
|
63
|
+
repoUrl: zod_1.z.string().url().describe('Git repository URL (HTTPS)'),
|
|
64
|
+
targetPath: zod_1.z
|
|
65
|
+
.string()
|
|
66
|
+
.describe('Path within repository where manifests will be stored (e.g., "apps/postgresql/")'),
|
|
67
|
+
branch: zod_1.z.string().optional().describe('Git branch (default: main)'),
|
|
68
|
+
commitMessage: zod_1.z
|
|
69
|
+
.string()
|
|
70
|
+
.optional()
|
|
71
|
+
.describe('Commit message (default: "Add {resource} deployment")'),
|
|
72
|
+
authorName: zod_1.z.string().optional().describe('Git author name'),
|
|
73
|
+
authorEmail: zod_1.z.string().optional().describe('Git author email'),
|
|
74
|
+
interaction_id: zod_1.z
|
|
75
|
+
.string()
|
|
76
|
+
.optional()
|
|
77
|
+
.describe('INTERNAL ONLY - Do not populate. Used for evaluation dataset generation.'),
|
|
78
|
+
};
|
|
79
|
+
function sanitizeRelativePath(relativePath) {
|
|
80
|
+
if (relativePath.startsWith('/')) {
|
|
81
|
+
throw new Error('Relative path cannot be absolute');
|
|
82
|
+
}
|
|
83
|
+
const normalized = path.posix.normalize(relativePath);
|
|
84
|
+
if (normalized.startsWith('..') || path.posix.isAbsolute(normalized)) {
|
|
85
|
+
throw new Error('Relative path cannot escape target directory');
|
|
86
|
+
}
|
|
87
|
+
return normalized;
|
|
88
|
+
}
|
|
89
|
+
async function handlePushToGitTool(args, dotAI, logger, requestId, sessionManager) {
|
|
90
|
+
return await error_handling_1.ErrorHandler.withErrorHandling(async () => {
|
|
91
|
+
logger.info('Handling pushToGit request', {
|
|
92
|
+
requestId,
|
|
93
|
+
solutionId: args.solutionId,
|
|
94
|
+
repoUrl: (0, git_utils_1.scrubCredentials)(args.repoUrl),
|
|
95
|
+
targetPath: args.targetPath,
|
|
96
|
+
branch: args.branch,
|
|
97
|
+
});
|
|
98
|
+
const sm = sessionManager || new generic_session_manager_1.GenericSessionManager('sol');
|
|
99
|
+
const session = sm.getSession(args.solutionId);
|
|
100
|
+
if (!session) {
|
|
101
|
+
throw error_handling_1.ErrorHandler.createError(error_handling_1.ErrorCategory.VALIDATION, error_handling_1.ErrorSeverity.HIGH, `Solution not found: ${args.solutionId}`, {
|
|
102
|
+
operation: 'push_to_git',
|
|
103
|
+
component: 'PushToGitTool',
|
|
104
|
+
requestId,
|
|
105
|
+
input: { solutionId: args.solutionId },
|
|
106
|
+
suggestedActions: [
|
|
107
|
+
'Verify the solution ID is correct',
|
|
108
|
+
'Ensure generateManifests stage was completed first',
|
|
109
|
+
'Check that the session has not expired',
|
|
110
|
+
],
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
const solution = session.data;
|
|
114
|
+
if (!solution.generatedManifests) {
|
|
115
|
+
throw error_handling_1.ErrorHandler.createError(error_handling_1.ErrorCategory.VALIDATION, error_handling_1.ErrorSeverity.HIGH, 'No manifests found. Run generateManifests stage first.', {
|
|
116
|
+
operation: 'push_to_git',
|
|
117
|
+
component: 'PushToGitTool',
|
|
118
|
+
requestId,
|
|
119
|
+
input: { solutionId: args.solutionId },
|
|
120
|
+
suggestedActions: [
|
|
121
|
+
'Call recommend tool with stage: generateManifests first',
|
|
122
|
+
'Ensure the solution was fully configured',
|
|
123
|
+
],
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
if (solution.generatedManifests.type === 'helm') {
|
|
127
|
+
throw error_handling_1.ErrorHandler.createError(error_handling_1.ErrorCategory.VALIDATION, error_handling_1.ErrorSeverity.HIGH, 'GitOps push for Helm charts is not yet supported. Use the deployManifests stage to install directly, or wait for a future release with Argo CD Application / Flux HelmRelease support.', {
|
|
128
|
+
operation: 'push_to_git',
|
|
129
|
+
component: 'PushToGitTool',
|
|
130
|
+
requestId,
|
|
131
|
+
input: { solutionId: args.solutionId },
|
|
132
|
+
suggestedActions: [
|
|
133
|
+
'Use deployManifests stage to install Helm chart directly',
|
|
134
|
+
'Wait for future release with GitOps Helm support (Argo CD Application / Flux HelmRelease)',
|
|
135
|
+
],
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
const authConfig = (0, git_utils_1.getGitAuthConfigFromEnv)();
|
|
139
|
+
if (!authConfig.pat && !authConfig.githubApp) {
|
|
140
|
+
throw error_handling_1.ErrorHandler.createError(error_handling_1.ErrorCategory.CONFIGURATION, error_handling_1.ErrorSeverity.HIGH, 'No Git authentication configured. Set DOT_AI_GIT_TOKEN or configure GitHub App.', {
|
|
141
|
+
operation: 'push_to_git',
|
|
142
|
+
component: 'PushToGitTool',
|
|
143
|
+
requestId,
|
|
144
|
+
input: { repoUrl: (0, git_utils_1.scrubCredentials)(args.repoUrl) },
|
|
145
|
+
suggestedActions: [
|
|
146
|
+
'Set DOT_AI_GIT_TOKEN environment variable with a valid PAT',
|
|
147
|
+
'Or configure GitHub App authentication (GITHUB_APP_ENABLED, GITHUB_APP_ID, GITHUB_APP_PRIVATE_KEY)',
|
|
148
|
+
],
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
const branch = args.branch || 'main';
|
|
152
|
+
const defaultCommitMessage = `Add ${solution.intent || 'deployment'} manifests`;
|
|
153
|
+
const commitMessage = args.commitMessage || defaultCommitMessage;
|
|
154
|
+
const rawTargetPath = args.targetPath.trim();
|
|
155
|
+
if (rawTargetPath === '' ||
|
|
156
|
+
rawTargetPath.startsWith('/') ||
|
|
157
|
+
rawTargetPath.startsWith('~') ||
|
|
158
|
+
rawTargetPath.includes('\\') ||
|
|
159
|
+
rawTargetPath.includes('..')) {
|
|
160
|
+
throw error_handling_1.ErrorHandler.createError(error_handling_1.ErrorCategory.VALIDATION, error_handling_1.ErrorSeverity.HIGH, 'Invalid target path: use a relative repository path without "/", "~", "\\", or ".."', {
|
|
161
|
+
operation: 'push_to_git',
|
|
162
|
+
component: 'PushToGitTool',
|
|
163
|
+
requestId,
|
|
164
|
+
input: { targetPath: args.targetPath },
|
|
165
|
+
suggestedActions: [
|
|
166
|
+
'Use a relative repository path such as "apps/postgresql"',
|
|
167
|
+
],
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
const targetPath = rawTargetPath.replace(/\/+$/, '');
|
|
171
|
+
const tmpDir = path.join(os.tmpdir(), `dot-ai-git-${args.solutionId}-${(0, crypto_1.randomUUID)()}`);
|
|
172
|
+
logger.info('Cloning repository', {
|
|
173
|
+
repoUrl: (0, git_utils_1.scrubCredentials)(args.repoUrl),
|
|
174
|
+
branch,
|
|
175
|
+
tmpDir,
|
|
176
|
+
});
|
|
177
|
+
try {
|
|
178
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
179
|
+
try {
|
|
180
|
+
await (0, git_utils_1.cloneRepo)(args.repoUrl, tmpDir, { branch, depth: 1 });
|
|
181
|
+
}
|
|
182
|
+
catch (cloneError) {
|
|
183
|
+
const errorMessage = cloneError instanceof Error
|
|
184
|
+
? cloneError.message
|
|
185
|
+
: String(cloneError);
|
|
186
|
+
logger.error('Failed to clone repository', cloneError, {
|
|
187
|
+
repoUrl: (0, git_utils_1.scrubCredentials)(args.repoUrl),
|
|
188
|
+
branch,
|
|
189
|
+
});
|
|
190
|
+
throw error_handling_1.ErrorHandler.createError(error_handling_1.ErrorCategory.NETWORK, error_handling_1.ErrorSeverity.HIGH, `Failed to clone repository: ${errorMessage}`, {
|
|
191
|
+
operation: 'push_to_git',
|
|
192
|
+
component: 'PushToGitTool',
|
|
193
|
+
requestId,
|
|
194
|
+
input: { repoUrl: (0, git_utils_1.scrubCredentials)(args.repoUrl), branch },
|
|
195
|
+
suggestedActions: [
|
|
196
|
+
'Verify the repository URL is correct',
|
|
197
|
+
'Check that the branch exists',
|
|
198
|
+
'Ensure your token has read access to the repository',
|
|
199
|
+
],
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
const files = [];
|
|
203
|
+
// Handle raw/kustomize manifests (Helm is rejected earlier in validation)
|
|
204
|
+
const manifestFiles = solution.generatedManifests.files;
|
|
205
|
+
if (manifestFiles && manifestFiles.length > 0) {
|
|
206
|
+
for (const file of manifestFiles) {
|
|
207
|
+
const sanitizedPath = sanitizeRelativePath(file.relativePath);
|
|
208
|
+
files.push({
|
|
209
|
+
path: path.posix.join(targetPath, sanitizedPath),
|
|
210
|
+
content: file.content,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (files.length === 0) {
|
|
215
|
+
throw error_handling_1.ErrorHandler.createError(error_handling_1.ErrorCategory.VALIDATION, error_handling_1.ErrorSeverity.HIGH, 'No files to push. Manifests may be empty or missing content.', {
|
|
216
|
+
operation: 'push_to_git',
|
|
217
|
+
component: 'PushToGitTool',
|
|
218
|
+
requestId,
|
|
219
|
+
input: { solutionId: args.solutionId },
|
|
220
|
+
suggestedActions: [
|
|
221
|
+
'Verify generateManifests completed successfully',
|
|
222
|
+
'Check that manifests contain content',
|
|
223
|
+
],
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
logger.info('Pushing files to repository', {
|
|
227
|
+
fileCount: files.length,
|
|
228
|
+
targetPath,
|
|
229
|
+
branch,
|
|
230
|
+
});
|
|
231
|
+
const filesPreview = files.map(f => ({
|
|
232
|
+
path: f.path,
|
|
233
|
+
size: f.content.length,
|
|
234
|
+
lines: f.content.split('\n').length,
|
|
235
|
+
}));
|
|
236
|
+
let pushResult;
|
|
237
|
+
try {
|
|
238
|
+
pushResult = await (0, git_utils_1.pushRepo)(tmpDir, files, commitMessage, {
|
|
239
|
+
branch,
|
|
240
|
+
author: args.authorName
|
|
241
|
+
? {
|
|
242
|
+
name: args.authorName,
|
|
243
|
+
email: args.authorEmail || 'dot-ai@users.noreply.github.com',
|
|
244
|
+
}
|
|
245
|
+
: undefined,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
catch (pushError) {
|
|
249
|
+
const errorMessage = pushError instanceof Error ? pushError.message : String(pushError);
|
|
250
|
+
logger.error('Failed to push to repository', pushError, {
|
|
251
|
+
repoUrl: (0, git_utils_1.scrubCredentials)(args.repoUrl),
|
|
252
|
+
branch,
|
|
253
|
+
targetPath,
|
|
254
|
+
});
|
|
255
|
+
throw error_handling_1.ErrorHandler.createError(error_handling_1.ErrorCategory.NETWORK, error_handling_1.ErrorSeverity.HIGH, `Failed to push to repository: ${errorMessage}`, {
|
|
256
|
+
operation: 'push_to_git',
|
|
257
|
+
component: 'PushToGitTool',
|
|
258
|
+
requestId,
|
|
259
|
+
input: {
|
|
260
|
+
repoUrl: (0, git_utils_1.scrubCredentials)(args.repoUrl),
|
|
261
|
+
branch,
|
|
262
|
+
targetPath,
|
|
263
|
+
},
|
|
264
|
+
suggestedActions: [
|
|
265
|
+
'Ensure your token has write access to the repository',
|
|
266
|
+
'Check for merge conflicts (pull latest changes first)',
|
|
267
|
+
'Verify the branch exists or can be created',
|
|
268
|
+
],
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
sm.updateSession(args.solutionId, {
|
|
272
|
+
stage: 'pushed',
|
|
273
|
+
gitPush: {
|
|
274
|
+
repoUrl: (0, git_utils_1.scrubCredentials)(args.repoUrl),
|
|
275
|
+
path: targetPath,
|
|
276
|
+
branch: pushResult.branch,
|
|
277
|
+
commitSha: pushResult.commitSha,
|
|
278
|
+
pushedAt: new Date().toISOString(),
|
|
279
|
+
},
|
|
280
|
+
});
|
|
281
|
+
const visualizationUrl = (0, visualization_1.getVisualizationUrl)(args.solutionId);
|
|
282
|
+
const response = {
|
|
283
|
+
success: true,
|
|
284
|
+
status: 'manifests_pushed',
|
|
285
|
+
solutionId: args.solutionId,
|
|
286
|
+
gitPush: {
|
|
287
|
+
repoUrl: (0, git_utils_1.scrubCredentials)(args.repoUrl),
|
|
288
|
+
path: targetPath,
|
|
289
|
+
branch: pushResult.branch,
|
|
290
|
+
commitSha: pushResult.commitSha,
|
|
291
|
+
filesPushed: pushResult.filesAdded,
|
|
292
|
+
pushedAt: new Date().toISOString(),
|
|
293
|
+
},
|
|
294
|
+
filesPreview,
|
|
295
|
+
gitopsMessage: `Manifests pushed successfully. Your GitOps controller (Argo CD/Flux) will sync these changes automatically.`,
|
|
296
|
+
timestamp: new Date().toISOString(),
|
|
297
|
+
...(visualizationUrl ? { visualizationUrl } : {}),
|
|
298
|
+
};
|
|
299
|
+
logger.info('Push to Git completed successfully', {
|
|
300
|
+
solutionId: args.solutionId,
|
|
301
|
+
commitSha: pushResult.commitSha,
|
|
302
|
+
branch: pushResult.branch,
|
|
303
|
+
});
|
|
304
|
+
const content = [
|
|
305
|
+
{
|
|
306
|
+
type: 'text',
|
|
307
|
+
text: JSON.stringify(response, null, 2),
|
|
308
|
+
},
|
|
309
|
+
];
|
|
310
|
+
const agentDisplayBlock = (0, index_1.buildAgentDisplayBlock)({ visualizationUrl });
|
|
311
|
+
if (agentDisplayBlock) {
|
|
312
|
+
content.push(agentDisplayBlock);
|
|
313
|
+
}
|
|
314
|
+
return { content };
|
|
315
|
+
}
|
|
316
|
+
finally {
|
|
317
|
+
try {
|
|
318
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
319
|
+
}
|
|
320
|
+
catch (cleanupError) {
|
|
321
|
+
logger.warn('Failed to cleanup temporary git directory', {
|
|
322
|
+
tmpDir,
|
|
323
|
+
error: cleanupError instanceof Error
|
|
324
|
+
? cleanupError.message
|
|
325
|
+
: String(cleanupError),
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}, {
|
|
330
|
+
operation: 'push_to_git',
|
|
331
|
+
component: 'PushToGitTool',
|
|
332
|
+
requestId,
|
|
333
|
+
input: { ...args, repoUrl: (0, git_utils_1.scrubCredentials)(args.repoUrl) },
|
|
334
|
+
});
|
|
335
|
+
}
|
|
@@ -16,11 +16,17 @@ export declare const RECOMMEND_TOOL_INPUT_SCHEMA: {
|
|
|
16
16
|
solutionId: z.ZodOptional<z.ZodString>;
|
|
17
17
|
answers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
18
18
|
timeout: z.ZodOptional<z.ZodNumber>;
|
|
19
|
+
repoUrl: z.ZodOptional<z.ZodString>;
|
|
20
|
+
targetPath: z.ZodOptional<z.ZodString>;
|
|
21
|
+
branch: z.ZodOptional<z.ZodString>;
|
|
22
|
+
commitMessage: z.ZodOptional<z.ZodString>;
|
|
23
|
+
authorName: z.ZodOptional<z.ZodString>;
|
|
24
|
+
authorEmail: z.ZodOptional<z.ZodString>;
|
|
19
25
|
interaction_id: z.ZodOptional<z.ZodString>;
|
|
20
26
|
};
|
|
21
27
|
export interface SolutionData {
|
|
22
28
|
toolName: 'recommend';
|
|
23
|
-
stage?: 'solutions' | 'questions' | 'manifests' | 'deployed';
|
|
29
|
+
stage?: 'solutions' | 'questions' | 'manifests' | 'pushed' | 'deployed';
|
|
24
30
|
intent: string;
|
|
25
31
|
type: string;
|
|
26
32
|
score: number;
|
|
@@ -67,6 +73,13 @@ export interface SolutionData {
|
|
|
67
73
|
validationAttempts?: number;
|
|
68
74
|
packagingAttempts?: number;
|
|
69
75
|
};
|
|
76
|
+
gitPush?: {
|
|
77
|
+
repoUrl: string;
|
|
78
|
+
path: string;
|
|
79
|
+
branch: string;
|
|
80
|
+
commitSha?: string;
|
|
81
|
+
pushedAt?: string;
|
|
82
|
+
};
|
|
70
83
|
currentQuestionStage?: 'required' | 'basic' | 'advanced' | 'open';
|
|
71
84
|
nextQuestionStage?: string | null;
|
|
72
85
|
allSolutions?: Array<{
|
|
@@ -95,6 +108,12 @@ interface RecommendToolArgs {
|
|
|
95
108
|
solutionId?: string;
|
|
96
109
|
answers?: Record<string, unknown>;
|
|
97
110
|
timeout?: number;
|
|
111
|
+
repoUrl?: string;
|
|
112
|
+
targetPath?: string;
|
|
113
|
+
branch?: string;
|
|
114
|
+
commitMessage?: string;
|
|
115
|
+
authorName?: string;
|
|
116
|
+
authorEmail?: string;
|
|
98
117
|
interaction_id?: string;
|
|
99
118
|
}
|
|
100
119
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recommend.d.ts","sourceRoot":"","sources":["../../src/tools/recommend.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAuB,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,KAAK,EAA0B,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"recommend.d.ts","sourceRoot":"","sources":["../../src/tools/recommend.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/recommend.js
CHANGED
|
@@ -14,6 +14,7 @@ const choose_solution_1 = require("./choose-solution");
|
|
|
14
14
|
const answer_question_1 = require("./answer-question");
|
|
15
15
|
const generate_manifests_1 = require("./generate-manifests");
|
|
16
16
|
const deploy_manifests_1 = require("./deploy-manifests");
|
|
17
|
+
const push_to_git_1 = require("./push-to-git");
|
|
17
18
|
const shared_prompt_loader_1 = require("../core/shared-prompt-loader");
|
|
18
19
|
const request_context_1 = require("../interfaces/request-context");
|
|
19
20
|
const rbac_1 = require("../core/rbac");
|
|
@@ -27,15 +28,22 @@ exports.RECOMMEND_TOOL_NAME = 'recommend';
|
|
|
27
28
|
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.';
|
|
28
29
|
// Zod schema for MCP registration (unified tool with stage routing)
|
|
29
30
|
exports.RECOMMEND_TOOL_INPUT_SCHEMA = {
|
|
30
|
-
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.'),
|
|
31
|
+
stage: zod_1.z.string().optional().describe('Deployment workflow stage: "recommend" (default), "chooseSolution", "answerQuestion:required", "answerQuestion:basic", "answerQuestion:advanced", "answerQuestion:open", "generateManifests", "pushToGit", "deployManifests". Defaults to "recommend" if omitted.'),
|
|
31
32
|
intent: zod_1.z.string().min(1).max(1000).optional().describe('What the user wants to deploy, create, setup, install, or run on Kubernetes. Examples: "deploy web application", "create PostgreSQL database", "setup Redis cache", "install Prometheus monitoring", "configure Ingress controller", "provision storage volumes", "launch MongoDB operator", "run Node.js API", "setup CI/CD pipeline", "create load balancer", "install Grafana dashboard", "deploy React frontend"'),
|
|
32
33
|
final: zod_1.z.boolean().optional().describe('Set to true to skip intent clarification and proceed directly with recommendations. If false or omitted, the tool will analyze the intent and provide clarification questions to help improve recommendation quality.'),
|
|
33
34
|
// Parameters for chooseSolution stage
|
|
34
|
-
solutionId: zod_1.z.string().optional().describe('Solution ID for chooseSolution, answerQuestion, generateManifests, and deployManifests stages'),
|
|
35
|
+
solutionId: zod_1.z.string().optional().describe('Solution ID for chooseSolution, answerQuestion, generateManifests, pushToGit, and deployManifests stages'),
|
|
35
36
|
// Parameters for answerQuestion stage (stage parameter contains the config stage like "answerQuestion:required")
|
|
36
37
|
answers: zod_1.z.record(zod_1.z.string(), zod_1.z.any()).optional().describe('User answers for answerQuestion stage'),
|
|
37
38
|
// Parameters for deployManifests stage
|
|
38
39
|
timeout: zod_1.z.number().optional().describe('Deployment timeout in seconds for deployManifests stage'),
|
|
40
|
+
// Parameters for pushToGit stage (PRD #395)
|
|
41
|
+
repoUrl: zod_1.z.string().url().optional().describe('Git repository URL for pushToGit stage (HTTPS)'),
|
|
42
|
+
targetPath: zod_1.z.string().optional().describe('Path within repository for pushToGit stage (e.g., "apps/postgresql/")'),
|
|
43
|
+
branch: zod_1.z.string().optional().describe('Git branch for pushToGit stage (default: main)'),
|
|
44
|
+
commitMessage: zod_1.z.string().optional().describe('Commit message for pushToGit stage'),
|
|
45
|
+
authorName: zod_1.z.string().optional().describe('Git author name for pushToGit stage'),
|
|
46
|
+
authorEmail: zod_1.z.string().optional().describe('Git author email for pushToGit stage'),
|
|
39
47
|
interaction_id: zod_1.z.string().optional().describe('INTERNAL ONLY - Do not populate. Used for evaluation dataset generation.')
|
|
40
48
|
};
|
|
41
49
|
/**
|
|
@@ -72,6 +80,9 @@ async function handleRecommendTool(args, dotAI, logger, requestId, pluginManager
|
|
|
72
80
|
// Stage-based routing: extract stage and route to appropriate handler
|
|
73
81
|
const stage = args.stage || 'recommend'; // Default to 'recommend' if not specified
|
|
74
82
|
logger.debug('Handling recommend request with stage routing', { requestId, stage, intent: args?.intent });
|
|
83
|
+
// Initialize session manager (shared across stages)
|
|
84
|
+
const sessionManager = new generic_session_manager_1.GenericSessionManager('sol');
|
|
85
|
+
logger.debug('Session manager initialized', { requestId });
|
|
75
86
|
// Route to appropriate handler based on stage
|
|
76
87
|
if (stage === 'chooseSolution') {
|
|
77
88
|
return await (0, choose_solution_1.handleChooseSolutionTool)(args, dotAI, logger, requestId);
|
|
@@ -117,13 +128,23 @@ async function handleRecommendTool(args, dotAI, logger, requestId, pluginManager
|
|
|
117
128
|
// PRD #359: Uses unified plugin registry for kubectl operations
|
|
118
129
|
return await (0, deploy_manifests_1.handleDeployManifestsTool)(args, dotAI, logger, requestId);
|
|
119
130
|
}
|
|
131
|
+
// PRD #395: pushToGit stage for GitOps workflows
|
|
132
|
+
if (stage === 'pushToGit') {
|
|
133
|
+
return await (0, push_to_git_1.handlePushToGitTool)({
|
|
134
|
+
solutionId: args.solutionId || '',
|
|
135
|
+
repoUrl: args.repoUrl || '',
|
|
136
|
+
targetPath: args.targetPath || '',
|
|
137
|
+
branch: args.branch,
|
|
138
|
+
commitMessage: args.commitMessage,
|
|
139
|
+
authorName: args.authorName,
|
|
140
|
+
authorEmail: args.authorEmail,
|
|
141
|
+
interaction_id: args.interaction_id,
|
|
142
|
+
}, dotAI, logger, requestId, sessionManager);
|
|
143
|
+
}
|
|
120
144
|
// Default: recommend stage (original recommend logic)
|
|
121
145
|
// Input validation is handled automatically by MCP SDK with Zod schema
|
|
122
146
|
// args are already validated and typed when we reach this point
|
|
123
147
|
// AI provider is already initialized and validated in dotAI.ai
|
|
124
|
-
// Initialize session manager
|
|
125
|
-
const sessionManager = new generic_session_manager_1.GenericSessionManager('sol');
|
|
126
|
-
logger.debug('Session manager initialized', { requestId });
|
|
127
148
|
logger.info('Starting resource recommendation process', {
|
|
128
149
|
requestId,
|
|
129
150
|
intent: args.intent,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vfarcic/dot-ai",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.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",
|
package/scripts/dot-ai.nu
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
# > main apply dot-ai --provider openai --model gpt-4o
|
|
8
8
|
# > main apply dot-ai --enable-tracing true
|
|
9
9
|
def "main apply dot-ai" [
|
|
10
|
-
--stack-version = "0.
|
|
10
|
+
--stack-version = "0.44.0",
|
|
11
11
|
--anthropic-api-key = "",
|
|
12
12
|
--openai-api-key = "",
|
|
13
13
|
--auth-token = "my-secret-token",
|
|
@@ -71,6 +71,8 @@ def "main apply dot-ai" [
|
|
|
71
71
|
# Update .env with auth token for MCP clients
|
|
72
72
|
$"export DOT_AI_AUTH_TOKEN=($auth_token)\n" | save --append .env
|
|
73
73
|
|
|
74
|
+
$"export DOT_AI_URL=http://($host)\n" | save --append .env
|
|
75
|
+
|
|
74
76
|
if $enable_tracing {
|
|
75
77
|
print $"Tracing enabled: Traces will be sent to (ansi yellow_bold)Jaeger in observability namespace(ansi reset)"
|
|
76
78
|
}
|