@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,13 +17,78 @@
|
|
|
17
17
|
*
|
|
18
18
|
* MIGRATED: Uses Vibescope API client instead of direct Supabase
|
|
19
19
|
*/
|
|
20
|
-
import {
|
|
20
|
+
import { parseArgs, uuidValidator, createEnumValidator } from '../validators.js';
|
|
21
21
|
import { getApiClient } from '../api-client.js';
|
|
22
|
+
const BODY_OF_WORK_STATUSES = ['draft', 'active', 'completed', 'cancelled'];
|
|
23
|
+
const TASK_PHASES = ['pre', 'core', 'post'];
|
|
24
|
+
const DEPLOY_ENVIRONMENTS = ['development', 'staging', 'production'];
|
|
25
|
+
const VERSION_BUMPS = ['patch', 'minor', 'major'];
|
|
26
|
+
const DEPLOY_TRIGGERS = ['all_completed', 'all_completed_validated'];
|
|
27
|
+
// ============================================================================
|
|
28
|
+
// Argument Schemas
|
|
29
|
+
// ============================================================================
|
|
30
|
+
const createBodyOfWorkSchema = {
|
|
31
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
32
|
+
title: { type: 'string', required: true },
|
|
33
|
+
description: { type: 'string' },
|
|
34
|
+
auto_deploy_on_completion: { type: 'boolean' },
|
|
35
|
+
deploy_environment: { type: 'string', validate: createEnumValidator(DEPLOY_ENVIRONMENTS) },
|
|
36
|
+
deploy_version_bump: { type: 'string', validate: createEnumValidator(VERSION_BUMPS) },
|
|
37
|
+
deploy_trigger: { type: 'string', validate: createEnumValidator(DEPLOY_TRIGGERS) },
|
|
38
|
+
};
|
|
39
|
+
const updateBodyOfWorkSchema = {
|
|
40
|
+
body_of_work_id: { type: 'string', required: true, validate: uuidValidator },
|
|
41
|
+
title: { type: 'string' },
|
|
42
|
+
description: { type: 'string' },
|
|
43
|
+
auto_deploy_on_completion: { type: 'boolean' },
|
|
44
|
+
deploy_environment: { type: 'string', validate: createEnumValidator(DEPLOY_ENVIRONMENTS) },
|
|
45
|
+
deploy_version_bump: { type: 'string', validate: createEnumValidator(VERSION_BUMPS) },
|
|
46
|
+
deploy_trigger: { type: 'string', validate: createEnumValidator(DEPLOY_TRIGGERS) },
|
|
47
|
+
};
|
|
48
|
+
const getBodyOfWorkSchema = {
|
|
49
|
+
body_of_work_id: { type: 'string', required: true, validate: uuidValidator },
|
|
50
|
+
summary_only: { type: 'boolean', default: false },
|
|
51
|
+
};
|
|
52
|
+
const getBodiesOfWorkSchema = {
|
|
53
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
54
|
+
status: { type: 'string', validate: createEnumValidator(BODY_OF_WORK_STATUSES) },
|
|
55
|
+
limit: { type: 'number', default: 50 },
|
|
56
|
+
offset: { type: 'number', default: 0 },
|
|
57
|
+
search_query: { type: 'string' },
|
|
58
|
+
};
|
|
59
|
+
const deleteBodyOfWorkSchema = {
|
|
60
|
+
body_of_work_id: { type: 'string', required: true, validate: uuidValidator },
|
|
61
|
+
};
|
|
62
|
+
const addTaskToBodyOfWorkSchema = {
|
|
63
|
+
body_of_work_id: { type: 'string', required: true, validate: uuidValidator },
|
|
64
|
+
task_id: { type: 'string', required: true, validate: uuidValidator },
|
|
65
|
+
phase: { type: 'string', validate: createEnumValidator(TASK_PHASES) },
|
|
66
|
+
order_index: { type: 'number' },
|
|
67
|
+
};
|
|
68
|
+
const removeTaskFromBodyOfWorkSchema = {
|
|
69
|
+
task_id: { type: 'string', required: true, validate: uuidValidator },
|
|
70
|
+
};
|
|
71
|
+
const activateBodyOfWorkSchema = {
|
|
72
|
+
body_of_work_id: { type: 'string', required: true, validate: uuidValidator },
|
|
73
|
+
};
|
|
74
|
+
const addTaskDependencySchema = {
|
|
75
|
+
body_of_work_id: { type: 'string', required: true, validate: uuidValidator },
|
|
76
|
+
task_id: { type: 'string', required: true, validate: uuidValidator },
|
|
77
|
+
depends_on_task_id: { type: 'string', required: true, validate: uuidValidator },
|
|
78
|
+
};
|
|
79
|
+
const removeTaskDependencySchema = {
|
|
80
|
+
task_id: { type: 'string', required: true, validate: uuidValidator },
|
|
81
|
+
depends_on_task_id: { type: 'string', required: true, validate: uuidValidator },
|
|
82
|
+
};
|
|
83
|
+
const getTaskDependenciesSchema = {
|
|
84
|
+
body_of_work_id: { type: 'string', validate: uuidValidator },
|
|
85
|
+
task_id: { type: 'string', validate: uuidValidator },
|
|
86
|
+
};
|
|
87
|
+
const getNextBodyOfWorkTaskSchema = {
|
|
88
|
+
body_of_work_id: { type: 'string', required: true, validate: uuidValidator },
|
|
89
|
+
};
|
|
22
90
|
export const createBodyOfWork = async (args, ctx) => {
|
|
23
|
-
const { project_id, title, description, auto_deploy_on_completion, deploy_environment, deploy_version_bump, deploy_trigger, } = args;
|
|
24
|
-
validateRequired(project_id, 'project_id');
|
|
25
|
-
validateUUID(project_id, 'project_id');
|
|
26
|
-
validateRequired(title, 'title');
|
|
91
|
+
const { project_id, title, description, auto_deploy_on_completion, deploy_environment, deploy_version_bump, deploy_trigger, } = parseArgs(args, createBodyOfWorkSchema);
|
|
27
92
|
const { session } = ctx;
|
|
28
93
|
const apiClient = getApiClient();
|
|
29
94
|
const response = await apiClient.proxy('create_body_of_work', {
|
|
@@ -40,7 +105,7 @@ export const createBodyOfWork = async (args, ctx) => {
|
|
|
40
105
|
instance_id: session.instanceId
|
|
41
106
|
});
|
|
42
107
|
if (!response.ok) {
|
|
43
|
-
|
|
108
|
+
return { result: { error: response.error || 'Failed to create body of work' }, isError: true };
|
|
44
109
|
}
|
|
45
110
|
return {
|
|
46
111
|
result: {
|
|
@@ -53,9 +118,7 @@ export const createBodyOfWork = async (args, ctx) => {
|
|
|
53
118
|
};
|
|
54
119
|
};
|
|
55
120
|
export const updateBodyOfWork = async (args, ctx) => {
|
|
56
|
-
const { body_of_work_id, title, description, auto_deploy_on_completion, deploy_environment, deploy_version_bump, deploy_trigger, } = args;
|
|
57
|
-
validateRequired(body_of_work_id, 'body_of_work_id');
|
|
58
|
-
validateUUID(body_of_work_id, 'body_of_work_id');
|
|
121
|
+
const { body_of_work_id, title, description, auto_deploy_on_completion, deploy_environment, deploy_version_bump, deploy_trigger, } = parseArgs(args, updateBodyOfWorkSchema);
|
|
59
122
|
// Check if any updates provided
|
|
60
123
|
if (title === undefined && description === undefined && auto_deploy_on_completion === undefined &&
|
|
61
124
|
deploy_environment === undefined && deploy_version_bump === undefined && deploy_trigger === undefined) {
|
|
@@ -72,58 +135,48 @@ export const updateBodyOfWork = async (args, ctx) => {
|
|
|
72
135
|
deploy_trigger
|
|
73
136
|
});
|
|
74
137
|
if (!response.ok) {
|
|
75
|
-
|
|
138
|
+
return { result: { error: response.error || 'Failed to update body of work' }, isError: true };
|
|
76
139
|
}
|
|
77
140
|
return { result: { success: true, body_of_work_id } };
|
|
78
141
|
};
|
|
79
142
|
export const getBodyOfWork = async (args, ctx) => {
|
|
80
|
-
const { body_of_work_id, summary_only
|
|
81
|
-
validateRequired(body_of_work_id, 'body_of_work_id');
|
|
82
|
-
validateUUID(body_of_work_id, 'body_of_work_id');
|
|
143
|
+
const { body_of_work_id, summary_only } = parseArgs(args, getBodyOfWorkSchema);
|
|
83
144
|
const apiClient = getApiClient();
|
|
84
145
|
// Response type varies based on summary_only
|
|
85
146
|
const response = await apiClient.proxy('get_body_of_work', { body_of_work_id, summary_only });
|
|
86
147
|
if (!response.ok) {
|
|
87
|
-
|
|
148
|
+
return { result: { error: response.error || 'Failed to get body of work' }, isError: true };
|
|
88
149
|
}
|
|
89
150
|
return { result: response.data };
|
|
90
151
|
};
|
|
91
152
|
export const getBodiesOfWork = async (args, ctx) => {
|
|
92
|
-
const { project_id, status, limit
|
|
93
|
-
validateRequired(project_id, 'project_id');
|
|
94
|
-
validateUUID(project_id, 'project_id');
|
|
153
|
+
const { project_id, status, limit, offset, search_query } = parseArgs(args, getBodiesOfWorkSchema);
|
|
95
154
|
const apiClient = getApiClient();
|
|
96
155
|
const response = await apiClient.proxy('get_bodies_of_work', {
|
|
97
156
|
project_id,
|
|
98
157
|
status,
|
|
99
|
-
limit: Math.min(limit, 100),
|
|
158
|
+
limit: Math.min(limit ?? 50, 100),
|
|
100
159
|
offset,
|
|
101
160
|
search_query
|
|
102
161
|
});
|
|
103
162
|
if (!response.ok) {
|
|
104
|
-
|
|
163
|
+
return { result: { error: response.error || 'Failed to fetch bodies of work' }, isError: true };
|
|
105
164
|
}
|
|
106
165
|
return { result: response.data };
|
|
107
166
|
};
|
|
108
167
|
export const deleteBodyOfWork = async (args, ctx) => {
|
|
109
|
-
const { body_of_work_id } = args;
|
|
110
|
-
validateRequired(body_of_work_id, 'body_of_work_id');
|
|
111
|
-
validateUUID(body_of_work_id, 'body_of_work_id');
|
|
168
|
+
const { body_of_work_id } = parseArgs(args, deleteBodyOfWorkSchema);
|
|
112
169
|
const apiClient = getApiClient();
|
|
113
170
|
const response = await apiClient.proxy('delete_body_of_work', {
|
|
114
171
|
body_of_work_id
|
|
115
172
|
});
|
|
116
173
|
if (!response.ok) {
|
|
117
|
-
|
|
174
|
+
return { result: { error: response.error || 'Failed to delete body of work' }, isError: true };
|
|
118
175
|
}
|
|
119
176
|
return { result: { success: true, message: 'Body of work deleted. Tasks are preserved.' } };
|
|
120
177
|
};
|
|
121
178
|
export const addTaskToBodyOfWork = async (args, ctx) => {
|
|
122
|
-
const { body_of_work_id, task_id, phase, order_index } = args;
|
|
123
|
-
validateRequired(body_of_work_id, 'body_of_work_id');
|
|
124
|
-
validateUUID(body_of_work_id, 'body_of_work_id');
|
|
125
|
-
validateRequired(task_id, 'task_id');
|
|
126
|
-
validateUUID(task_id, 'task_id');
|
|
179
|
+
const { body_of_work_id, task_id, phase, order_index } = parseArgs(args, addTaskToBodyOfWorkSchema);
|
|
127
180
|
const apiClient = getApiClient();
|
|
128
181
|
const response = await apiClient.proxy('add_task_to_body_of_work', {
|
|
129
182
|
body_of_work_id,
|
|
@@ -132,42 +185,32 @@ export const addTaskToBodyOfWork = async (args, ctx) => {
|
|
|
132
185
|
order_index
|
|
133
186
|
});
|
|
134
187
|
if (!response.ok) {
|
|
135
|
-
|
|
188
|
+
return { result: { error: response.error || 'Failed to add task to body of work' }, isError: true };
|
|
136
189
|
}
|
|
137
190
|
return { result: response.data };
|
|
138
191
|
};
|
|
139
192
|
export const removeTaskFromBodyOfWork = async (args, ctx) => {
|
|
140
|
-
const { task_id } = args;
|
|
141
|
-
validateRequired(task_id, 'task_id');
|
|
142
|
-
validateUUID(task_id, 'task_id');
|
|
193
|
+
const { task_id } = parseArgs(args, removeTaskFromBodyOfWorkSchema);
|
|
143
194
|
const apiClient = getApiClient();
|
|
144
195
|
const response = await apiClient.proxy('remove_task_from_body_of_work', { task_id });
|
|
145
196
|
if (!response.ok) {
|
|
146
|
-
|
|
197
|
+
return { result: { error: response.error || 'Failed to remove task from body of work' }, isError: true };
|
|
147
198
|
}
|
|
148
199
|
return { result: response.data };
|
|
149
200
|
};
|
|
150
201
|
export const activateBodyOfWork = async (args, ctx) => {
|
|
151
|
-
const { body_of_work_id } = args;
|
|
152
|
-
validateRequired(body_of_work_id, 'body_of_work_id');
|
|
153
|
-
validateUUID(body_of_work_id, 'body_of_work_id');
|
|
202
|
+
const { body_of_work_id } = parseArgs(args, activateBodyOfWorkSchema);
|
|
154
203
|
const apiClient = getApiClient();
|
|
155
204
|
const response = await apiClient.proxy('activate_body_of_work', { body_of_work_id });
|
|
156
205
|
if (!response.ok) {
|
|
157
|
-
|
|
206
|
+
return { result: { error: response.error || 'Failed to activate body of work' }, isError: true };
|
|
158
207
|
}
|
|
159
208
|
return { result: response.data };
|
|
160
209
|
};
|
|
161
210
|
export const addTaskDependency = async (args, ctx) => {
|
|
162
|
-
const { body_of_work_id, task_id, depends_on_task_id } = args;
|
|
163
|
-
validateRequired(body_of_work_id, 'body_of_work_id');
|
|
164
|
-
validateUUID(body_of_work_id, 'body_of_work_id');
|
|
165
|
-
validateRequired(task_id, 'task_id');
|
|
166
|
-
validateUUID(task_id, 'task_id');
|
|
167
|
-
validateRequired(depends_on_task_id, 'depends_on_task_id');
|
|
168
|
-
validateUUID(depends_on_task_id, 'depends_on_task_id');
|
|
211
|
+
const { body_of_work_id, task_id, depends_on_task_id } = parseArgs(args, addTaskDependencySchema);
|
|
169
212
|
if (task_id === depends_on_task_id) {
|
|
170
|
-
|
|
213
|
+
return { result: { error: 'A task cannot depend on itself' }, isError: true };
|
|
171
214
|
}
|
|
172
215
|
const apiClient = getApiClient();
|
|
173
216
|
const response = await apiClient.proxy('add_task_dependency', {
|
|
@@ -176,53 +219,43 @@ export const addTaskDependency = async (args, ctx) => {
|
|
|
176
219
|
depends_on_task_id
|
|
177
220
|
});
|
|
178
221
|
if (!response.ok) {
|
|
179
|
-
|
|
222
|
+
return { result: { error: response.error || 'Failed to add task dependency' }, isError: true };
|
|
180
223
|
}
|
|
181
224
|
return { result: response.data };
|
|
182
225
|
};
|
|
183
226
|
export const removeTaskDependency = async (args, ctx) => {
|
|
184
|
-
const { task_id, depends_on_task_id } = args;
|
|
185
|
-
validateRequired(task_id, 'task_id');
|
|
186
|
-
validateUUID(task_id, 'task_id');
|
|
187
|
-
validateRequired(depends_on_task_id, 'depends_on_task_id');
|
|
188
|
-
validateUUID(depends_on_task_id, 'depends_on_task_id');
|
|
227
|
+
const { task_id, depends_on_task_id } = parseArgs(args, removeTaskDependencySchema);
|
|
189
228
|
const apiClient = getApiClient();
|
|
190
229
|
const response = await apiClient.proxy('remove_task_dependency', {
|
|
191
230
|
task_id,
|
|
192
231
|
depends_on_task_id
|
|
193
232
|
});
|
|
194
233
|
if (!response.ok) {
|
|
195
|
-
|
|
234
|
+
return { result: { error: response.error || 'Failed to remove task dependency' }, isError: true };
|
|
196
235
|
}
|
|
197
236
|
return { result: response.data };
|
|
198
237
|
};
|
|
199
238
|
export const getTaskDependencies = async (args, ctx) => {
|
|
200
|
-
const { body_of_work_id, task_id } = args;
|
|
239
|
+
const { body_of_work_id, task_id } = parseArgs(args, getTaskDependenciesSchema);
|
|
201
240
|
if (!body_of_work_id && !task_id) {
|
|
202
|
-
|
|
241
|
+
return { result: { error: 'Either body_of_work_id or task_id is required' }, isError: true };
|
|
203
242
|
}
|
|
204
|
-
if (body_of_work_id)
|
|
205
|
-
validateUUID(body_of_work_id, 'body_of_work_id');
|
|
206
|
-
if (task_id)
|
|
207
|
-
validateUUID(task_id, 'task_id');
|
|
208
243
|
const apiClient = getApiClient();
|
|
209
244
|
const response = await apiClient.proxy('get_task_dependencies', {
|
|
210
245
|
body_of_work_id,
|
|
211
246
|
task_id
|
|
212
247
|
});
|
|
213
248
|
if (!response.ok) {
|
|
214
|
-
|
|
249
|
+
return { result: { error: response.error || 'Failed to fetch task dependencies' }, isError: true };
|
|
215
250
|
}
|
|
216
251
|
return { result: response.data };
|
|
217
252
|
};
|
|
218
253
|
export const getNextBodyOfWorkTask = async (args, ctx) => {
|
|
219
|
-
const { body_of_work_id } = args;
|
|
220
|
-
validateRequired(body_of_work_id, 'body_of_work_id');
|
|
221
|
-
validateUUID(body_of_work_id, 'body_of_work_id');
|
|
254
|
+
const { body_of_work_id } = parseArgs(args, getNextBodyOfWorkTaskSchema);
|
|
222
255
|
const apiClient = getApiClient();
|
|
223
256
|
const response = await apiClient.proxy('get_next_body_of_work_task', { body_of_work_id });
|
|
224
257
|
if (!response.ok) {
|
|
225
|
-
|
|
258
|
+
return { result: { error: response.error || 'Failed to get next body of work task' }, isError: true };
|
|
226
259
|
}
|
|
227
260
|
return { result: response.data };
|
|
228
261
|
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connectors Handlers
|
|
3
|
+
*
|
|
4
|
+
* Handles external integration management:
|
|
5
|
+
* - get_connectors
|
|
6
|
+
* - get_connector
|
|
7
|
+
* - add_connector
|
|
8
|
+
* - update_connector
|
|
9
|
+
* - delete_connector
|
|
10
|
+
* - test_connector
|
|
11
|
+
* - get_connector_events
|
|
12
|
+
*/
|
|
13
|
+
import type { Handler, HandlerRegistry } from './types.js';
|
|
14
|
+
/**
|
|
15
|
+
* Get all connectors for a project
|
|
16
|
+
*/
|
|
17
|
+
export declare const getConnectors: Handler;
|
|
18
|
+
/**
|
|
19
|
+
* Get a single connector with full details
|
|
20
|
+
*/
|
|
21
|
+
export declare const getConnector: Handler;
|
|
22
|
+
/**
|
|
23
|
+
* Add a new connector
|
|
24
|
+
*/
|
|
25
|
+
export declare const addConnector: Handler;
|
|
26
|
+
/**
|
|
27
|
+
* Update a connector
|
|
28
|
+
*/
|
|
29
|
+
export declare const updateConnector: Handler;
|
|
30
|
+
/**
|
|
31
|
+
* Delete a connector
|
|
32
|
+
*/
|
|
33
|
+
export declare const deleteConnector: Handler;
|
|
34
|
+
/**
|
|
35
|
+
* Test a connector by sending a test event
|
|
36
|
+
*/
|
|
37
|
+
export declare const testConnector: Handler;
|
|
38
|
+
/**
|
|
39
|
+
* Get connector event history
|
|
40
|
+
*/
|
|
41
|
+
export declare const getConnectorEvents: Handler;
|
|
42
|
+
/**
|
|
43
|
+
* Connectors handlers registry
|
|
44
|
+
*/
|
|
45
|
+
export declare const connectorHandlers: HandlerRegistry;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connectors Handlers
|
|
3
|
+
*
|
|
4
|
+
* Handles external integration management:
|
|
5
|
+
* - get_connectors
|
|
6
|
+
* - get_connector
|
|
7
|
+
* - add_connector
|
|
8
|
+
* - update_connector
|
|
9
|
+
* - delete_connector
|
|
10
|
+
* - test_connector
|
|
11
|
+
* - get_connector_events
|
|
12
|
+
*/
|
|
13
|
+
import { success, error } from './types.js';
|
|
14
|
+
import { parseArgs, uuidValidator, createEnumValidator, } from '../validators.js';
|
|
15
|
+
import { getApiClient } from '../api-client.js';
|
|
16
|
+
// Valid connector types
|
|
17
|
+
const VALID_CONNECTOR_TYPES = ['webhook', 'slack', 'discord', 'github', 'custom'];
|
|
18
|
+
// Valid connector statuses
|
|
19
|
+
const VALID_CONNECTOR_STATUSES = ['active', 'disabled'];
|
|
20
|
+
// Valid event statuses
|
|
21
|
+
const VALID_EVENT_STATUSES = ['pending', 'sent', 'failed', 'retrying'];
|
|
22
|
+
// Argument schemas for type-safe parsing
|
|
23
|
+
const getConnectorsSchema = {
|
|
24
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
25
|
+
type: { type: 'string', validate: createEnumValidator(VALID_CONNECTOR_TYPES) },
|
|
26
|
+
status: { type: 'string', validate: createEnumValidator(VALID_CONNECTOR_STATUSES) },
|
|
27
|
+
limit: { type: 'number', default: 50 },
|
|
28
|
+
offset: { type: 'number', default: 0 },
|
|
29
|
+
};
|
|
30
|
+
const getConnectorSchema = {
|
|
31
|
+
connector_id: { type: 'string', required: true, validate: uuidValidator },
|
|
32
|
+
};
|
|
33
|
+
const addConnectorSchema = {
|
|
34
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
35
|
+
name: { type: 'string', required: true },
|
|
36
|
+
type: { type: 'string', required: true, validate: createEnumValidator(VALID_CONNECTOR_TYPES) },
|
|
37
|
+
description: { type: 'string' },
|
|
38
|
+
config: { type: 'object' },
|
|
39
|
+
events: { type: 'object' },
|
|
40
|
+
};
|
|
41
|
+
const updateConnectorSchema = {
|
|
42
|
+
connector_id: { type: 'string', required: true, validate: uuidValidator },
|
|
43
|
+
name: { type: 'string' },
|
|
44
|
+
description: { type: 'string' },
|
|
45
|
+
config: { type: 'object' },
|
|
46
|
+
events: { type: 'object' },
|
|
47
|
+
status: { type: 'string', validate: createEnumValidator(VALID_CONNECTOR_STATUSES) },
|
|
48
|
+
};
|
|
49
|
+
const deleteConnectorSchema = {
|
|
50
|
+
connector_id: { type: 'string', required: true, validate: uuidValidator },
|
|
51
|
+
};
|
|
52
|
+
const testConnectorSchema = {
|
|
53
|
+
connector_id: { type: 'string', required: true, validate: uuidValidator },
|
|
54
|
+
};
|
|
55
|
+
const getConnectorEventsSchema = {
|
|
56
|
+
connector_id: { type: 'string', validate: uuidValidator },
|
|
57
|
+
project_id: { type: 'string', validate: uuidValidator },
|
|
58
|
+
status: { type: 'string', validate: createEnumValidator(VALID_EVENT_STATUSES) },
|
|
59
|
+
limit: { type: 'number', default: 50 },
|
|
60
|
+
offset: { type: 'number', default: 0 },
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Get all connectors for a project
|
|
64
|
+
*/
|
|
65
|
+
export const getConnectors = async (args, _ctx) => {
|
|
66
|
+
const { project_id, type, status, limit, offset } = parseArgs(args, getConnectorsSchema);
|
|
67
|
+
const apiClient = getApiClient();
|
|
68
|
+
const response = await apiClient.getConnectors(project_id, {
|
|
69
|
+
type,
|
|
70
|
+
status,
|
|
71
|
+
limit,
|
|
72
|
+
offset
|
|
73
|
+
});
|
|
74
|
+
if (!response.ok) {
|
|
75
|
+
return error(response.error || 'Failed to fetch connectors');
|
|
76
|
+
}
|
|
77
|
+
return success(response.data);
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Get a single connector with full details
|
|
81
|
+
*/
|
|
82
|
+
export const getConnector = async (args, _ctx) => {
|
|
83
|
+
const { connector_id } = parseArgs(args, getConnectorSchema);
|
|
84
|
+
const apiClient = getApiClient();
|
|
85
|
+
const response = await apiClient.getConnector(connector_id);
|
|
86
|
+
if (!response.ok) {
|
|
87
|
+
return error(response.error || 'Failed to fetch connector');
|
|
88
|
+
}
|
|
89
|
+
return success(response.data);
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Add a new connector
|
|
93
|
+
*/
|
|
94
|
+
export const addConnector = async (args, _ctx) => {
|
|
95
|
+
const { project_id, name, type, description, config, events } = parseArgs(args, addConnectorSchema);
|
|
96
|
+
const apiClient = getApiClient();
|
|
97
|
+
const response = await apiClient.addConnector(project_id, {
|
|
98
|
+
name,
|
|
99
|
+
type,
|
|
100
|
+
description,
|
|
101
|
+
config: config,
|
|
102
|
+
events: events
|
|
103
|
+
});
|
|
104
|
+
if (!response.ok) {
|
|
105
|
+
return error(response.error || 'Failed to create connector');
|
|
106
|
+
}
|
|
107
|
+
return success(response.data);
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Update a connector
|
|
111
|
+
*/
|
|
112
|
+
export const updateConnector = async (args, _ctx) => {
|
|
113
|
+
const { connector_id, name, description, config, events, status } = parseArgs(args, updateConnectorSchema);
|
|
114
|
+
const apiClient = getApiClient();
|
|
115
|
+
const response = await apiClient.updateConnector(connector_id, {
|
|
116
|
+
name,
|
|
117
|
+
description,
|
|
118
|
+
config: config,
|
|
119
|
+
events: events,
|
|
120
|
+
status
|
|
121
|
+
});
|
|
122
|
+
if (!response.ok) {
|
|
123
|
+
return error(response.error || 'Failed to update connector');
|
|
124
|
+
}
|
|
125
|
+
return success(response.data);
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Delete a connector
|
|
129
|
+
*/
|
|
130
|
+
export const deleteConnector = async (args, _ctx) => {
|
|
131
|
+
const { connector_id } = parseArgs(args, deleteConnectorSchema);
|
|
132
|
+
const apiClient = getApiClient();
|
|
133
|
+
const response = await apiClient.deleteConnector(connector_id);
|
|
134
|
+
if (!response.ok) {
|
|
135
|
+
return error(response.error || 'Failed to delete connector');
|
|
136
|
+
}
|
|
137
|
+
return success(response.data);
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* Test a connector by sending a test event
|
|
141
|
+
*/
|
|
142
|
+
export const testConnector = async (args, _ctx) => {
|
|
143
|
+
const { connector_id } = parseArgs(args, testConnectorSchema);
|
|
144
|
+
const apiClient = getApiClient();
|
|
145
|
+
const response = await apiClient.testConnector(connector_id);
|
|
146
|
+
if (!response.ok) {
|
|
147
|
+
return error(response.error || 'Failed to test connector');
|
|
148
|
+
}
|
|
149
|
+
return success(response.data);
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* Get connector event history
|
|
153
|
+
*/
|
|
154
|
+
export const getConnectorEvents = async (args, _ctx) => {
|
|
155
|
+
const { connector_id, project_id, status, limit, offset } = parseArgs(args, getConnectorEventsSchema);
|
|
156
|
+
if (!connector_id && !project_id) {
|
|
157
|
+
return error('Either connector_id or project_id is required');
|
|
158
|
+
}
|
|
159
|
+
const apiClient = getApiClient();
|
|
160
|
+
const response = await apiClient.getConnectorEvents({
|
|
161
|
+
connector_id,
|
|
162
|
+
project_id,
|
|
163
|
+
status,
|
|
164
|
+
limit,
|
|
165
|
+
offset
|
|
166
|
+
});
|
|
167
|
+
if (!response.ok) {
|
|
168
|
+
return error(response.error || 'Failed to fetch connector events');
|
|
169
|
+
}
|
|
170
|
+
return success(response.data);
|
|
171
|
+
};
|
|
172
|
+
/**
|
|
173
|
+
* Connectors handlers registry
|
|
174
|
+
*/
|
|
175
|
+
export const connectorHandlers = {
|
|
176
|
+
get_connectors: getConnectors,
|
|
177
|
+
get_connector: getConnector,
|
|
178
|
+
add_connector: addConnector,
|
|
179
|
+
update_connector: updateConnector,
|
|
180
|
+
delete_connector: deleteConnector,
|
|
181
|
+
test_connector: testConnector,
|
|
182
|
+
get_connector_events: getConnectorEvents,
|
|
183
|
+
};
|
package/dist/handlers/cost.d.ts
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
* - update_cost_alert
|
|
9
9
|
* - delete_cost_alert
|
|
10
10
|
* - get_task_costs
|
|
11
|
+
* - get_body_of_work_costs
|
|
12
|
+
* - get_sprint_costs
|
|
11
13
|
*/
|
|
12
14
|
import type { Handler, HandlerRegistry } from './types.js';
|
|
13
15
|
/**
|
|
@@ -34,6 +36,14 @@ export declare const deleteCostAlert: Handler;
|
|
|
34
36
|
* Get task costs for a project
|
|
35
37
|
*/
|
|
36
38
|
export declare const getTaskCosts: Handler;
|
|
39
|
+
/**
|
|
40
|
+
* Get body of work costs with phase breakdown
|
|
41
|
+
*/
|
|
42
|
+
export declare const getBodyOfWorkCosts: Handler;
|
|
43
|
+
/**
|
|
44
|
+
* Get sprint costs with velocity metrics
|
|
45
|
+
*/
|
|
46
|
+
export declare const getSprintCosts: Handler;
|
|
37
47
|
/**
|
|
38
48
|
* Cost handlers registry
|
|
39
49
|
*/
|