@vibescope/mcp-server 0.1.0 → 0.2.1
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 +1 -1
- package/dist/api-client.d.ts +120 -2
- package/dist/api-client.js +51 -5
- package/dist/handlers/bodies-of-work.js +84 -50
- package/dist/handlers/cost.js +62 -54
- package/dist/handlers/decisions.js +29 -16
- package/dist/handlers/deployment.js +114 -107
- package/dist/handlers/discovery.d.ts +3 -0
- package/dist/handlers/discovery.js +55 -657
- package/dist/handlers/fallback.js +42 -28
- package/dist/handlers/file-checkouts.d.ts +18 -0
- package/dist/handlers/file-checkouts.js +101 -0
- package/dist/handlers/findings.d.ts +14 -1
- package/dist/handlers/findings.js +104 -28
- package/dist/handlers/git-issues.js +36 -32
- package/dist/handlers/ideas.js +44 -26
- package/dist/handlers/index.d.ts +2 -0
- package/dist/handlers/index.js +6 -0
- package/dist/handlers/milestones.js +34 -27
- package/dist/handlers/organizations.js +86 -78
- package/dist/handlers/progress.js +22 -11
- package/dist/handlers/project.js +62 -22
- package/dist/handlers/requests.js +15 -11
- package/dist/handlers/roles.d.ts +18 -0
- package/dist/handlers/roles.js +130 -0
- package/dist/handlers/session.js +52 -15
- package/dist/handlers/sprints.js +78 -65
- package/dist/handlers/tasks.js +135 -74
- package/dist/handlers/tool-docs.d.ts +4 -3
- package/dist/handlers/tool-docs.js +252 -5
- package/dist/handlers/validation.js +30 -14
- package/dist/index.js +25 -7
- package/dist/tools.js +417 -4
- package/package.json +1 -1
- package/src/api-client.ts +161 -8
- package/src/handlers/__test-setup__.ts +12 -0
- package/src/handlers/bodies-of-work.ts +127 -111
- package/src/handlers/cost.test.ts +34 -44
- package/src/handlers/cost.ts +77 -92
- package/src/handlers/decisions.test.ts +3 -2
- package/src/handlers/decisions.ts +32 -27
- package/src/handlers/deployment.ts +144 -190
- package/src/handlers/discovery.test.ts +4 -5
- package/src/handlers/discovery.ts +60 -746
- package/src/handlers/fallback.test.ts +78 -0
- package/src/handlers/fallback.ts +51 -38
- package/src/handlers/file-checkouts.test.ts +477 -0
- package/src/handlers/file-checkouts.ts +127 -0
- package/src/handlers/findings.test.ts +274 -2
- package/src/handlers/findings.ts +123 -57
- package/src/handlers/git-issues.ts +40 -80
- package/src/handlers/ideas.ts +56 -54
- package/src/handlers/index.ts +6 -0
- package/src/handlers/milestones.test.ts +1 -1
- package/src/handlers/milestones.ts +47 -45
- package/src/handlers/organizations.ts +104 -129
- package/src/handlers/progress.ts +24 -22
- package/src/handlers/project.ts +89 -57
- package/src/handlers/requests.ts +18 -14
- package/src/handlers/roles.test.ts +303 -0
- package/src/handlers/roles.ts +208 -0
- package/src/handlers/session.test.ts +37 -2
- package/src/handlers/session.ts +64 -21
- package/src/handlers/sprints.ts +114 -134
- package/src/handlers/tasks.test.ts +61 -0
- package/src/handlers/tasks.ts +170 -139
- package/src/handlers/tool-docs.ts +1024 -0
- package/src/handlers/validation.test.ts +53 -1
- package/src/handlers/validation.ts +32 -21
- package/src/index.ts +25 -7
- package/src/tools.ts +417 -4
- 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
- package/src/knowledge.ts +0 -230
|
@@ -18,22 +18,91 @@
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
import type { Handler, HandlerRegistry } from './types.js';
|
|
21
|
-
import {
|
|
21
|
+
import { parseArgs, uuidValidator, createEnumValidator, ValidationError } from '../validators.js';
|
|
22
22
|
import { getApiClient } from '../api-client.js';
|
|
23
23
|
|
|
24
24
|
// Valid roles in order of permission level
|
|
25
25
|
const ROLE_ORDER = ['viewer', 'member', 'admin', 'owner'] as const;
|
|
26
|
+
const ASSIGNABLE_ROLES = ['viewer', 'member', 'admin'] as const;
|
|
26
27
|
type Role = (typeof ROLE_ORDER)[number];
|
|
28
|
+
type AssignableRole = (typeof ASSIGNABLE_ROLES)[number];
|
|
27
29
|
|
|
28
30
|
// Valid share permissions
|
|
29
31
|
const PERMISSION_ORDER = ['read', 'write', 'admin'] as const;
|
|
30
32
|
type Permission = (typeof PERMISSION_ORDER)[number];
|
|
31
33
|
|
|
34
|
+
// ============================================================================
|
|
35
|
+
// Argument Schemas
|
|
36
|
+
// ============================================================================
|
|
37
|
+
|
|
38
|
+
const createOrganizationSchema = {
|
|
39
|
+
name: { type: 'string' as const, required: true as const },
|
|
40
|
+
description: { type: 'string' as const },
|
|
41
|
+
slug: { type: 'string' as const },
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const updateOrganizationSchema = {
|
|
45
|
+
organization_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
46
|
+
name: { type: 'string' as const },
|
|
47
|
+
description: { type: 'string' as const },
|
|
48
|
+
logo_url: { type: 'string' as const },
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const deleteOrganizationSchema = {
|
|
52
|
+
organization_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const listOrgMembersSchema = {
|
|
56
|
+
organization_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const inviteMemberSchema = {
|
|
60
|
+
organization_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
61
|
+
email: { type: 'string' as const, required: true as const },
|
|
62
|
+
role: { type: 'string' as const, default: 'member', validate: createEnumValidator(ASSIGNABLE_ROLES) },
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const updateMemberRoleSchema = {
|
|
66
|
+
organization_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
67
|
+
user_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
68
|
+
role: { type: 'string' as const, required: true as const, validate: createEnumValidator(ROLE_ORDER) },
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const removeMemberSchema = {
|
|
72
|
+
organization_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
73
|
+
user_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const leaveOrganizationSchema = {
|
|
77
|
+
organization_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const shareProjectWithOrgSchema = {
|
|
81
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
82
|
+
organization_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
83
|
+
permission: { type: 'string' as const, default: 'read', validate: createEnumValidator(PERMISSION_ORDER) },
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const updateProjectShareSchema = {
|
|
87
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
88
|
+
organization_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
89
|
+
permission: { type: 'string' as const, required: true as const, validate: createEnumValidator(PERMISSION_ORDER) },
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const unshareProjectSchema = {
|
|
93
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
94
|
+
organization_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const listProjectSharesSchema = {
|
|
98
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
99
|
+
};
|
|
100
|
+
|
|
32
101
|
// ============================================================================
|
|
33
102
|
// Organization Management
|
|
34
103
|
// ============================================================================
|
|
35
104
|
|
|
36
|
-
export const listOrganizations: Handler = async (_args,
|
|
105
|
+
export const listOrganizations: Handler = async (_args, _ctx) => {
|
|
37
106
|
const apiClient = getApiClient();
|
|
38
107
|
const response = await apiClient.listOrganizations();
|
|
39
108
|
|
|
@@ -44,14 +113,8 @@ export const listOrganizations: Handler = async (_args, ctx) => {
|
|
|
44
113
|
return { result: response.data };
|
|
45
114
|
};
|
|
46
115
|
|
|
47
|
-
export const createOrganization: Handler = async (args,
|
|
48
|
-
const { name, description, slug } = args
|
|
49
|
-
name: string;
|
|
50
|
-
description?: string;
|
|
51
|
-
slug?: string;
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
validateRequired(name, 'name');
|
|
116
|
+
export const createOrganization: Handler = async (args, _ctx) => {
|
|
117
|
+
const { name, description, slug } = parseArgs(args, createOrganizationSchema);
|
|
55
118
|
|
|
56
119
|
const apiClient = getApiClient();
|
|
57
120
|
const response = await apiClient.createOrganization({
|
|
@@ -67,26 +130,19 @@ export const createOrganization: Handler = async (args, ctx) => {
|
|
|
67
130
|
return { result: response.data };
|
|
68
131
|
};
|
|
69
132
|
|
|
70
|
-
export const updateOrganization: Handler = async (args,
|
|
71
|
-
const { organization_id, name, description, logo_url } = args
|
|
72
|
-
organization_id: string;
|
|
73
|
-
name?: string;
|
|
74
|
-
description?: string;
|
|
75
|
-
logo_url?: string;
|
|
76
|
-
};
|
|
133
|
+
export const updateOrganization: Handler = async (args, _ctx) => {
|
|
134
|
+
const { organization_id, name, description, logo_url } = parseArgs(args, updateOrganizationSchema);
|
|
77
135
|
|
|
78
|
-
|
|
79
|
-
|
|
136
|
+
// Check that at least one update is provided
|
|
137
|
+
if (name === undefined && description === undefined && logo_url === undefined) {
|
|
138
|
+
throw new ValidationError('No updates provided');
|
|
139
|
+
}
|
|
80
140
|
|
|
81
141
|
const updates: Record<string, unknown> = {};
|
|
82
142
|
if (name !== undefined) updates.name = name;
|
|
83
143
|
if (description !== undefined) updates.description = description;
|
|
84
144
|
if (logo_url !== undefined) updates.logo_url = logo_url;
|
|
85
145
|
|
|
86
|
-
if (Object.keys(updates).length === 0) {
|
|
87
|
-
throw new Error('No updates provided');
|
|
88
|
-
}
|
|
89
|
-
|
|
90
146
|
const apiClient = getApiClient();
|
|
91
147
|
const response = await apiClient.updateOrganization(organization_id, updates);
|
|
92
148
|
|
|
@@ -97,11 +153,8 @@ export const updateOrganization: Handler = async (args, ctx) => {
|
|
|
97
153
|
return { result: response.data };
|
|
98
154
|
};
|
|
99
155
|
|
|
100
|
-
export const deleteOrganization: Handler = async (args,
|
|
101
|
-
const { organization_id } = args
|
|
102
|
-
|
|
103
|
-
validateRequired(organization_id, 'organization_id');
|
|
104
|
-
validateUUID(organization_id, 'organization_id');
|
|
156
|
+
export const deleteOrganization: Handler = async (args, _ctx) => {
|
|
157
|
+
const { organization_id } = parseArgs(args, deleteOrganizationSchema);
|
|
105
158
|
|
|
106
159
|
const apiClient = getApiClient();
|
|
107
160
|
const response = await apiClient.deleteOrganization(organization_id);
|
|
@@ -117,11 +170,8 @@ export const deleteOrganization: Handler = async (args, ctx) => {
|
|
|
117
170
|
// Member Management
|
|
118
171
|
// ============================================================================
|
|
119
172
|
|
|
120
|
-
export const listOrgMembers: Handler = async (args,
|
|
121
|
-
const { organization_id } = args
|
|
122
|
-
|
|
123
|
-
validateRequired(organization_id, 'organization_id');
|
|
124
|
-
validateUUID(organization_id, 'organization_id');
|
|
173
|
+
export const listOrgMembers: Handler = async (args, _ctx) => {
|
|
174
|
+
const { organization_id } = parseArgs(args, listOrgMembersSchema);
|
|
125
175
|
|
|
126
176
|
const apiClient = getApiClient();
|
|
127
177
|
const response = await apiClient.listOrgMembers(organization_id);
|
|
@@ -133,23 +183,11 @@ export const listOrgMembers: Handler = async (args, ctx) => {
|
|
|
133
183
|
return { result: response.data };
|
|
134
184
|
};
|
|
135
185
|
|
|
136
|
-
export const inviteMember: Handler = async (args,
|
|
137
|
-
const { organization_id, email, role
|
|
138
|
-
organization_id: string;
|
|
139
|
-
email: string;
|
|
140
|
-
role?: 'admin' | 'member' | 'viewer';
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
validateRequired(organization_id, 'organization_id');
|
|
144
|
-
validateRequired(email, 'email');
|
|
145
|
-
validateUUID(organization_id, 'organization_id');
|
|
146
|
-
|
|
147
|
-
if (!['admin', 'member', 'viewer'].includes(role)) {
|
|
148
|
-
throw new Error('Invalid role. Must be admin, member, or viewer.');
|
|
149
|
-
}
|
|
186
|
+
export const inviteMember: Handler = async (args, _ctx) => {
|
|
187
|
+
const { organization_id, email, role } = parseArgs(args, inviteMemberSchema);
|
|
150
188
|
|
|
151
189
|
const apiClient = getApiClient();
|
|
152
|
-
const response = await apiClient.inviteMember(organization_id, email, role);
|
|
190
|
+
const response = await apiClient.inviteMember(organization_id, email, role as AssignableRole);
|
|
153
191
|
|
|
154
192
|
if (!response.ok) {
|
|
155
193
|
throw new Error(response.error || 'Failed to create invite');
|
|
@@ -158,29 +196,15 @@ export const inviteMember: Handler = async (args, ctx) => {
|
|
|
158
196
|
return { result: response.data };
|
|
159
197
|
};
|
|
160
198
|
|
|
161
|
-
export const updateMemberRole: Handler = async (args,
|
|
162
|
-
const { organization_id, user_id, role } = args
|
|
163
|
-
organization_id: string;
|
|
164
|
-
user_id: string;
|
|
165
|
-
role: Role;
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
validateRequired(organization_id, 'organization_id');
|
|
169
|
-
validateRequired(user_id, 'user_id');
|
|
170
|
-
validateRequired(role, 'role');
|
|
171
|
-
validateUUID(organization_id, 'organization_id');
|
|
172
|
-
validateUUID(user_id, 'user_id');
|
|
173
|
-
|
|
174
|
-
if (!ROLE_ORDER.includes(role)) {
|
|
175
|
-
throw new Error(`Invalid role. Must be one of: ${ROLE_ORDER.join(', ')}`);
|
|
176
|
-
}
|
|
199
|
+
export const updateMemberRole: Handler = async (args, _ctx) => {
|
|
200
|
+
const { organization_id, user_id, role } = parseArgs(args, updateMemberRoleSchema);
|
|
177
201
|
|
|
178
202
|
if (role === 'owner') {
|
|
179
|
-
throw new
|
|
203
|
+
throw new ValidationError('Cannot assign owner role. Use transfer ownership instead.');
|
|
180
204
|
}
|
|
181
205
|
|
|
182
206
|
const apiClient = getApiClient();
|
|
183
|
-
const response = await apiClient.updateMemberRole(organization_id, user_id, role);
|
|
207
|
+
const response = await apiClient.updateMemberRole(organization_id, user_id, role as Role);
|
|
184
208
|
|
|
185
209
|
if (!response.ok) {
|
|
186
210
|
throw new Error(response.error || 'Failed to update member role');
|
|
@@ -189,16 +213,8 @@ export const updateMemberRole: Handler = async (args, ctx) => {
|
|
|
189
213
|
return { result: response.data };
|
|
190
214
|
};
|
|
191
215
|
|
|
192
|
-
export const removeMember: Handler = async (args,
|
|
193
|
-
const { organization_id, user_id } = args
|
|
194
|
-
organization_id: string;
|
|
195
|
-
user_id: string;
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
validateRequired(organization_id, 'organization_id');
|
|
199
|
-
validateRequired(user_id, 'user_id');
|
|
200
|
-
validateUUID(organization_id, 'organization_id');
|
|
201
|
-
validateUUID(user_id, 'user_id');
|
|
216
|
+
export const removeMember: Handler = async (args, _ctx) => {
|
|
217
|
+
const { organization_id, user_id } = parseArgs(args, removeMemberSchema);
|
|
202
218
|
|
|
203
219
|
const apiClient = getApiClient();
|
|
204
220
|
const response = await apiClient.removeMember(organization_id, user_id);
|
|
@@ -210,11 +226,8 @@ export const removeMember: Handler = async (args, ctx) => {
|
|
|
210
226
|
return { result: response.data };
|
|
211
227
|
};
|
|
212
228
|
|
|
213
|
-
export const leaveOrganization: Handler = async (args,
|
|
214
|
-
const { organization_id } = args
|
|
215
|
-
|
|
216
|
-
validateRequired(organization_id, 'organization_id');
|
|
217
|
-
validateUUID(organization_id, 'organization_id');
|
|
229
|
+
export const leaveOrganization: Handler = async (args, _ctx) => {
|
|
230
|
+
const { organization_id } = parseArgs(args, leaveOrganizationSchema);
|
|
218
231
|
|
|
219
232
|
const apiClient = getApiClient();
|
|
220
233
|
const response = await apiClient.leaveOrganization(organization_id);
|
|
@@ -230,24 +243,11 @@ export const leaveOrganization: Handler = async (args, ctx) => {
|
|
|
230
243
|
// Project Sharing
|
|
231
244
|
// ============================================================================
|
|
232
245
|
|
|
233
|
-
export const shareProjectWithOrg: Handler = async (args,
|
|
234
|
-
const { project_id, organization_id, permission
|
|
235
|
-
project_id: string;
|
|
236
|
-
organization_id: string;
|
|
237
|
-
permission?: Permission;
|
|
238
|
-
};
|
|
239
|
-
|
|
240
|
-
validateRequired(project_id, 'project_id');
|
|
241
|
-
validateRequired(organization_id, 'organization_id');
|
|
242
|
-
validateUUID(project_id, 'project_id');
|
|
243
|
-
validateUUID(organization_id, 'organization_id');
|
|
244
|
-
|
|
245
|
-
if (!PERMISSION_ORDER.includes(permission)) {
|
|
246
|
-
throw new Error(`Invalid permission. Must be one of: ${PERMISSION_ORDER.join(', ')}`);
|
|
247
|
-
}
|
|
246
|
+
export const shareProjectWithOrg: Handler = async (args, _ctx) => {
|
|
247
|
+
const { project_id, organization_id, permission } = parseArgs(args, shareProjectWithOrgSchema);
|
|
248
248
|
|
|
249
249
|
const apiClient = getApiClient();
|
|
250
|
-
const response = await apiClient.shareProjectWithOrg(project_id, organization_id, permission);
|
|
250
|
+
const response = await apiClient.shareProjectWithOrg(project_id, organization_id, permission as Permission);
|
|
251
251
|
|
|
252
252
|
if (!response.ok) {
|
|
253
253
|
throw new Error(response.error || 'Failed to share project');
|
|
@@ -256,25 +256,11 @@ export const shareProjectWithOrg: Handler = async (args, ctx) => {
|
|
|
256
256
|
return { result: response.data };
|
|
257
257
|
};
|
|
258
258
|
|
|
259
|
-
export const updateProjectShare: Handler = async (args,
|
|
260
|
-
const { project_id, organization_id, permission } = args
|
|
261
|
-
project_id: string;
|
|
262
|
-
organization_id: string;
|
|
263
|
-
permission: Permission;
|
|
264
|
-
};
|
|
265
|
-
|
|
266
|
-
validateRequired(project_id, 'project_id');
|
|
267
|
-
validateRequired(organization_id, 'organization_id');
|
|
268
|
-
validateRequired(permission, 'permission');
|
|
269
|
-
validateUUID(project_id, 'project_id');
|
|
270
|
-
validateUUID(organization_id, 'organization_id');
|
|
271
|
-
|
|
272
|
-
if (!PERMISSION_ORDER.includes(permission)) {
|
|
273
|
-
throw new Error(`Invalid permission. Must be one of: ${PERMISSION_ORDER.join(', ')}`);
|
|
274
|
-
}
|
|
259
|
+
export const updateProjectShare: Handler = async (args, _ctx) => {
|
|
260
|
+
const { project_id, organization_id, permission } = parseArgs(args, updateProjectShareSchema);
|
|
275
261
|
|
|
276
262
|
const apiClient = getApiClient();
|
|
277
|
-
const response = await apiClient.updateProjectShare(project_id, organization_id, permission);
|
|
263
|
+
const response = await apiClient.updateProjectShare(project_id, organization_id, permission as Permission);
|
|
278
264
|
|
|
279
265
|
if (!response.ok) {
|
|
280
266
|
throw new Error(response.error || 'Failed to update share');
|
|
@@ -283,16 +269,8 @@ export const updateProjectShare: Handler = async (args, ctx) => {
|
|
|
283
269
|
return { result: response.data };
|
|
284
270
|
};
|
|
285
271
|
|
|
286
|
-
export const unshareProject: Handler = async (args,
|
|
287
|
-
const { project_id, organization_id } = args
|
|
288
|
-
project_id: string;
|
|
289
|
-
organization_id: string;
|
|
290
|
-
};
|
|
291
|
-
|
|
292
|
-
validateRequired(project_id, 'project_id');
|
|
293
|
-
validateRequired(organization_id, 'organization_id');
|
|
294
|
-
validateUUID(project_id, 'project_id');
|
|
295
|
-
validateUUID(organization_id, 'organization_id');
|
|
272
|
+
export const unshareProject: Handler = async (args, _ctx) => {
|
|
273
|
+
const { project_id, organization_id } = parseArgs(args, unshareProjectSchema);
|
|
296
274
|
|
|
297
275
|
const apiClient = getApiClient();
|
|
298
276
|
const response = await apiClient.unshareProject(project_id, organization_id);
|
|
@@ -304,11 +282,8 @@ export const unshareProject: Handler = async (args, ctx) => {
|
|
|
304
282
|
return { result: response.data };
|
|
305
283
|
};
|
|
306
284
|
|
|
307
|
-
export const listProjectShares: Handler = async (args,
|
|
308
|
-
const { project_id } = args
|
|
309
|
-
|
|
310
|
-
validateRequired(project_id, 'project_id');
|
|
311
|
-
validateUUID(project_id, 'project_id');
|
|
285
|
+
export const listProjectShares: Handler = async (args, _ctx) => {
|
|
286
|
+
const { project_id } = parseArgs(args, listProjectSharesSchema);
|
|
312
287
|
|
|
313
288
|
const apiClient = getApiClient();
|
|
314
289
|
const response = await apiClient.listProjectShares(project_id);
|
package/src/handlers/progress.ts
CHANGED
|
@@ -9,20 +9,27 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import type { Handler, HandlerRegistry } from './types.js';
|
|
12
|
-
import {
|
|
12
|
+
import { parseArgs, uuidValidator } from '../validators.js';
|
|
13
13
|
import { getApiClient } from '../api-client.js';
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
// Argument schemas for type-safe parsing
|
|
16
|
+
const logProgressSchema = {
|
|
17
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
18
|
+
task_id: { type: 'string' as const, validate: uuidValidator },
|
|
19
|
+
summary: { type: 'string' as const, required: true as const },
|
|
20
|
+
details: { type: 'string' as const },
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const getActivityFeedSchema = {
|
|
24
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
25
|
+
limit: { type: 'number' as const, default: 50 },
|
|
26
|
+
since: { type: 'string' as const },
|
|
27
|
+
types: { type: 'array' as const },
|
|
28
|
+
created_by: { type: 'string' as const },
|
|
29
|
+
};
|
|
22
30
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
validateRequired(summary, 'summary');
|
|
31
|
+
export const logProgress: Handler = async (args, ctx) => {
|
|
32
|
+
const { project_id, task_id, summary, details } = parseArgs(args, logProgressSchema);
|
|
26
33
|
|
|
27
34
|
const { session } = ctx;
|
|
28
35
|
const apiClient = getApiClient();
|
|
@@ -41,22 +48,17 @@ export const logProgress: Handler = async (args, ctx) => {
|
|
|
41
48
|
return { result: { success: true, progress_id: response.data?.progress_id } };
|
|
42
49
|
};
|
|
43
50
|
|
|
44
|
-
export const getActivityFeed: Handler = async (args,
|
|
45
|
-
const { project_id, limit
|
|
46
|
-
project_id: string;
|
|
47
|
-
limit?: number;
|
|
48
|
-
since?: string;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
validateRequired(project_id, 'project_id');
|
|
52
|
-
validateUUID(project_id, 'project_id');
|
|
51
|
+
export const getActivityFeed: Handler = async (args, _ctx) => {
|
|
52
|
+
const { project_id, limit, since, types, created_by } = parseArgs(args, getActivityFeedSchema);
|
|
53
53
|
|
|
54
54
|
const apiClient = getApiClient();
|
|
55
|
-
const effectiveLimit = Math.min(limit, 200);
|
|
55
|
+
const effectiveLimit = Math.min(limit ?? 50, 200);
|
|
56
56
|
|
|
57
57
|
const response = await apiClient.getActivityFeed(project_id, {
|
|
58
58
|
limit: effectiveLimit,
|
|
59
|
-
since
|
|
59
|
+
since,
|
|
60
|
+
types: types as string[] | undefined,
|
|
61
|
+
created_by
|
|
60
62
|
});
|
|
61
63
|
|
|
62
64
|
if (!response.ok) {
|
package/src/handlers/project.ts
CHANGED
|
@@ -10,14 +10,60 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import type { Handler, HandlerRegistry } from './types.js';
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
parseArgs,
|
|
15
|
+
uuidValidator,
|
|
16
|
+
projectStatusValidator,
|
|
17
|
+
createEnumValidator,
|
|
18
|
+
VALID_PROJECT_STATUSES,
|
|
19
|
+
} from '../validators.js';
|
|
14
20
|
import { getApiClient } from '../api-client.js';
|
|
15
21
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
const VALID_GIT_WORKFLOWS = ['none', 'trunk-based', 'github-flow', 'git-flow'] as const;
|
|
23
|
+
type GitWorkflow = typeof VALID_GIT_WORKFLOWS[number];
|
|
24
|
+
|
|
25
|
+
// Argument schemas for type-safe parsing
|
|
26
|
+
const getProjectContextSchema = {
|
|
27
|
+
project_id: { type: 'string' as const, validate: uuidValidator },
|
|
28
|
+
git_url: { type: 'string' as const },
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const getGitWorkflowSchema = {
|
|
32
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
33
|
+
task_id: { type: 'string' as const, validate: uuidValidator },
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const createProjectSchema = {
|
|
37
|
+
name: { type: 'string' as const, required: true as const },
|
|
38
|
+
description: { type: 'string' as const },
|
|
39
|
+
goal: { type: 'string' as const },
|
|
40
|
+
git_url: { type: 'string' as const },
|
|
41
|
+
tech_stack: { type: 'array' as const },
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const updateProjectSchema = {
|
|
45
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
46
|
+
name: { type: 'string' as const },
|
|
47
|
+
description: { type: 'string' as const },
|
|
48
|
+
goal: { type: 'string' as const },
|
|
49
|
+
git_url: { type: 'string' as const },
|
|
50
|
+
tech_stack: { type: 'array' as const },
|
|
51
|
+
status: { type: 'string' as const, validate: projectStatusValidator },
|
|
52
|
+
git_workflow: { type: 'string' as const, validate: createEnumValidator(VALID_GIT_WORKFLOWS) },
|
|
53
|
+
git_main_branch: { type: 'string' as const },
|
|
54
|
+
git_develop_branch: { type: 'string' as const },
|
|
55
|
+
git_auto_branch: { type: 'boolean' as const },
|
|
56
|
+
git_auto_tag: { type: 'boolean' as const },
|
|
57
|
+
deployment_instructions: { type: 'string' as const },
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const updateProjectReadmeSchema = {
|
|
61
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
62
|
+
readme_content: { type: 'string' as const, required: true as const },
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export const getProjectContext: Handler = async (args, _ctx) => {
|
|
66
|
+
const { project_id, git_url } = parseArgs(args, getProjectContextSchema);
|
|
21
67
|
|
|
22
68
|
const apiClient = getApiClient();
|
|
23
69
|
|
|
@@ -51,14 +97,8 @@ export const getProjectContext: Handler = async (args, ctx) => {
|
|
|
51
97
|
return { result: response.data };
|
|
52
98
|
};
|
|
53
99
|
|
|
54
|
-
export const getGitWorkflow: Handler = async (args,
|
|
55
|
-
const { project_id, task_id } = args
|
|
56
|
-
project_id: string;
|
|
57
|
-
task_id?: string;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
validateRequired(project_id, 'project_id');
|
|
61
|
-
validateUUID(project_id, 'project_id');
|
|
100
|
+
export const getGitWorkflow: Handler = async (args, _ctx) => {
|
|
101
|
+
const { project_id, task_id } = parseArgs(args, getGitWorkflowSchema);
|
|
62
102
|
|
|
63
103
|
const apiClient = getApiClient();
|
|
64
104
|
const response = await apiClient.getGitWorkflow(project_id, task_id);
|
|
@@ -70,16 +110,8 @@ export const getGitWorkflow: Handler = async (args, ctx) => {
|
|
|
70
110
|
return { result: response.data };
|
|
71
111
|
};
|
|
72
112
|
|
|
73
|
-
export const createProject: Handler = async (args,
|
|
74
|
-
const { name, description, goal, git_url, tech_stack } = args
|
|
75
|
-
name: string;
|
|
76
|
-
description?: string;
|
|
77
|
-
goal?: string;
|
|
78
|
-
git_url?: string;
|
|
79
|
-
tech_stack?: string[];
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
validateRequired(name, 'name');
|
|
113
|
+
export const createProject: Handler = async (args, _ctx) => {
|
|
114
|
+
const { name, description, goal, git_url, tech_stack } = parseArgs(args, createProjectSchema);
|
|
83
115
|
|
|
84
116
|
const apiClient = getApiClient();
|
|
85
117
|
const response = await apiClient.createProject({
|
|
@@ -87,7 +119,7 @@ export const createProject: Handler = async (args, ctx) => {
|
|
|
87
119
|
description,
|
|
88
120
|
goal,
|
|
89
121
|
git_url,
|
|
90
|
-
tech_stack
|
|
122
|
+
tech_stack: tech_stack as string[] | undefined
|
|
91
123
|
});
|
|
92
124
|
|
|
93
125
|
if (!response.ok) {
|
|
@@ -97,31 +129,38 @@ export const createProject: Handler = async (args, ctx) => {
|
|
|
97
129
|
return { result: response.data };
|
|
98
130
|
};
|
|
99
131
|
|
|
100
|
-
export const updateProject: Handler = async (args,
|
|
101
|
-
const {
|
|
102
|
-
project_id
|
|
103
|
-
name
|
|
104
|
-
description
|
|
105
|
-
goal
|
|
106
|
-
git_url
|
|
107
|
-
tech_stack
|
|
108
|
-
status
|
|
109
|
-
git_workflow
|
|
110
|
-
git_main_branch
|
|
111
|
-
git_develop_branch
|
|
112
|
-
git_auto_branch
|
|
113
|
-
git_auto_tag
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
deployment_instructions?: string;
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
validateRequired(project_id, 'project_id');
|
|
120
|
-
validateUUID(project_id, 'project_id');
|
|
121
|
-
validateProjectStatus(updates.status);
|
|
132
|
+
export const updateProject: Handler = async (args, _ctx) => {
|
|
133
|
+
const {
|
|
134
|
+
project_id,
|
|
135
|
+
name,
|
|
136
|
+
description,
|
|
137
|
+
goal,
|
|
138
|
+
git_url,
|
|
139
|
+
tech_stack,
|
|
140
|
+
status,
|
|
141
|
+
git_workflow,
|
|
142
|
+
git_main_branch,
|
|
143
|
+
git_develop_branch,
|
|
144
|
+
git_auto_branch,
|
|
145
|
+
git_auto_tag,
|
|
146
|
+
deployment_instructions
|
|
147
|
+
} = parseArgs(args, updateProjectSchema);
|
|
122
148
|
|
|
123
149
|
const apiClient = getApiClient();
|
|
124
|
-
const response = await apiClient.updateProject(project_id,
|
|
150
|
+
const response = await apiClient.updateProject(project_id, {
|
|
151
|
+
name,
|
|
152
|
+
description,
|
|
153
|
+
goal,
|
|
154
|
+
git_url,
|
|
155
|
+
tech_stack: tech_stack as string[] | undefined,
|
|
156
|
+
status: status as typeof VALID_PROJECT_STATUSES[number] | undefined,
|
|
157
|
+
git_workflow: git_workflow as GitWorkflow | undefined,
|
|
158
|
+
git_main_branch,
|
|
159
|
+
git_develop_branch,
|
|
160
|
+
git_auto_branch,
|
|
161
|
+
git_auto_tag,
|
|
162
|
+
deployment_instructions
|
|
163
|
+
});
|
|
125
164
|
|
|
126
165
|
if (!response.ok) {
|
|
127
166
|
throw new Error(response.error || 'Failed to update project');
|
|
@@ -130,15 +169,8 @@ export const updateProject: Handler = async (args, ctx) => {
|
|
|
130
169
|
return { result: response.data };
|
|
131
170
|
};
|
|
132
171
|
|
|
133
|
-
export const updateProjectReadme: Handler = async (args,
|
|
134
|
-
const { project_id, readme_content } = args
|
|
135
|
-
project_id: string;
|
|
136
|
-
readme_content: string;
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
validateRequired(project_id, 'project_id');
|
|
140
|
-
validateUUID(project_id, 'project_id');
|
|
141
|
-
validateRequired(readme_content, 'readme_content');
|
|
172
|
+
export const updateProjectReadme: Handler = async (args, _ctx) => {
|
|
173
|
+
const { project_id, readme_content } = parseArgs(args, updateProjectReadmeSchema);
|
|
142
174
|
|
|
143
175
|
const apiClient = getApiClient();
|
|
144
176
|
const response = await apiClient.updateProjectReadme(project_id, readme_content);
|
package/src/handlers/requests.ts
CHANGED
|
@@ -10,14 +10,25 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import type { Handler, HandlerRegistry } from './types.js';
|
|
13
|
-
import {
|
|
13
|
+
import { parseArgs, uuidValidator } from '../validators.js';
|
|
14
14
|
import { getApiClient } from '../api-client.js';
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
// Argument schemas for type-safe parsing
|
|
17
|
+
const getPendingRequestsSchema = {
|
|
18
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
19
|
+
};
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
const acknowledgeRequestSchema = {
|
|
22
|
+
request_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const answerQuestionSchema = {
|
|
26
|
+
request_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
27
|
+
answer: { type: 'string' as const, required: true as const },
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const getPendingRequests: Handler = async (args, ctx) => {
|
|
31
|
+
const { project_id } = parseArgs(args, getPendingRequestsSchema);
|
|
21
32
|
|
|
22
33
|
const { session } = ctx;
|
|
23
34
|
const apiClient = getApiClient();
|
|
@@ -37,10 +48,7 @@ export const getPendingRequests: Handler = async (args, ctx) => {
|
|
|
37
48
|
};
|
|
38
49
|
|
|
39
50
|
export const acknowledgeRequest: Handler = async (args, ctx) => {
|
|
40
|
-
const { request_id } = args
|
|
41
|
-
|
|
42
|
-
validateRequired(request_id, 'request_id');
|
|
43
|
-
validateUUID(request_id, 'request_id');
|
|
51
|
+
const { request_id } = parseArgs(args, acknowledgeRequestSchema);
|
|
44
52
|
|
|
45
53
|
const { session } = ctx;
|
|
46
54
|
const apiClient = getApiClient();
|
|
@@ -59,11 +67,7 @@ export const acknowledgeRequest: Handler = async (args, ctx) => {
|
|
|
59
67
|
};
|
|
60
68
|
|
|
61
69
|
export const answerQuestion: Handler = async (args, ctx) => {
|
|
62
|
-
const { request_id, answer } = args
|
|
63
|
-
|
|
64
|
-
validateRequired(request_id, 'request_id');
|
|
65
|
-
validateRequired(answer, 'answer');
|
|
66
|
-
validateUUID(request_id, 'request_id');
|
|
70
|
+
const { request_id, answer } = parseArgs(args, answerQuestionSchema);
|
|
67
71
|
|
|
68
72
|
const { session } = ctx;
|
|
69
73
|
const apiClient = getApiClient();
|