@vibescope/mcp-server 0.2.0 → 0.2.2
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 +60 -7
- package/dist/api-client.d.ts +251 -1
- package/dist/api-client.js +82 -3
- package/dist/handlers/blockers.js +9 -8
- package/dist/handlers/bodies-of-work.js +96 -63
- package/dist/handlers/connectors.d.ts +45 -0
- package/dist/handlers/connectors.js +183 -0
- package/dist/handlers/cost.d.ts +10 -0
- package/dist/handlers/cost.js +112 -50
- package/dist/handlers/decisions.js +32 -19
- package/dist/handlers/deployment.js +144 -122
- package/dist/handlers/discovery.d.ts +7 -0
- package/dist/handlers/discovery.js +96 -7
- package/dist/handlers/fallback.js +29 -23
- package/dist/handlers/file-checkouts.d.ts +20 -0
- package/dist/handlers/file-checkouts.js +133 -0
- package/dist/handlers/findings.d.ts +6 -0
- package/dist/handlers/findings.js +96 -40
- package/dist/handlers/git-issues.js +40 -36
- package/dist/handlers/ideas.js +49 -31
- package/dist/handlers/index.d.ts +3 -0
- package/dist/handlers/index.js +9 -0
- package/dist/handlers/milestones.js +39 -32
- package/dist/handlers/organizations.js +99 -91
- package/dist/handlers/progress.js +24 -13
- package/dist/handlers/project.js +68 -28
- package/dist/handlers/requests.js +18 -14
- package/dist/handlers/roles.d.ts +18 -0
- package/dist/handlers/roles.js +130 -0
- package/dist/handlers/session.js +58 -17
- package/dist/handlers/sprints.js +93 -81
- package/dist/handlers/tasks.d.ts +2 -0
- package/dist/handlers/tasks.js +189 -91
- package/dist/handlers/types.d.ts +64 -2
- package/dist/handlers/types.js +48 -1
- package/dist/handlers/validation.js +21 -17
- package/dist/index.js +7 -2716
- package/dist/token-tracking.d.ts +74 -0
- package/dist/token-tracking.js +122 -0
- package/dist/tools.js +685 -9
- package/dist/utils.d.ts +5 -0
- package/dist/utils.js +17 -0
- package/docs/TOOLS.md +2053 -0
- package/package.json +4 -1
- package/scripts/generate-docs.ts +212 -0
- package/src/api-client.test.ts +718 -0
- package/src/api-client.ts +320 -6
- package/src/handlers/__test-setup__.ts +16 -0
- package/src/handlers/blockers.test.ts +31 -19
- package/src/handlers/blockers.ts +9 -8
- package/src/handlers/bodies-of-work.test.ts +55 -32
- package/src/handlers/bodies-of-work.ts +115 -115
- package/src/handlers/connectors.test.ts +834 -0
- package/src/handlers/connectors.ts +229 -0
- package/src/handlers/cost.test.ts +34 -44
- package/src/handlers/cost.ts +136 -85
- package/src/handlers/decisions.test.ts +37 -27
- package/src/handlers/decisions.ts +35 -30
- package/src/handlers/deployment.ts +180 -208
- package/src/handlers/discovery.test.ts +4 -5
- package/src/handlers/discovery.ts +98 -8
- package/src/handlers/fallback.test.ts +26 -22
- package/src/handlers/fallback.ts +36 -33
- package/src/handlers/file-checkouts.test.ts +670 -0
- package/src/handlers/file-checkouts.ts +165 -0
- package/src/handlers/findings.test.ts +178 -19
- package/src/handlers/findings.ts +112 -74
- package/src/handlers/git-issues.test.ts +51 -43
- package/src/handlers/git-issues.ts +44 -84
- package/src/handlers/ideas.test.ts +28 -23
- package/src/handlers/ideas.ts +61 -59
- package/src/handlers/index.ts +9 -0
- package/src/handlers/milestones.test.ts +33 -28
- package/src/handlers/milestones.ts +52 -50
- package/src/handlers/organizations.test.ts +104 -83
- package/src/handlers/organizations.ts +117 -142
- package/src/handlers/progress.test.ts +20 -14
- package/src/handlers/progress.ts +26 -24
- package/src/handlers/project.test.ts +34 -27
- package/src/handlers/project.ts +95 -63
- package/src/handlers/requests.test.ts +27 -18
- package/src/handlers/requests.ts +21 -17
- package/src/handlers/roles.test.ts +303 -0
- package/src/handlers/roles.ts +208 -0
- package/src/handlers/session.test.ts +47 -0
- package/src/handlers/session.ts +71 -26
- package/src/handlers/sprints.test.ts +71 -50
- package/src/handlers/sprints.ts +113 -146
- package/src/handlers/tasks.test.ts +77 -15
- package/src/handlers/tasks.ts +231 -156
- package/src/handlers/tool-categories.test.ts +66 -0
- package/src/handlers/types.ts +81 -2
- package/src/handlers/validation.test.ts +78 -45
- package/src/handlers/validation.ts +23 -25
- package/src/index.ts +12 -2732
- package/src/token-tracking.test.ts +453 -0
- package/src/token-tracking.ts +164 -0
- package/src/tools.ts +685 -9
- package/src/utils.test.ts +2 -2
- package/src/utils.ts +17 -0
- package/dist/config/tool-categories.d.ts +0 -31
- package/dist/config/tool-categories.js +0 -253
- package/dist/knowledge.d.ts +0 -6
- package/dist/knowledge.js +0 -218
|
@@ -17,34 +17,134 @@
|
|
|
17
17
|
import type { Handler, HandlerRegistry } from './types.js';
|
|
18
18
|
import {
|
|
19
19
|
ValidationError,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
parseArgs,
|
|
21
|
+
uuidValidator,
|
|
22
|
+
createEnumValidator,
|
|
23
23
|
} from '../validators.js';
|
|
24
24
|
import { getApiClient } from '../api-client.js';
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
git_ref?: string;
|
|
33
|
-
};
|
|
26
|
+
const ENVIRONMENTS = ['development', 'staging', 'production'] as const;
|
|
27
|
+
const VERSION_BUMPS = ['patch', 'minor', 'major'] as const;
|
|
28
|
+
const REQUIREMENT_TYPES = ['migration', 'env_var', 'config', 'manual', 'breaking_change', 'agent_task'] as const;
|
|
29
|
+
const REQUIREMENT_STAGES = ['preparation', 'deployment', 'verification'] as const;
|
|
30
|
+
const REQUIREMENT_STATUSES = ['pending', 'completed', 'converted_to_task', 'all'] as const;
|
|
31
|
+
const SCHEDULE_TYPES = ['once', 'hourly', 'daily', 'weekly', 'monthly'] as const;
|
|
34
32
|
|
|
35
|
-
|
|
33
|
+
type Environment = typeof ENVIRONMENTS[number];
|
|
34
|
+
type VersionBump = typeof VERSION_BUMPS[number];
|
|
35
|
+
type RequirementType = typeof REQUIREMENT_TYPES[number];
|
|
36
|
+
type RequirementStage = typeof REQUIREMENT_STAGES[number];
|
|
37
|
+
type RequirementStatus = typeof REQUIREMENT_STATUSES[number];
|
|
38
|
+
type ScheduleType = typeof SCHEDULE_TYPES[number];
|
|
39
|
+
|
|
40
|
+
// ============================================================================
|
|
41
|
+
// Argument Schemas
|
|
42
|
+
// ============================================================================
|
|
36
43
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
44
|
+
const requestDeploymentSchema = {
|
|
45
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
46
|
+
environment: { type: 'string' as const, default: 'production', validate: createEnumValidator(ENVIRONMENTS) },
|
|
47
|
+
version_bump: { type: 'string' as const, default: 'patch', validate: createEnumValidator(VERSION_BUMPS) },
|
|
48
|
+
notes: { type: 'string' as const },
|
|
49
|
+
git_ref: { type: 'string' as const },
|
|
50
|
+
};
|
|
40
51
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
52
|
+
const claimDeploymentValidationSchema = {
|
|
53
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const reportValidationSchema = {
|
|
57
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
58
|
+
build_passed: { type: 'boolean' as const, required: true as const },
|
|
59
|
+
tests_passed: { type: 'boolean' as const },
|
|
60
|
+
error_message: { type: 'string' as const },
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const checkDeploymentStatusSchema = {
|
|
64
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const startDeploymentSchema = {
|
|
68
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const completeDeploymentSchema = {
|
|
72
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
73
|
+
success: { type: 'boolean' as const, required: true as const },
|
|
74
|
+
summary: { type: 'string' as const },
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const cancelDeploymentSchema = {
|
|
78
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
79
|
+
reason: { type: 'string' as const },
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const addDeploymentRequirementSchema = {
|
|
83
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
84
|
+
type: { type: 'string' as const, required: true as const, validate: createEnumValidator(REQUIREMENT_TYPES) },
|
|
85
|
+
title: { type: 'string' as const, required: true as const },
|
|
86
|
+
description: { type: 'string' as const },
|
|
87
|
+
file_path: { type: 'string' as const },
|
|
88
|
+
stage: { type: 'string' as const, default: 'preparation', validate: createEnumValidator(REQUIREMENT_STAGES) },
|
|
89
|
+
blocking: { type: 'boolean' as const, default: false },
|
|
90
|
+
recurring: { type: 'boolean' as const, default: false },
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const completeDeploymentRequirementSchema = {
|
|
94
|
+
requirement_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const getDeploymentRequirementsSchema = {
|
|
98
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
99
|
+
status: { type: 'string' as const, default: 'pending', validate: createEnumValidator(REQUIREMENT_STATUSES) },
|
|
100
|
+
stage: { type: 'string' as const, validate: createEnumValidator([...REQUIREMENT_STAGES, 'all'] as const) },
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const scheduleDeploymentSchema = {
|
|
104
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
105
|
+
environment: { type: 'string' as const, default: 'production', validate: createEnumValidator(ENVIRONMENTS) },
|
|
106
|
+
version_bump: { type: 'string' as const, default: 'patch', validate: createEnumValidator(VERSION_BUMPS) },
|
|
107
|
+
schedule_type: { type: 'string' as const, default: 'once', validate: createEnumValidator(SCHEDULE_TYPES) },
|
|
108
|
+
scheduled_at: { type: 'string' as const, required: true as const },
|
|
109
|
+
auto_trigger: { type: 'boolean' as const, default: true },
|
|
110
|
+
hours_interval: { type: 'number' as const, default: 1 },
|
|
111
|
+
notes: { type: 'string' as const },
|
|
112
|
+
git_ref: { type: 'string' as const },
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const getScheduledDeploymentsSchema = {
|
|
116
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
117
|
+
include_disabled: { type: 'boolean' as const, default: false },
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const updateScheduledDeploymentSchema = {
|
|
121
|
+
schedule_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
122
|
+
environment: { type: 'string' as const, validate: createEnumValidator(ENVIRONMENTS) },
|
|
123
|
+
version_bump: { type: 'string' as const, validate: createEnumValidator(VERSION_BUMPS) },
|
|
124
|
+
schedule_type: { type: 'string' as const, validate: createEnumValidator(SCHEDULE_TYPES) },
|
|
125
|
+
scheduled_at: { type: 'string' as const },
|
|
126
|
+
auto_trigger: { type: 'boolean' as const },
|
|
127
|
+
hours_interval: { type: 'number' as const },
|
|
128
|
+
enabled: { type: 'boolean' as const },
|
|
129
|
+
notes: { type: 'string' as const },
|
|
130
|
+
git_ref: { type: 'string' as const },
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const deleteScheduledDeploymentSchema = {
|
|
134
|
+
schedule_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const triggerScheduledDeploymentSchema = {
|
|
138
|
+
schedule_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const checkDueDeploymentsSchema = {
|
|
142
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
export const requestDeployment: Handler = async (args, ctx) => {
|
|
146
|
+
const { project_id, environment, version_bump, notes, git_ref } = parseArgs(args, requestDeploymentSchema);
|
|
147
|
+
const { session } = ctx;
|
|
48
148
|
|
|
49
149
|
const apiClient = getApiClient();
|
|
50
150
|
const response = await apiClient.requestDeployment(project_id, {
|
|
@@ -55,19 +155,16 @@ export const requestDeployment: Handler = async (args, ctx) => {
|
|
|
55
155
|
});
|
|
56
156
|
|
|
57
157
|
if (!response.ok) {
|
|
58
|
-
|
|
158
|
+
return { result: { error: response.error || 'Failed to request deployment' }, isError: true };
|
|
59
159
|
}
|
|
60
160
|
|
|
61
161
|
return { result: response.data };
|
|
62
162
|
};
|
|
63
163
|
|
|
64
164
|
export const claimDeploymentValidation: Handler = async (args, ctx) => {
|
|
65
|
-
const { project_id } = args
|
|
165
|
+
const { project_id } = parseArgs(args, claimDeploymentValidationSchema);
|
|
66
166
|
const { session } = ctx;
|
|
67
167
|
|
|
68
|
-
validateRequired(project_id, 'project_id');
|
|
69
|
-
validateUUID(project_id, 'project_id');
|
|
70
|
-
|
|
71
168
|
const apiClient = getApiClient();
|
|
72
169
|
const response = await apiClient.claimDeploymentValidation(
|
|
73
170
|
project_id,
|
|
@@ -75,31 +172,16 @@ export const claimDeploymentValidation: Handler = async (args, ctx) => {
|
|
|
75
172
|
);
|
|
76
173
|
|
|
77
174
|
if (!response.ok) {
|
|
78
|
-
|
|
175
|
+
return { result: { error: response.error || 'Failed to claim deployment validation' }, isError: true };
|
|
79
176
|
}
|
|
80
177
|
|
|
81
178
|
return { result: response.data };
|
|
82
179
|
};
|
|
83
180
|
|
|
84
181
|
export const reportValidation: Handler = async (args, ctx) => {
|
|
85
|
-
const { project_id, build_passed, tests_passed, error_message } = args
|
|
86
|
-
project_id: string;
|
|
87
|
-
build_passed: boolean;
|
|
88
|
-
tests_passed?: boolean;
|
|
89
|
-
error_message?: string;
|
|
90
|
-
};
|
|
91
|
-
|
|
182
|
+
const { project_id, build_passed, tests_passed, error_message } = parseArgs(args, reportValidationSchema);
|
|
92
183
|
const { session } = ctx;
|
|
93
184
|
|
|
94
|
-
validateRequired(project_id, 'project_id');
|
|
95
|
-
validateUUID(project_id, 'project_id');
|
|
96
|
-
if (build_passed === undefined) {
|
|
97
|
-
throw new ValidationError('build_passed is required', {
|
|
98
|
-
field: 'build_passed',
|
|
99
|
-
hint: 'Set to true if the build succeeded, false otherwise',
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
|
|
103
185
|
const apiClient = getApiClient();
|
|
104
186
|
const response = await apiClient.reportValidation(project_id, {
|
|
105
187
|
build_passed,
|
|
@@ -108,35 +190,29 @@ export const reportValidation: Handler = async (args, ctx) => {
|
|
|
108
190
|
});
|
|
109
191
|
|
|
110
192
|
if (!response.ok) {
|
|
111
|
-
|
|
193
|
+
return { result: { error: response.error || 'Failed to report validation' }, isError: true };
|
|
112
194
|
}
|
|
113
195
|
|
|
114
196
|
return { result: response.data };
|
|
115
197
|
};
|
|
116
198
|
|
|
117
199
|
export const checkDeploymentStatus: Handler = async (args, ctx) => {
|
|
118
|
-
const { project_id } = args
|
|
119
|
-
|
|
120
|
-
validateRequired(project_id, 'project_id');
|
|
121
|
-
validateUUID(project_id, 'project_id');
|
|
200
|
+
const { project_id } = parseArgs(args, checkDeploymentStatusSchema);
|
|
122
201
|
|
|
123
202
|
const apiClient = getApiClient();
|
|
124
203
|
const response = await apiClient.checkDeploymentStatus(project_id);
|
|
125
204
|
|
|
126
205
|
if (!response.ok) {
|
|
127
|
-
|
|
206
|
+
return { result: { error: response.error || 'Failed to check deployment status' }, isError: true };
|
|
128
207
|
}
|
|
129
208
|
|
|
130
209
|
return { result: response.data };
|
|
131
210
|
};
|
|
132
211
|
|
|
133
212
|
export const startDeployment: Handler = async (args, ctx) => {
|
|
134
|
-
const { project_id } = args
|
|
213
|
+
const { project_id } = parseArgs(args, startDeploymentSchema);
|
|
135
214
|
const { session } = ctx;
|
|
136
215
|
|
|
137
|
-
validateRequired(project_id, 'project_id');
|
|
138
|
-
validateUUID(project_id, 'project_id');
|
|
139
|
-
|
|
140
216
|
const apiClient = getApiClient();
|
|
141
217
|
const response = await apiClient.startDeployment(
|
|
142
218
|
project_id,
|
|
@@ -144,30 +220,16 @@ export const startDeployment: Handler = async (args, ctx) => {
|
|
|
144
220
|
);
|
|
145
221
|
|
|
146
222
|
if (!response.ok) {
|
|
147
|
-
|
|
223
|
+
return { result: { error: response.error || 'Failed to start deployment' }, isError: true };
|
|
148
224
|
}
|
|
149
225
|
|
|
150
226
|
return { result: response.data };
|
|
151
227
|
};
|
|
152
228
|
|
|
153
229
|
export const completeDeployment: Handler = async (args, ctx) => {
|
|
154
|
-
const { project_id, success, summary } = args
|
|
155
|
-
project_id: string;
|
|
156
|
-
success: boolean;
|
|
157
|
-
summary?: string;
|
|
158
|
-
};
|
|
159
|
-
|
|
230
|
+
const { project_id, success, summary } = parseArgs(args, completeDeploymentSchema);
|
|
160
231
|
const { session } = ctx;
|
|
161
232
|
|
|
162
|
-
validateRequired(project_id, 'project_id');
|
|
163
|
-
validateUUID(project_id, 'project_id');
|
|
164
|
-
if (success === undefined) {
|
|
165
|
-
throw new ValidationError('success is required', {
|
|
166
|
-
field: 'success',
|
|
167
|
-
hint: 'Set to true if deployment succeeded, false otherwise',
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
|
|
171
233
|
const apiClient = getApiClient();
|
|
172
234
|
const response = await apiClient.completeDeployment(project_id, {
|
|
173
235
|
success,
|
|
@@ -175,54 +237,27 @@ export const completeDeployment: Handler = async (args, ctx) => {
|
|
|
175
237
|
});
|
|
176
238
|
|
|
177
239
|
if (!response.ok) {
|
|
178
|
-
|
|
240
|
+
return { result: { error: response.error || 'Failed to complete deployment' }, isError: true };
|
|
179
241
|
}
|
|
180
242
|
|
|
181
243
|
return { result: response.data };
|
|
182
244
|
};
|
|
183
245
|
|
|
184
246
|
export const cancelDeployment: Handler = async (args, ctx) => {
|
|
185
|
-
const { project_id, reason } = args
|
|
186
|
-
|
|
187
|
-
validateRequired(project_id, 'project_id');
|
|
188
|
-
validateUUID(project_id, 'project_id');
|
|
247
|
+
const { project_id, reason } = parseArgs(args, cancelDeploymentSchema);
|
|
189
248
|
|
|
190
249
|
const apiClient = getApiClient();
|
|
191
250
|
const response = await apiClient.cancelDeployment(project_id, reason);
|
|
192
251
|
|
|
193
252
|
if (!response.ok) {
|
|
194
|
-
|
|
253
|
+
return { result: { error: response.error || 'Failed to cancel deployment' }, isError: true };
|
|
195
254
|
}
|
|
196
255
|
|
|
197
256
|
return { result: response.data };
|
|
198
257
|
};
|
|
199
258
|
|
|
200
259
|
export const addDeploymentRequirement: Handler = async (args, ctx) => {
|
|
201
|
-
const { project_id, type, title, description, file_path, stage
|
|
202
|
-
project_id: string;
|
|
203
|
-
type: string;
|
|
204
|
-
title: string;
|
|
205
|
-
description?: string;
|
|
206
|
-
file_path?: string;
|
|
207
|
-
stage?: string;
|
|
208
|
-
blocking?: boolean;
|
|
209
|
-
recurring?: boolean;
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
validateRequired(project_id, 'project_id');
|
|
213
|
-
validateUUID(project_id, 'project_id');
|
|
214
|
-
validateRequired(type, 'type');
|
|
215
|
-
validateRequired(title, 'title');
|
|
216
|
-
|
|
217
|
-
const validTypes = ['migration', 'env_var', 'config', 'manual', 'breaking_change', 'agent_task'];
|
|
218
|
-
if (!validTypes.includes(type)) {
|
|
219
|
-
throw new ValidationError(`type must be one of: ${validTypes.join(', ')}`);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
const validStages = ['preparation', 'deployment', 'verification'];
|
|
223
|
-
if (!validStages.includes(stage)) {
|
|
224
|
-
throw new ValidationError(`stage must be one of: ${validStages.join(', ')}`);
|
|
225
|
-
}
|
|
260
|
+
const { project_id, type, title, description, file_path, stage, blocking, recurring } = parseArgs(args, addDeploymentRequirementSchema);
|
|
226
261
|
|
|
227
262
|
const apiClient = getApiClient();
|
|
228
263
|
const response = await apiClient.addDeploymentRequirement(project_id, {
|
|
@@ -236,37 +271,27 @@ export const addDeploymentRequirement: Handler = async (args, ctx) => {
|
|
|
236
271
|
});
|
|
237
272
|
|
|
238
273
|
if (!response.ok) {
|
|
239
|
-
|
|
274
|
+
return { result: { error: response.error || 'Failed to add deployment requirement' }, isError: true };
|
|
240
275
|
}
|
|
241
276
|
|
|
242
277
|
return { result: response.data };
|
|
243
278
|
};
|
|
244
279
|
|
|
245
280
|
export const completeDeploymentRequirement: Handler = async (args, ctx) => {
|
|
246
|
-
const { requirement_id } = args
|
|
247
|
-
|
|
248
|
-
validateRequired(requirement_id, 'requirement_id');
|
|
249
|
-
validateUUID(requirement_id, 'requirement_id');
|
|
281
|
+
const { requirement_id } = parseArgs(args, completeDeploymentRequirementSchema);
|
|
250
282
|
|
|
251
283
|
const apiClient = getApiClient();
|
|
252
284
|
const response = await apiClient.completeDeploymentRequirement(requirement_id);
|
|
253
285
|
|
|
254
286
|
if (!response.ok) {
|
|
255
|
-
|
|
287
|
+
return { result: { error: response.error || 'Failed to complete deployment requirement' }, isError: true };
|
|
256
288
|
}
|
|
257
289
|
|
|
258
290
|
return { result: response.data };
|
|
259
291
|
};
|
|
260
292
|
|
|
261
293
|
export const getDeploymentRequirements: Handler = async (args, ctx) => {
|
|
262
|
-
const { project_id, status
|
|
263
|
-
project_id: string;
|
|
264
|
-
status?: string;
|
|
265
|
-
stage?: string;
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
validateRequired(project_id, 'project_id');
|
|
269
|
-
validateUUID(project_id, 'project_id');
|
|
294
|
+
const { project_id, status, stage } = parseArgs(args, getDeploymentRequirementsSchema);
|
|
270
295
|
|
|
271
296
|
const apiClient = getApiClient();
|
|
272
297
|
const response = await apiClient.getDeploymentRequirements(project_id, {
|
|
@@ -275,7 +300,7 @@ export const getDeploymentRequirements: Handler = async (args, ctx) => {
|
|
|
275
300
|
});
|
|
276
301
|
|
|
277
302
|
if (!response.ok) {
|
|
278
|
-
|
|
303
|
+
return { result: { error: response.error || 'Failed to get deployment requirements' }, isError: true };
|
|
279
304
|
}
|
|
280
305
|
|
|
281
306
|
return { result: response.data };
|
|
@@ -288,42 +313,15 @@ export const getDeploymentRequirements: Handler = async (args, ctx) => {
|
|
|
288
313
|
export const scheduleDeployment: Handler = async (args, ctx) => {
|
|
289
314
|
const {
|
|
290
315
|
project_id,
|
|
291
|
-
environment
|
|
292
|
-
version_bump
|
|
293
|
-
schedule_type
|
|
316
|
+
environment,
|
|
317
|
+
version_bump,
|
|
318
|
+
schedule_type,
|
|
294
319
|
scheduled_at,
|
|
295
|
-
auto_trigger
|
|
320
|
+
auto_trigger,
|
|
321
|
+
hours_interval,
|
|
296
322
|
notes,
|
|
297
323
|
git_ref,
|
|
298
|
-
} = args
|
|
299
|
-
project_id: string;
|
|
300
|
-
environment?: string;
|
|
301
|
-
version_bump?: string;
|
|
302
|
-
schedule_type?: string;
|
|
303
|
-
scheduled_at: string;
|
|
304
|
-
auto_trigger?: boolean;
|
|
305
|
-
notes?: string;
|
|
306
|
-
git_ref?: string;
|
|
307
|
-
};
|
|
308
|
-
|
|
309
|
-
validateRequired(project_id, 'project_id');
|
|
310
|
-
validateUUID(project_id, 'project_id');
|
|
311
|
-
validateRequired(scheduled_at, 'scheduled_at');
|
|
312
|
-
validateEnvironment(environment);
|
|
313
|
-
|
|
314
|
-
if (!['patch', 'minor', 'major'].includes(version_bump)) {
|
|
315
|
-
throw new ValidationError('Invalid version_bump value', {
|
|
316
|
-
field: 'version_bump',
|
|
317
|
-
validValues: ['patch', 'minor', 'major'],
|
|
318
|
-
});
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
if (!['once', 'daily', 'weekly', 'monthly'].includes(schedule_type)) {
|
|
322
|
-
throw new ValidationError('Invalid schedule_type value', {
|
|
323
|
-
field: 'schedule_type',
|
|
324
|
-
validValues: ['once', 'daily', 'weekly', 'monthly'],
|
|
325
|
-
});
|
|
326
|
-
}
|
|
324
|
+
} = parseArgs(args, scheduleDeploymentSchema);
|
|
327
325
|
|
|
328
326
|
// Parse and validate scheduled_at
|
|
329
327
|
const scheduledDate = new Date(scheduled_at);
|
|
@@ -340,38 +338,41 @@ export const scheduleDeployment: Handler = async (args, ctx) => {
|
|
|
340
338
|
});
|
|
341
339
|
}
|
|
342
340
|
|
|
341
|
+
// Validate hours_interval for hourly schedule type (default is 1)
|
|
342
|
+
const hoursInterval = hours_interval ?? 1;
|
|
343
|
+
if (schedule_type === 'hourly' && (hoursInterval < 1 || hoursInterval > 24)) {
|
|
344
|
+
throw new ValidationError('hours_interval must be between 1 and 24', {
|
|
345
|
+
field: 'hours_interval',
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
|
|
343
349
|
const apiClient = getApiClient();
|
|
344
350
|
const response = await apiClient.scheduleDeployment(project_id, {
|
|
345
351
|
environment: environment as 'development' | 'staging' | 'production',
|
|
346
352
|
version_bump: version_bump as 'patch' | 'minor' | 'major',
|
|
347
|
-
schedule_type: schedule_type as 'once' | 'daily' | 'weekly' | 'monthly',
|
|
353
|
+
schedule_type: schedule_type as 'once' | 'hourly' | 'daily' | 'weekly' | 'monthly',
|
|
348
354
|
scheduled_at: scheduledDate.toISOString(),
|
|
349
355
|
auto_trigger,
|
|
356
|
+
hours_interval: hoursInterval,
|
|
350
357
|
notes,
|
|
351
358
|
git_ref
|
|
352
359
|
});
|
|
353
360
|
|
|
354
361
|
if (!response.ok) {
|
|
355
|
-
|
|
362
|
+
return { result: { error: response.error || 'Failed to schedule deployment' }, isError: true };
|
|
356
363
|
}
|
|
357
364
|
|
|
358
365
|
return { result: response.data };
|
|
359
366
|
};
|
|
360
367
|
|
|
361
368
|
export const getScheduledDeployments: Handler = async (args, ctx) => {
|
|
362
|
-
const { project_id, include_disabled
|
|
363
|
-
project_id: string;
|
|
364
|
-
include_disabled?: boolean;
|
|
365
|
-
};
|
|
366
|
-
|
|
367
|
-
validateRequired(project_id, 'project_id');
|
|
368
|
-
validateUUID(project_id, 'project_id');
|
|
369
|
+
const { project_id, include_disabled } = parseArgs(args, getScheduledDeploymentsSchema);
|
|
369
370
|
|
|
370
371
|
const apiClient = getApiClient();
|
|
371
372
|
const response = await apiClient.getScheduledDeployments(project_id, include_disabled);
|
|
372
373
|
|
|
373
374
|
if (!response.ok) {
|
|
374
|
-
|
|
375
|
+
return { result: { error: response.error || 'Failed to get scheduled deployments' }, isError: true };
|
|
375
376
|
}
|
|
376
377
|
|
|
377
378
|
return { result: response.data };
|
|
@@ -385,44 +386,17 @@ export const updateScheduledDeployment: Handler = async (args, ctx) => {
|
|
|
385
386
|
schedule_type,
|
|
386
387
|
scheduled_at,
|
|
387
388
|
auto_trigger,
|
|
389
|
+
hours_interval,
|
|
388
390
|
enabled,
|
|
389
391
|
notes,
|
|
390
392
|
git_ref,
|
|
391
|
-
} = args
|
|
392
|
-
schedule_id: string;
|
|
393
|
-
environment?: string;
|
|
394
|
-
version_bump?: string;
|
|
395
|
-
schedule_type?: string;
|
|
396
|
-
scheduled_at?: string;
|
|
397
|
-
auto_trigger?: boolean;
|
|
398
|
-
enabled?: boolean;
|
|
399
|
-
notes?: string;
|
|
400
|
-
git_ref?: string;
|
|
401
|
-
};
|
|
402
|
-
|
|
403
|
-
validateRequired(schedule_id, 'schedule_id');
|
|
404
|
-
validateUUID(schedule_id, 'schedule_id');
|
|
393
|
+
} = parseArgs(args, updateScheduledDeploymentSchema);
|
|
405
394
|
|
|
406
395
|
const updates: Record<string, unknown> = {};
|
|
407
396
|
|
|
408
|
-
if (environment !== undefined)
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
if (version_bump !== undefined) {
|
|
414
|
-
if (!['patch', 'minor', 'major'].includes(version_bump)) {
|
|
415
|
-
throw new ValidationError('Invalid version_bump value');
|
|
416
|
-
}
|
|
417
|
-
updates.version_bump = version_bump;
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
if (schedule_type !== undefined) {
|
|
421
|
-
if (!['once', 'daily', 'weekly', 'monthly'].includes(schedule_type)) {
|
|
422
|
-
throw new ValidationError('Invalid schedule_type value');
|
|
423
|
-
}
|
|
424
|
-
updates.schedule_type = schedule_type;
|
|
425
|
-
}
|
|
397
|
+
if (environment !== undefined) updates.environment = environment;
|
|
398
|
+
if (version_bump !== undefined) updates.version_bump = version_bump;
|
|
399
|
+
if (schedule_type !== undefined) updates.schedule_type = schedule_type;
|
|
426
400
|
|
|
427
401
|
if (scheduled_at !== undefined) {
|
|
428
402
|
const scheduledDate = new Date(scheduled_at);
|
|
@@ -433,6 +407,12 @@ export const updateScheduledDeployment: Handler = async (args, ctx) => {
|
|
|
433
407
|
}
|
|
434
408
|
|
|
435
409
|
if (auto_trigger !== undefined) updates.auto_trigger = auto_trigger;
|
|
410
|
+
if (hours_interval !== undefined) {
|
|
411
|
+
if (hours_interval < 1 || hours_interval > 24) {
|
|
412
|
+
throw new ValidationError('hours_interval must be between 1 and 24');
|
|
413
|
+
}
|
|
414
|
+
updates.hours_interval = hours_interval;
|
|
415
|
+
}
|
|
436
416
|
if (enabled !== undefined) updates.enabled = enabled;
|
|
437
417
|
if (notes !== undefined) updates.notes = notes;
|
|
438
418
|
if (git_ref !== undefined) updates.git_ref = git_ref;
|
|
@@ -445,44 +425,39 @@ export const updateScheduledDeployment: Handler = async (args, ctx) => {
|
|
|
445
425
|
const response = await apiClient.updateScheduledDeployment(schedule_id, updates as {
|
|
446
426
|
environment?: 'development' | 'staging' | 'production';
|
|
447
427
|
version_bump?: 'patch' | 'minor' | 'major';
|
|
448
|
-
schedule_type?: 'once' | 'daily' | 'weekly' | 'monthly';
|
|
428
|
+
schedule_type?: 'once' | 'hourly' | 'daily' | 'weekly' | 'monthly';
|
|
449
429
|
scheduled_at?: string;
|
|
450
430
|
auto_trigger?: boolean;
|
|
431
|
+
hours_interval?: number;
|
|
451
432
|
enabled?: boolean;
|
|
452
433
|
notes?: string;
|
|
453
434
|
git_ref?: string;
|
|
454
435
|
});
|
|
455
436
|
|
|
456
437
|
if (!response.ok) {
|
|
457
|
-
|
|
438
|
+
return { result: { error: response.error || 'Failed to update scheduled deployment' }, isError: true };
|
|
458
439
|
}
|
|
459
440
|
|
|
460
441
|
return { result: response.data };
|
|
461
442
|
};
|
|
462
443
|
|
|
463
444
|
export const deleteScheduledDeployment: Handler = async (args, ctx) => {
|
|
464
|
-
const { schedule_id } = args
|
|
465
|
-
|
|
466
|
-
validateRequired(schedule_id, 'schedule_id');
|
|
467
|
-
validateUUID(schedule_id, 'schedule_id');
|
|
445
|
+
const { schedule_id } = parseArgs(args, deleteScheduledDeploymentSchema);
|
|
468
446
|
|
|
469
447
|
const apiClient = getApiClient();
|
|
470
448
|
const response = await apiClient.deleteScheduledDeployment(schedule_id);
|
|
471
449
|
|
|
472
450
|
if (!response.ok) {
|
|
473
|
-
|
|
451
|
+
return { result: { error: response.error || 'Failed to delete scheduled deployment' }, isError: true };
|
|
474
452
|
}
|
|
475
453
|
|
|
476
454
|
return { result: response.data };
|
|
477
455
|
};
|
|
478
456
|
|
|
479
457
|
export const triggerScheduledDeployment: Handler = async (args, ctx) => {
|
|
480
|
-
const { schedule_id } = args
|
|
458
|
+
const { schedule_id } = parseArgs(args, triggerScheduledDeploymentSchema);
|
|
481
459
|
const { session } = ctx;
|
|
482
460
|
|
|
483
|
-
validateRequired(schedule_id, 'schedule_id');
|
|
484
|
-
validateUUID(schedule_id, 'schedule_id');
|
|
485
|
-
|
|
486
461
|
const apiClient = getApiClient();
|
|
487
462
|
const response = await apiClient.triggerScheduledDeployment(
|
|
488
463
|
schedule_id,
|
|
@@ -490,23 +465,20 @@ export const triggerScheduledDeployment: Handler = async (args, ctx) => {
|
|
|
490
465
|
);
|
|
491
466
|
|
|
492
467
|
if (!response.ok) {
|
|
493
|
-
|
|
468
|
+
return { result: { error: response.error || 'Failed to trigger scheduled deployment' }, isError: true };
|
|
494
469
|
}
|
|
495
470
|
|
|
496
471
|
return { result: response.data };
|
|
497
472
|
};
|
|
498
473
|
|
|
499
474
|
export const checkDueDeployments: Handler = async (args, ctx) => {
|
|
500
|
-
const { project_id } = args
|
|
501
|
-
|
|
502
|
-
validateRequired(project_id, 'project_id');
|
|
503
|
-
validateUUID(project_id, 'project_id');
|
|
475
|
+
const { project_id } = parseArgs(args, checkDueDeploymentsSchema);
|
|
504
476
|
|
|
505
477
|
const apiClient = getApiClient();
|
|
506
478
|
const response = await apiClient.checkDueDeployments(project_id);
|
|
507
479
|
|
|
508
480
|
if (!response.ok) {
|
|
509
|
-
|
|
481
|
+
return { result: { error: response.error || 'Failed to check due deployments' }, isError: true };
|
|
510
482
|
}
|
|
511
483
|
|
|
512
484
|
return { result: response.data };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
2
|
import { discoverTools, getToolInfo } from './discovery.js';
|
|
3
3
|
import { createMockContext } from './__test-utils__.js';
|
|
4
|
+
import { ValidationError } from '../validators.js';
|
|
4
5
|
|
|
5
6
|
// ============================================================================
|
|
6
7
|
// discoverTools Tests
|
|
@@ -113,13 +114,11 @@ describe('discoverTools', () => {
|
|
|
113
114
|
// ============================================================================
|
|
114
115
|
|
|
115
116
|
describe('getToolInfo', () => {
|
|
116
|
-
it('should
|
|
117
|
+
it('should throw ValidationError for missing tool_name', async () => {
|
|
117
118
|
const ctx = createMockContext();
|
|
118
119
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
expect(res.error).toBe('tool_name is required');
|
|
120
|
+
await expect(getToolInfo({}, ctx)).rejects.toThrow(ValidationError);
|
|
121
|
+
await expect(getToolInfo({}, ctx)).rejects.toThrow('Missing required field: tool_name');
|
|
123
122
|
});
|
|
124
123
|
|
|
125
124
|
it('should return error for unknown tool', async () => {
|