@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
|
@@ -13,21 +13,105 @@
|
|
|
13
13
|
* - complete_deployment_requirement
|
|
14
14
|
* - get_deployment_requirements
|
|
15
15
|
*/
|
|
16
|
-
import { ValidationError,
|
|
16
|
+
import { ValidationError, parseArgs, uuidValidator, createEnumValidator, } from '../validators.js';
|
|
17
17
|
import { getApiClient } from '../api-client.js';
|
|
18
|
+
const ENVIRONMENTS = ['development', 'staging', 'production'];
|
|
19
|
+
const VERSION_BUMPS = ['patch', 'minor', 'major'];
|
|
20
|
+
const REQUIREMENT_TYPES = ['migration', 'env_var', 'config', 'manual', 'breaking_change', 'agent_task'];
|
|
21
|
+
const REQUIREMENT_STAGES = ['preparation', 'deployment', 'verification'];
|
|
22
|
+
const REQUIREMENT_STATUSES = ['pending', 'completed', 'converted_to_task', 'all'];
|
|
23
|
+
const SCHEDULE_TYPES = ['once', 'hourly', 'daily', 'weekly', 'monthly'];
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// Argument Schemas
|
|
26
|
+
// ============================================================================
|
|
27
|
+
const requestDeploymentSchema = {
|
|
28
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
29
|
+
environment: { type: 'string', default: 'production', validate: createEnumValidator(ENVIRONMENTS) },
|
|
30
|
+
version_bump: { type: 'string', default: 'patch', validate: createEnumValidator(VERSION_BUMPS) },
|
|
31
|
+
notes: { type: 'string' },
|
|
32
|
+
git_ref: { type: 'string' },
|
|
33
|
+
};
|
|
34
|
+
const claimDeploymentValidationSchema = {
|
|
35
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
36
|
+
};
|
|
37
|
+
const reportValidationSchema = {
|
|
38
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
39
|
+
build_passed: { type: 'boolean', required: true },
|
|
40
|
+
tests_passed: { type: 'boolean' },
|
|
41
|
+
error_message: { type: 'string' },
|
|
42
|
+
};
|
|
43
|
+
const checkDeploymentStatusSchema = {
|
|
44
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
45
|
+
};
|
|
46
|
+
const startDeploymentSchema = {
|
|
47
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
48
|
+
};
|
|
49
|
+
const completeDeploymentSchema = {
|
|
50
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
51
|
+
success: { type: 'boolean', required: true },
|
|
52
|
+
summary: { type: 'string' },
|
|
53
|
+
};
|
|
54
|
+
const cancelDeploymentSchema = {
|
|
55
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
56
|
+
reason: { type: 'string' },
|
|
57
|
+
};
|
|
58
|
+
const addDeploymentRequirementSchema = {
|
|
59
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
60
|
+
type: { type: 'string', required: true, validate: createEnumValidator(REQUIREMENT_TYPES) },
|
|
61
|
+
title: { type: 'string', required: true },
|
|
62
|
+
description: { type: 'string' },
|
|
63
|
+
file_path: { type: 'string' },
|
|
64
|
+
stage: { type: 'string', default: 'preparation', validate: createEnumValidator(REQUIREMENT_STAGES) },
|
|
65
|
+
blocking: { type: 'boolean', default: false },
|
|
66
|
+
recurring: { type: 'boolean', default: false },
|
|
67
|
+
};
|
|
68
|
+
const completeDeploymentRequirementSchema = {
|
|
69
|
+
requirement_id: { type: 'string', required: true, validate: uuidValidator },
|
|
70
|
+
};
|
|
71
|
+
const getDeploymentRequirementsSchema = {
|
|
72
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
73
|
+
status: { type: 'string', default: 'pending', validate: createEnumValidator(REQUIREMENT_STATUSES) },
|
|
74
|
+
stage: { type: 'string', validate: createEnumValidator([...REQUIREMENT_STAGES, 'all']) },
|
|
75
|
+
};
|
|
76
|
+
const scheduleDeploymentSchema = {
|
|
77
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
78
|
+
environment: { type: 'string', default: 'production', validate: createEnumValidator(ENVIRONMENTS) },
|
|
79
|
+
version_bump: { type: 'string', default: 'patch', validate: createEnumValidator(VERSION_BUMPS) },
|
|
80
|
+
schedule_type: { type: 'string', default: 'once', validate: createEnumValidator(SCHEDULE_TYPES) },
|
|
81
|
+
scheduled_at: { type: 'string', required: true },
|
|
82
|
+
auto_trigger: { type: 'boolean', default: true },
|
|
83
|
+
hours_interval: { type: 'number', default: 1 },
|
|
84
|
+
notes: { type: 'string' },
|
|
85
|
+
git_ref: { type: 'string' },
|
|
86
|
+
};
|
|
87
|
+
const getScheduledDeploymentsSchema = {
|
|
88
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
89
|
+
include_disabled: { type: 'boolean', default: false },
|
|
90
|
+
};
|
|
91
|
+
const updateScheduledDeploymentSchema = {
|
|
92
|
+
schedule_id: { type: 'string', required: true, validate: uuidValidator },
|
|
93
|
+
environment: { type: 'string', validate: createEnumValidator(ENVIRONMENTS) },
|
|
94
|
+
version_bump: { type: 'string', validate: createEnumValidator(VERSION_BUMPS) },
|
|
95
|
+
schedule_type: { type: 'string', validate: createEnumValidator(SCHEDULE_TYPES) },
|
|
96
|
+
scheduled_at: { type: 'string' },
|
|
97
|
+
auto_trigger: { type: 'boolean' },
|
|
98
|
+
hours_interval: { type: 'number' },
|
|
99
|
+
enabled: { type: 'boolean' },
|
|
100
|
+
notes: { type: 'string' },
|
|
101
|
+
git_ref: { type: 'string' },
|
|
102
|
+
};
|
|
103
|
+
const deleteScheduledDeploymentSchema = {
|
|
104
|
+
schedule_id: { type: 'string', required: true, validate: uuidValidator },
|
|
105
|
+
};
|
|
106
|
+
const triggerScheduledDeploymentSchema = {
|
|
107
|
+
schedule_id: { type: 'string', required: true, validate: uuidValidator },
|
|
108
|
+
};
|
|
109
|
+
const checkDueDeploymentsSchema = {
|
|
110
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
111
|
+
};
|
|
18
112
|
export const requestDeployment = async (args, ctx) => {
|
|
19
|
-
const { project_id, environment
|
|
113
|
+
const { project_id, environment, version_bump, notes, git_ref } = parseArgs(args, requestDeploymentSchema);
|
|
20
114
|
const { session } = ctx;
|
|
21
|
-
validateRequired(project_id, 'project_id');
|
|
22
|
-
validateUUID(project_id, 'project_id');
|
|
23
|
-
validateEnvironment(environment);
|
|
24
|
-
if (version_bump && !['patch', 'minor', 'major'].includes(version_bump)) {
|
|
25
|
-
throw new ValidationError('Invalid version_bump value', {
|
|
26
|
-
field: 'version_bump',
|
|
27
|
-
validValues: ['patch', 'minor', 'major'],
|
|
28
|
-
hint: 'Must be one of: patch, minor, major',
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
115
|
const apiClient = getApiClient();
|
|
32
116
|
const response = await apiClient.requestDeployment(project_id, {
|
|
33
117
|
environment,
|
|
@@ -36,33 +120,23 @@ export const requestDeployment = async (args, ctx) => {
|
|
|
36
120
|
git_ref
|
|
37
121
|
});
|
|
38
122
|
if (!response.ok) {
|
|
39
|
-
|
|
123
|
+
return { result: { error: response.error || 'Failed to request deployment' }, isError: true };
|
|
40
124
|
}
|
|
41
125
|
return { result: response.data };
|
|
42
126
|
};
|
|
43
127
|
export const claimDeploymentValidation = async (args, ctx) => {
|
|
44
|
-
const { project_id } = args;
|
|
128
|
+
const { project_id } = parseArgs(args, claimDeploymentValidationSchema);
|
|
45
129
|
const { session } = ctx;
|
|
46
|
-
validateRequired(project_id, 'project_id');
|
|
47
|
-
validateUUID(project_id, 'project_id');
|
|
48
130
|
const apiClient = getApiClient();
|
|
49
131
|
const response = await apiClient.claimDeploymentValidation(project_id, session.currentSessionId || undefined);
|
|
50
132
|
if (!response.ok) {
|
|
51
|
-
|
|
133
|
+
return { result: { error: response.error || 'Failed to claim deployment validation' }, isError: true };
|
|
52
134
|
}
|
|
53
135
|
return { result: response.data };
|
|
54
136
|
};
|
|
55
137
|
export const reportValidation = async (args, ctx) => {
|
|
56
|
-
const { project_id, build_passed, tests_passed, error_message } = args;
|
|
138
|
+
const { project_id, build_passed, tests_passed, error_message } = parseArgs(args, reportValidationSchema);
|
|
57
139
|
const { session } = ctx;
|
|
58
|
-
validateRequired(project_id, 'project_id');
|
|
59
|
-
validateUUID(project_id, 'project_id');
|
|
60
|
-
if (build_passed === undefined) {
|
|
61
|
-
throw new ValidationError('build_passed is required', {
|
|
62
|
-
field: 'build_passed',
|
|
63
|
-
hint: 'Set to true if the build succeeded, false otherwise',
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
140
|
const apiClient = getApiClient();
|
|
67
141
|
const response = await apiClient.reportValidation(project_id, {
|
|
68
142
|
build_passed,
|
|
@@ -70,79 +144,53 @@ export const reportValidation = async (args, ctx) => {
|
|
|
70
144
|
error_message
|
|
71
145
|
});
|
|
72
146
|
if (!response.ok) {
|
|
73
|
-
|
|
147
|
+
return { result: { error: response.error || 'Failed to report validation' }, isError: true };
|
|
74
148
|
}
|
|
75
149
|
return { result: response.data };
|
|
76
150
|
};
|
|
77
151
|
export const checkDeploymentStatus = async (args, ctx) => {
|
|
78
|
-
const { project_id } = args;
|
|
79
|
-
validateRequired(project_id, 'project_id');
|
|
80
|
-
validateUUID(project_id, 'project_id');
|
|
152
|
+
const { project_id } = parseArgs(args, checkDeploymentStatusSchema);
|
|
81
153
|
const apiClient = getApiClient();
|
|
82
154
|
const response = await apiClient.checkDeploymentStatus(project_id);
|
|
83
155
|
if (!response.ok) {
|
|
84
|
-
|
|
156
|
+
return { result: { error: response.error || 'Failed to check deployment status' }, isError: true };
|
|
85
157
|
}
|
|
86
158
|
return { result: response.data };
|
|
87
159
|
};
|
|
88
160
|
export const startDeployment = async (args, ctx) => {
|
|
89
|
-
const { project_id } = args;
|
|
161
|
+
const { project_id } = parseArgs(args, startDeploymentSchema);
|
|
90
162
|
const { session } = ctx;
|
|
91
|
-
validateRequired(project_id, 'project_id');
|
|
92
|
-
validateUUID(project_id, 'project_id');
|
|
93
163
|
const apiClient = getApiClient();
|
|
94
164
|
const response = await apiClient.startDeployment(project_id, session.currentSessionId || undefined);
|
|
95
165
|
if (!response.ok) {
|
|
96
|
-
|
|
166
|
+
return { result: { error: response.error || 'Failed to start deployment' }, isError: true };
|
|
97
167
|
}
|
|
98
168
|
return { result: response.data };
|
|
99
169
|
};
|
|
100
170
|
export const completeDeployment = async (args, ctx) => {
|
|
101
|
-
const { project_id, success, summary } = args;
|
|
171
|
+
const { project_id, success, summary } = parseArgs(args, completeDeploymentSchema);
|
|
102
172
|
const { session } = ctx;
|
|
103
|
-
validateRequired(project_id, 'project_id');
|
|
104
|
-
validateUUID(project_id, 'project_id');
|
|
105
|
-
if (success === undefined) {
|
|
106
|
-
throw new ValidationError('success is required', {
|
|
107
|
-
field: 'success',
|
|
108
|
-
hint: 'Set to true if deployment succeeded, false otherwise',
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
173
|
const apiClient = getApiClient();
|
|
112
174
|
const response = await apiClient.completeDeployment(project_id, {
|
|
113
175
|
success,
|
|
114
176
|
summary
|
|
115
177
|
});
|
|
116
178
|
if (!response.ok) {
|
|
117
|
-
|
|
179
|
+
return { result: { error: response.error || 'Failed to complete deployment' }, isError: true };
|
|
118
180
|
}
|
|
119
181
|
return { result: response.data };
|
|
120
182
|
};
|
|
121
183
|
export const cancelDeployment = async (args, ctx) => {
|
|
122
|
-
const { project_id, reason } = args;
|
|
123
|
-
validateRequired(project_id, 'project_id');
|
|
124
|
-
validateUUID(project_id, 'project_id');
|
|
184
|
+
const { project_id, reason } = parseArgs(args, cancelDeploymentSchema);
|
|
125
185
|
const apiClient = getApiClient();
|
|
126
186
|
const response = await apiClient.cancelDeployment(project_id, reason);
|
|
127
187
|
if (!response.ok) {
|
|
128
|
-
|
|
188
|
+
return { result: { error: response.error || 'Failed to cancel deployment' }, isError: true };
|
|
129
189
|
}
|
|
130
190
|
return { result: response.data };
|
|
131
191
|
};
|
|
132
192
|
export const addDeploymentRequirement = async (args, ctx) => {
|
|
133
|
-
const { project_id, type, title, description, file_path, stage
|
|
134
|
-
validateRequired(project_id, 'project_id');
|
|
135
|
-
validateUUID(project_id, 'project_id');
|
|
136
|
-
validateRequired(type, 'type');
|
|
137
|
-
validateRequired(title, 'title');
|
|
138
|
-
const validTypes = ['migration', 'env_var', 'config', 'manual', 'breaking_change', 'agent_task'];
|
|
139
|
-
if (!validTypes.includes(type)) {
|
|
140
|
-
throw new ValidationError(`type must be one of: ${validTypes.join(', ')}`);
|
|
141
|
-
}
|
|
142
|
-
const validStages = ['preparation', 'deployment', 'verification'];
|
|
143
|
-
if (!validStages.includes(stage)) {
|
|
144
|
-
throw new ValidationError(`stage must be one of: ${validStages.join(', ')}`);
|
|
145
|
-
}
|
|
193
|
+
const { project_id, type, title, description, file_path, stage, blocking, recurring } = parseArgs(args, addDeploymentRequirementSchema);
|
|
146
194
|
const apiClient = getApiClient();
|
|
147
195
|
const response = await apiClient.addDeploymentRequirement(project_id, {
|
|
148
196
|
type: type,
|
|
@@ -154,32 +202,28 @@ export const addDeploymentRequirement = async (args, ctx) => {
|
|
|
154
202
|
recurring
|
|
155
203
|
});
|
|
156
204
|
if (!response.ok) {
|
|
157
|
-
|
|
205
|
+
return { result: { error: response.error || 'Failed to add deployment requirement' }, isError: true };
|
|
158
206
|
}
|
|
159
207
|
return { result: response.data };
|
|
160
208
|
};
|
|
161
209
|
export const completeDeploymentRequirement = async (args, ctx) => {
|
|
162
|
-
const { requirement_id } = args;
|
|
163
|
-
validateRequired(requirement_id, 'requirement_id');
|
|
164
|
-
validateUUID(requirement_id, 'requirement_id');
|
|
210
|
+
const { requirement_id } = parseArgs(args, completeDeploymentRequirementSchema);
|
|
165
211
|
const apiClient = getApiClient();
|
|
166
212
|
const response = await apiClient.completeDeploymentRequirement(requirement_id);
|
|
167
213
|
if (!response.ok) {
|
|
168
|
-
|
|
214
|
+
return { result: { error: response.error || 'Failed to complete deployment requirement' }, isError: true };
|
|
169
215
|
}
|
|
170
216
|
return { result: response.data };
|
|
171
217
|
};
|
|
172
218
|
export const getDeploymentRequirements = async (args, ctx) => {
|
|
173
|
-
const { project_id, status
|
|
174
|
-
validateRequired(project_id, 'project_id');
|
|
175
|
-
validateUUID(project_id, 'project_id');
|
|
219
|
+
const { project_id, status, stage } = parseArgs(args, getDeploymentRequirementsSchema);
|
|
176
220
|
const apiClient = getApiClient();
|
|
177
221
|
const response = await apiClient.getDeploymentRequirements(project_id, {
|
|
178
222
|
status: status,
|
|
179
223
|
stage: stage
|
|
180
224
|
});
|
|
181
225
|
if (!response.ok) {
|
|
182
|
-
|
|
226
|
+
return { result: { error: response.error || 'Failed to get deployment requirements' }, isError: true };
|
|
183
227
|
}
|
|
184
228
|
return { result: response.data };
|
|
185
229
|
};
|
|
@@ -187,23 +231,7 @@ export const getDeploymentRequirements = async (args, ctx) => {
|
|
|
187
231
|
// Scheduled Deployments
|
|
188
232
|
// ============================================================================
|
|
189
233
|
export const scheduleDeployment = async (args, ctx) => {
|
|
190
|
-
const { project_id, environment
|
|
191
|
-
validateRequired(project_id, 'project_id');
|
|
192
|
-
validateUUID(project_id, 'project_id');
|
|
193
|
-
validateRequired(scheduled_at, 'scheduled_at');
|
|
194
|
-
validateEnvironment(environment);
|
|
195
|
-
if (!['patch', 'minor', 'major'].includes(version_bump)) {
|
|
196
|
-
throw new ValidationError('Invalid version_bump value', {
|
|
197
|
-
field: 'version_bump',
|
|
198
|
-
validValues: ['patch', 'minor', 'major'],
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
if (!['once', 'daily', 'weekly', 'monthly'].includes(schedule_type)) {
|
|
202
|
-
throw new ValidationError('Invalid schedule_type value', {
|
|
203
|
-
field: 'schedule_type',
|
|
204
|
-
validValues: ['once', 'daily', 'weekly', 'monthly'],
|
|
205
|
-
});
|
|
206
|
-
}
|
|
234
|
+
const { project_id, environment, version_bump, schedule_type, scheduled_at, auto_trigger, hours_interval, notes, git_ref, } = parseArgs(args, scheduleDeploymentSchema);
|
|
207
235
|
// Parse and validate scheduled_at
|
|
208
236
|
const scheduledDate = new Date(scheduled_at);
|
|
209
237
|
if (isNaN(scheduledDate.getTime())) {
|
|
@@ -217,6 +245,13 @@ export const scheduleDeployment = async (args, ctx) => {
|
|
|
217
245
|
field: 'scheduled_at',
|
|
218
246
|
});
|
|
219
247
|
}
|
|
248
|
+
// Validate hours_interval for hourly schedule type (default is 1)
|
|
249
|
+
const hoursInterval = hours_interval ?? 1;
|
|
250
|
+
if (schedule_type === 'hourly' && (hoursInterval < 1 || hoursInterval > 24)) {
|
|
251
|
+
throw new ValidationError('hours_interval must be between 1 and 24', {
|
|
252
|
+
field: 'hours_interval',
|
|
253
|
+
});
|
|
254
|
+
}
|
|
220
255
|
const apiClient = getApiClient();
|
|
221
256
|
const response = await apiClient.scheduleDeployment(project_id, {
|
|
222
257
|
environment: environment,
|
|
@@ -224,46 +259,33 @@ export const scheduleDeployment = async (args, ctx) => {
|
|
|
224
259
|
schedule_type: schedule_type,
|
|
225
260
|
scheduled_at: scheduledDate.toISOString(),
|
|
226
261
|
auto_trigger,
|
|
262
|
+
hours_interval: hoursInterval,
|
|
227
263
|
notes,
|
|
228
264
|
git_ref
|
|
229
265
|
});
|
|
230
266
|
if (!response.ok) {
|
|
231
|
-
|
|
267
|
+
return { result: { error: response.error || 'Failed to schedule deployment' }, isError: true };
|
|
232
268
|
}
|
|
233
269
|
return { result: response.data };
|
|
234
270
|
};
|
|
235
271
|
export const getScheduledDeployments = async (args, ctx) => {
|
|
236
|
-
const { project_id, include_disabled
|
|
237
|
-
validateRequired(project_id, 'project_id');
|
|
238
|
-
validateUUID(project_id, 'project_id');
|
|
272
|
+
const { project_id, include_disabled } = parseArgs(args, getScheduledDeploymentsSchema);
|
|
239
273
|
const apiClient = getApiClient();
|
|
240
274
|
const response = await apiClient.getScheduledDeployments(project_id, include_disabled);
|
|
241
275
|
if (!response.ok) {
|
|
242
|
-
|
|
276
|
+
return { result: { error: response.error || 'Failed to get scheduled deployments' }, isError: true };
|
|
243
277
|
}
|
|
244
278
|
return { result: response.data };
|
|
245
279
|
};
|
|
246
280
|
export const updateScheduledDeployment = async (args, ctx) => {
|
|
247
|
-
const { schedule_id, environment, version_bump, schedule_type, scheduled_at, auto_trigger, enabled, notes, git_ref, } = args;
|
|
248
|
-
validateRequired(schedule_id, 'schedule_id');
|
|
249
|
-
validateUUID(schedule_id, 'schedule_id');
|
|
281
|
+
const { schedule_id, environment, version_bump, schedule_type, scheduled_at, auto_trigger, hours_interval, enabled, notes, git_ref, } = parseArgs(args, updateScheduledDeploymentSchema);
|
|
250
282
|
const updates = {};
|
|
251
|
-
if (environment !== undefined)
|
|
252
|
-
validateEnvironment(environment);
|
|
283
|
+
if (environment !== undefined)
|
|
253
284
|
updates.environment = environment;
|
|
254
|
-
|
|
255
|
-
if (version_bump !== undefined) {
|
|
256
|
-
if (!['patch', 'minor', 'major'].includes(version_bump)) {
|
|
257
|
-
throw new ValidationError('Invalid version_bump value');
|
|
258
|
-
}
|
|
285
|
+
if (version_bump !== undefined)
|
|
259
286
|
updates.version_bump = version_bump;
|
|
260
|
-
|
|
261
|
-
if (schedule_type !== undefined) {
|
|
262
|
-
if (!['once', 'daily', 'weekly', 'monthly'].includes(schedule_type)) {
|
|
263
|
-
throw new ValidationError('Invalid schedule_type value');
|
|
264
|
-
}
|
|
287
|
+
if (schedule_type !== undefined)
|
|
265
288
|
updates.schedule_type = schedule_type;
|
|
266
|
-
}
|
|
267
289
|
if (scheduled_at !== undefined) {
|
|
268
290
|
const scheduledDate = new Date(scheduled_at);
|
|
269
291
|
if (isNaN(scheduledDate.getTime())) {
|
|
@@ -273,6 +295,12 @@ export const updateScheduledDeployment = async (args, ctx) => {
|
|
|
273
295
|
}
|
|
274
296
|
if (auto_trigger !== undefined)
|
|
275
297
|
updates.auto_trigger = auto_trigger;
|
|
298
|
+
if (hours_interval !== undefined) {
|
|
299
|
+
if (hours_interval < 1 || hours_interval > 24) {
|
|
300
|
+
throw new ValidationError('hours_interval must be between 1 and 24');
|
|
301
|
+
}
|
|
302
|
+
updates.hours_interval = hours_interval;
|
|
303
|
+
}
|
|
276
304
|
if (enabled !== undefined)
|
|
277
305
|
updates.enabled = enabled;
|
|
278
306
|
if (notes !== undefined)
|
|
@@ -285,41 +313,35 @@ export const updateScheduledDeployment = async (args, ctx) => {
|
|
|
285
313
|
const apiClient = getApiClient();
|
|
286
314
|
const response = await apiClient.updateScheduledDeployment(schedule_id, updates);
|
|
287
315
|
if (!response.ok) {
|
|
288
|
-
|
|
316
|
+
return { result: { error: response.error || 'Failed to update scheduled deployment' }, isError: true };
|
|
289
317
|
}
|
|
290
318
|
return { result: response.data };
|
|
291
319
|
};
|
|
292
320
|
export const deleteScheduledDeployment = async (args, ctx) => {
|
|
293
|
-
const { schedule_id } = args;
|
|
294
|
-
validateRequired(schedule_id, 'schedule_id');
|
|
295
|
-
validateUUID(schedule_id, 'schedule_id');
|
|
321
|
+
const { schedule_id } = parseArgs(args, deleteScheduledDeploymentSchema);
|
|
296
322
|
const apiClient = getApiClient();
|
|
297
323
|
const response = await apiClient.deleteScheduledDeployment(schedule_id);
|
|
298
324
|
if (!response.ok) {
|
|
299
|
-
|
|
325
|
+
return { result: { error: response.error || 'Failed to delete scheduled deployment' }, isError: true };
|
|
300
326
|
}
|
|
301
327
|
return { result: response.data };
|
|
302
328
|
};
|
|
303
329
|
export const triggerScheduledDeployment = async (args, ctx) => {
|
|
304
|
-
const { schedule_id } = args;
|
|
330
|
+
const { schedule_id } = parseArgs(args, triggerScheduledDeploymentSchema);
|
|
305
331
|
const { session } = ctx;
|
|
306
|
-
validateRequired(schedule_id, 'schedule_id');
|
|
307
|
-
validateUUID(schedule_id, 'schedule_id');
|
|
308
332
|
const apiClient = getApiClient();
|
|
309
333
|
const response = await apiClient.triggerScheduledDeployment(schedule_id, session.currentSessionId || undefined);
|
|
310
334
|
if (!response.ok) {
|
|
311
|
-
|
|
335
|
+
return { result: { error: response.error || 'Failed to trigger scheduled deployment' }, isError: true };
|
|
312
336
|
}
|
|
313
337
|
return { result: response.data };
|
|
314
338
|
};
|
|
315
339
|
export const checkDueDeployments = async (args, ctx) => {
|
|
316
|
-
const { project_id } = args;
|
|
317
|
-
validateRequired(project_id, 'project_id');
|
|
318
|
-
validateUUID(project_id, 'project_id');
|
|
340
|
+
const { project_id } = parseArgs(args, checkDueDeploymentsSchema);
|
|
319
341
|
const apiClient = getApiClient();
|
|
320
342
|
const response = await apiClient.checkDueDeployments(project_id);
|
|
321
343
|
if (!response.ok) {
|
|
322
|
-
|
|
344
|
+
return { result: { error: response.error || 'Failed to check due deployments' }, isError: true };
|
|
323
345
|
}
|
|
324
346
|
return { result: response.data };
|
|
325
347
|
};
|
|
@@ -9,6 +9,13 @@
|
|
|
9
9
|
* This saves ~8,000 tokens per schema load.
|
|
10
10
|
*/
|
|
11
11
|
import type { Handler, HandlerRegistry } from './types.js';
|
|
12
|
+
export declare const TOOL_CATEGORIES: Record<string, {
|
|
13
|
+
description: string;
|
|
14
|
+
tools: Array<{
|
|
15
|
+
name: string;
|
|
16
|
+
brief: string;
|
|
17
|
+
}>;
|
|
18
|
+
}>;
|
|
12
19
|
export declare const discoverTools: Handler;
|
|
13
20
|
export declare const getToolInfo: Handler;
|
|
14
21
|
/**
|
|
@@ -8,6 +8,14 @@
|
|
|
8
8
|
* Note: Tool documentation is lazy-loaded from tool-docs.ts to save tokens.
|
|
9
9
|
* This saves ~8,000 tokens per schema load.
|
|
10
10
|
*/
|
|
11
|
+
import { parseArgs } from '../validators.js';
|
|
12
|
+
// Argument schemas for type-safe parsing
|
|
13
|
+
const discoverToolsSchema = {
|
|
14
|
+
category: { type: 'string' },
|
|
15
|
+
};
|
|
16
|
+
const getToolInfoSchema = {
|
|
17
|
+
tool_name: { type: 'string', required: true },
|
|
18
|
+
};
|
|
11
19
|
// Lazy-loaded tool documentation cache
|
|
12
20
|
let toolInfoCache = null;
|
|
13
21
|
/**
|
|
@@ -22,8 +30,8 @@ async function getToolDocs() {
|
|
|
22
30
|
toolInfoCache = TOOL_INFO;
|
|
23
31
|
return toolInfoCache;
|
|
24
32
|
}
|
|
25
|
-
// Tool categories with brief descriptions
|
|
26
|
-
const TOOL_CATEGORIES = {
|
|
33
|
+
// Tool categories with brief descriptions (exported for documentation generation)
|
|
34
|
+
export const TOOL_CATEGORIES = {
|
|
27
35
|
session: {
|
|
28
36
|
description: 'Session lifecycle and monitoring',
|
|
29
37
|
tools: [
|
|
@@ -108,6 +116,7 @@ const TOOL_CATEGORIES = {
|
|
|
108
116
|
tools: [
|
|
109
117
|
{ name: 'add_finding', brief: 'Record audit finding' },
|
|
110
118
|
{ name: 'get_findings', brief: 'List findings' },
|
|
119
|
+
{ name: 'get_findings_stats', brief: 'Get findings statistics' },
|
|
111
120
|
{ name: 'update_finding', brief: 'Update finding status' },
|
|
112
121
|
{ name: 'delete_finding', brief: 'Remove finding' },
|
|
113
122
|
],
|
|
@@ -161,6 +170,26 @@ const TOOL_CATEGORIES = {
|
|
|
161
170
|
{ name: 'add_task_to_body_of_work', brief: 'Add task to group' },
|
|
162
171
|
{ name: 'remove_task_from_body_of_work', brief: 'Remove from group' },
|
|
163
172
|
{ name: 'activate_body_of_work', brief: 'Activate for work' },
|
|
173
|
+
{ name: 'add_task_dependency', brief: 'Add task dependency' },
|
|
174
|
+
{ name: 'remove_task_dependency', brief: 'Remove task dependency' },
|
|
175
|
+
{ name: 'get_task_dependencies', brief: 'List task dependencies' },
|
|
176
|
+
{ name: 'get_next_body_of_work_task', brief: 'Get next available task' },
|
|
177
|
+
],
|
|
178
|
+
},
|
|
179
|
+
sprints: {
|
|
180
|
+
description: 'Time-bounded sprints with velocity tracking',
|
|
181
|
+
tools: [
|
|
182
|
+
{ name: 'create_sprint', brief: 'Create new sprint' },
|
|
183
|
+
{ name: 'update_sprint', brief: 'Update sprint details' },
|
|
184
|
+
{ name: 'get_sprint', brief: 'Get sprint with tasks' },
|
|
185
|
+
{ name: 'get_sprints', brief: 'List project sprints' },
|
|
186
|
+
{ name: 'delete_sprint', brief: 'Delete sprint' },
|
|
187
|
+
{ name: 'start_sprint', brief: 'Start sprint' },
|
|
188
|
+
{ name: 'complete_sprint', brief: 'Complete sprint' },
|
|
189
|
+
{ name: 'add_task_to_sprint', brief: 'Add task to sprint' },
|
|
190
|
+
{ name: 'remove_task_from_sprint', brief: 'Remove from sprint' },
|
|
191
|
+
{ name: 'get_sprint_backlog', brief: 'Get available tasks' },
|
|
192
|
+
{ name: 'get_sprint_velocity', brief: 'Velocity metrics' },
|
|
164
193
|
],
|
|
165
194
|
},
|
|
166
195
|
requests: {
|
|
@@ -198,6 +227,17 @@ const TOOL_CATEGORIES = {
|
|
|
198
227
|
{ name: 'update_cost_alert', brief: 'Update alert config' },
|
|
199
228
|
{ name: 'delete_cost_alert', brief: 'Remove alert' },
|
|
200
229
|
{ name: 'get_task_costs', brief: 'Cost per task' },
|
|
230
|
+
{ name: 'get_body_of_work_costs', brief: 'Cost per body of work' },
|
|
231
|
+
{ name: 'get_sprint_costs', brief: 'Cost per sprint' },
|
|
232
|
+
],
|
|
233
|
+
},
|
|
234
|
+
git_issues: {
|
|
235
|
+
description: 'Git conflict and issue tracking',
|
|
236
|
+
tools: [
|
|
237
|
+
{ name: 'add_git_issue', brief: 'Record git issue' },
|
|
238
|
+
{ name: 'resolve_git_issue', brief: 'Mark resolved' },
|
|
239
|
+
{ name: 'get_git_issues', brief: 'List git issues' },
|
|
240
|
+
{ name: 'delete_git_issue', brief: 'Delete git issue' },
|
|
201
241
|
],
|
|
202
242
|
},
|
|
203
243
|
knowledge: {
|
|
@@ -206,9 +246,61 @@ const TOOL_CATEGORIES = {
|
|
|
206
246
|
{ name: 'query_knowledge_base', brief: 'Aggregated project knowledge in one call' },
|
|
207
247
|
],
|
|
208
248
|
},
|
|
249
|
+
discovery: {
|
|
250
|
+
description: 'Tool discovery and documentation',
|
|
251
|
+
tools: [
|
|
252
|
+
{ name: 'discover_tools', brief: 'List tools by category' },
|
|
253
|
+
{ name: 'get_tool_info', brief: 'Get detailed tool docs' },
|
|
254
|
+
],
|
|
255
|
+
},
|
|
256
|
+
subtasks: {
|
|
257
|
+
description: 'Break tasks into smaller pieces',
|
|
258
|
+
tools: [
|
|
259
|
+
{ name: 'add_subtask', brief: 'Add subtask to task' },
|
|
260
|
+
{ name: 'get_subtasks', brief: 'List task subtasks' },
|
|
261
|
+
],
|
|
262
|
+
},
|
|
263
|
+
worktrees: {
|
|
264
|
+
description: 'Git worktree management',
|
|
265
|
+
tools: [
|
|
266
|
+
{ name: 'get_stale_worktrees', brief: 'Find orphaned worktrees' },
|
|
267
|
+
{ name: 'clear_worktree_path', brief: 'Clear worktree from task' },
|
|
268
|
+
],
|
|
269
|
+
},
|
|
270
|
+
roles: {
|
|
271
|
+
description: 'Agent role management',
|
|
272
|
+
tools: [
|
|
273
|
+
{ name: 'get_role_settings', brief: 'Get project role settings' },
|
|
274
|
+
{ name: 'update_role_settings', brief: 'Configure role behavior' },
|
|
275
|
+
{ name: 'set_session_role', brief: 'Set session role' },
|
|
276
|
+
{ name: 'get_agents_by_role', brief: 'List agents by role' },
|
|
277
|
+
],
|
|
278
|
+
},
|
|
279
|
+
file_locks: {
|
|
280
|
+
description: 'File checkout/locking for multi-agent',
|
|
281
|
+
tools: [
|
|
282
|
+
{ name: 'checkout_file', brief: 'Lock file for editing' },
|
|
283
|
+
{ name: 'checkin_file', brief: 'Release file lock' },
|
|
284
|
+
{ name: 'get_file_checkouts', brief: 'List file locks' },
|
|
285
|
+
{ name: 'abandon_checkout', brief: 'Force-release lock' },
|
|
286
|
+
{ name: 'is_file_available', brief: 'Check if file is free' },
|
|
287
|
+
],
|
|
288
|
+
},
|
|
289
|
+
connectors: {
|
|
290
|
+
description: 'External integration connectors',
|
|
291
|
+
tools: [
|
|
292
|
+
{ name: 'get_connectors', brief: 'List project connectors' },
|
|
293
|
+
{ name: 'get_connector', brief: 'Get connector details' },
|
|
294
|
+
{ name: 'add_connector', brief: 'Create new connector' },
|
|
295
|
+
{ name: 'update_connector', brief: 'Update connector config' },
|
|
296
|
+
{ name: 'delete_connector', brief: 'Remove connector' },
|
|
297
|
+
{ name: 'test_connector', brief: 'Send test event' },
|
|
298
|
+
{ name: 'get_connector_events', brief: 'Event history' },
|
|
299
|
+
],
|
|
300
|
+
},
|
|
209
301
|
};
|
|
210
302
|
export const discoverTools = async (args) => {
|
|
211
|
-
const { category } = args;
|
|
303
|
+
const { category } = parseArgs(args, discoverToolsSchema);
|
|
212
304
|
if (category) {
|
|
213
305
|
// Return tools in specific category
|
|
214
306
|
const cat = TOOL_CATEGORIES[category];
|
|
@@ -243,10 +335,7 @@ export const discoverTools = async (args) => {
|
|
|
243
335
|
};
|
|
244
336
|
};
|
|
245
337
|
export const getToolInfo = async (args) => {
|
|
246
|
-
const { tool_name } = args;
|
|
247
|
-
if (!tool_name) {
|
|
248
|
-
return { result: { error: 'tool_name is required' } };
|
|
249
|
-
}
|
|
338
|
+
const { tool_name } = parseArgs(args, getToolInfoSchema);
|
|
250
339
|
// Lazy-load tool documentation
|
|
251
340
|
const toolDocs = await getToolDocs();
|
|
252
341
|
const info = toolDocs[tool_name];
|