@vibescope/mcp-server 0.2.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/dist/api-client.d.ts +64 -1
- package/dist/api-client.js +34 -3
- package/dist/handlers/bodies-of-work.js +82 -49
- package/dist/handlers/cost.js +62 -54
- package/dist/handlers/decisions.js +29 -16
- package/dist/handlers/deployment.js +112 -106
- package/dist/handlers/discovery.js +35 -5
- package/dist/handlers/fallback.js +24 -19
- package/dist/handlers/file-checkouts.d.ts +18 -0
- package/dist/handlers/file-checkouts.js +101 -0
- package/dist/handlers/findings.d.ts +6 -0
- package/dist/handlers/findings.js +85 -30
- 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 +30 -8
- package/dist/handlers/sprints.js +76 -64
- package/dist/handlers/tasks.js +113 -73
- package/dist/handlers/validation.js +18 -14
- package/dist/tools.js +387 -0
- package/package.json +1 -1
- package/src/api-client.ts +89 -6
- package/src/handlers/__test-setup__.ts +7 -0
- package/src/handlers/bodies-of-work.ts +101 -101
- 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 +142 -190
- package/src/handlers/discovery.test.ts +4 -5
- package/src/handlers/discovery.ts +37 -6
- package/src/handlers/fallback.ts +31 -29
- package/src/handlers/file-checkouts.test.ts +477 -0
- package/src/handlers/file-checkouts.ts +127 -0
- package/src/handlers/findings.test.ts +145 -0
- package/src/handlers/findings.ts +101 -64
- 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.ts +39 -17
- package/src/handlers/sprints.ts +96 -129
- package/src/handlers/tasks.ts +144 -138
- package/src/handlers/validation.test.ts +1 -1
- package/src/handlers/validation.ts +20 -22
- package/src/tools.ts +387 -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
|
@@ -8,21 +8,62 @@
|
|
|
8
8
|
* - update_finding
|
|
9
9
|
* - delete_finding
|
|
10
10
|
*/
|
|
11
|
-
import {
|
|
11
|
+
import { parseArgs, uuidValidator, createEnumValidator } from '../validators.js';
|
|
12
12
|
import { getApiClient } from '../api-client.js';
|
|
13
|
+
const VALID_FINDING_CATEGORIES = ['performance', 'security', 'code_quality', 'accessibility', 'documentation', 'architecture', 'testing', 'other'];
|
|
14
|
+
const VALID_FINDING_SEVERITIES = ['info', 'low', 'medium', 'high', 'critical'];
|
|
15
|
+
const VALID_FINDING_STATUSES = ['open', 'addressed', 'dismissed', 'wontfix'];
|
|
16
|
+
// Argument schemas for type-safe parsing
|
|
17
|
+
const addFindingSchema = {
|
|
18
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
19
|
+
title: { type: 'string', required: true },
|
|
20
|
+
description: { type: 'string' },
|
|
21
|
+
category: { type: 'string', validate: createEnumValidator(VALID_FINDING_CATEGORIES) },
|
|
22
|
+
severity: { type: 'string', validate: createEnumValidator(VALID_FINDING_SEVERITIES) },
|
|
23
|
+
file_path: { type: 'string' },
|
|
24
|
+
line_number: { type: 'number' },
|
|
25
|
+
related_task_id: { type: 'string', validate: uuidValidator },
|
|
26
|
+
};
|
|
27
|
+
const getFindingsSchema = {
|
|
28
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
29
|
+
category: { type: 'string', validate: createEnumValidator(VALID_FINDING_CATEGORIES) },
|
|
30
|
+
severity: { type: 'string', validate: createEnumValidator(VALID_FINDING_SEVERITIES) },
|
|
31
|
+
status: { type: 'string', validate: createEnumValidator(VALID_FINDING_STATUSES) },
|
|
32
|
+
limit: { type: 'number', default: 50 },
|
|
33
|
+
offset: { type: 'number', default: 0 },
|
|
34
|
+
search_query: { type: 'string' },
|
|
35
|
+
summary_only: { type: 'boolean', default: false },
|
|
36
|
+
};
|
|
37
|
+
const getFindingsStatsSchema = {
|
|
38
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
39
|
+
};
|
|
40
|
+
const updateFindingSchema = {
|
|
41
|
+
finding_id: { type: 'string', required: true, validate: uuidValidator },
|
|
42
|
+
title: { type: 'string' },
|
|
43
|
+
description: { type: 'string' },
|
|
44
|
+
severity: { type: 'string', validate: createEnumValidator(VALID_FINDING_SEVERITIES) },
|
|
45
|
+
status: { type: 'string', validate: createEnumValidator(VALID_FINDING_STATUSES) },
|
|
46
|
+
resolution_note: { type: 'string' },
|
|
47
|
+
};
|
|
48
|
+
const deleteFindingSchema = {
|
|
49
|
+
finding_id: { type: 'string', required: true, validate: uuidValidator },
|
|
50
|
+
};
|
|
51
|
+
const VALID_SCOPES = ['summary', 'detailed'];
|
|
52
|
+
const queryKnowledgeBaseSchema = {
|
|
53
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
54
|
+
scope: { type: 'string', default: 'summary', validate: createEnumValidator(VALID_SCOPES) },
|
|
55
|
+
categories: { type: 'array' },
|
|
56
|
+
limit: { type: 'number', default: 5 },
|
|
57
|
+
search_query: { type: 'string' },
|
|
58
|
+
};
|
|
13
59
|
export const addFinding = async (args, ctx) => {
|
|
14
|
-
const { project_id,
|
|
15
|
-
validateRequired(project_id, 'project_id');
|
|
16
|
-
validateUUID(project_id, 'project_id');
|
|
17
|
-
validateRequired(title, 'title');
|
|
18
|
-
if (related_task_id)
|
|
19
|
-
validateUUID(related_task_id, 'related_task_id');
|
|
60
|
+
const { project_id, title, description, category, severity, file_path, line_number, related_task_id } = parseArgs(args, addFindingSchema);
|
|
20
61
|
const apiClient = getApiClient();
|
|
21
62
|
const response = await apiClient.addFinding(project_id, {
|
|
22
63
|
title,
|
|
23
64
|
description,
|
|
24
|
-
category,
|
|
25
|
-
severity,
|
|
65
|
+
category: category,
|
|
66
|
+
severity: severity,
|
|
26
67
|
file_path,
|
|
27
68
|
line_number,
|
|
28
69
|
related_task_id
|
|
@@ -32,15 +73,13 @@ export const addFinding = async (args, ctx) => {
|
|
|
32
73
|
}
|
|
33
74
|
return { result: response.data };
|
|
34
75
|
};
|
|
35
|
-
export const getFindings = async (args,
|
|
36
|
-
const { project_id, category, severity, status, limit
|
|
37
|
-
validateRequired(project_id, 'project_id');
|
|
38
|
-
validateUUID(project_id, 'project_id');
|
|
76
|
+
export const getFindings = async (args, _ctx) => {
|
|
77
|
+
const { project_id, category, severity, status, limit, offset, search_query, summary_only } = parseArgs(args, getFindingsSchema);
|
|
39
78
|
const apiClient = getApiClient();
|
|
40
79
|
const response = await apiClient.getFindings(project_id, {
|
|
41
|
-
category,
|
|
42
|
-
severity,
|
|
43
|
-
status,
|
|
80
|
+
category: category,
|
|
81
|
+
severity: severity,
|
|
82
|
+
status: status,
|
|
44
83
|
limit,
|
|
45
84
|
offset,
|
|
46
85
|
search_query,
|
|
@@ -56,10 +95,8 @@ export const getFindings = async (args, ctx) => {
|
|
|
56
95
|
* Returns counts by category, severity, and status without the actual finding data.
|
|
57
96
|
* This is much more token-efficient than get_findings for understanding the overall state.
|
|
58
97
|
*/
|
|
59
|
-
export const getFindingsStats = async (args,
|
|
60
|
-
const { project_id } = args;
|
|
61
|
-
validateRequired(project_id, 'project_id');
|
|
62
|
-
validateUUID(project_id, 'project_id');
|
|
98
|
+
export const getFindingsStats = async (args, _ctx) => {
|
|
99
|
+
const { project_id } = parseArgs(args, getFindingsStatsSchema);
|
|
63
100
|
const apiClient = getApiClient();
|
|
64
101
|
const response = await apiClient.getFindingsStats(project_id);
|
|
65
102
|
if (!response.ok) {
|
|
@@ -67,16 +104,14 @@ export const getFindingsStats = async (args, ctx) => {
|
|
|
67
104
|
}
|
|
68
105
|
return { result: response.data };
|
|
69
106
|
};
|
|
70
|
-
export const updateFinding = async (args,
|
|
71
|
-
const { finding_id,
|
|
72
|
-
validateRequired(finding_id, 'finding_id');
|
|
73
|
-
validateUUID(finding_id, 'finding_id');
|
|
107
|
+
export const updateFinding = async (args, _ctx) => {
|
|
108
|
+
const { finding_id, title, description, severity, status, resolution_note } = parseArgs(args, updateFindingSchema);
|
|
74
109
|
const apiClient = getApiClient();
|
|
75
110
|
const response = await apiClient.updateFinding(finding_id, {
|
|
76
111
|
title,
|
|
77
112
|
description,
|
|
78
|
-
severity,
|
|
79
|
-
status,
|
|
113
|
+
severity: severity,
|
|
114
|
+
status: status,
|
|
80
115
|
resolution_note
|
|
81
116
|
});
|
|
82
117
|
if (!response.ok) {
|
|
@@ -84,10 +119,8 @@ export const updateFinding = async (args, ctx) => {
|
|
|
84
119
|
}
|
|
85
120
|
return { result: response.data };
|
|
86
121
|
};
|
|
87
|
-
export const deleteFinding = async (args,
|
|
88
|
-
const { finding_id } = args;
|
|
89
|
-
validateRequired(finding_id, 'finding_id');
|
|
90
|
-
validateUUID(finding_id, 'finding_id');
|
|
122
|
+
export const deleteFinding = async (args, _ctx) => {
|
|
123
|
+
const { finding_id } = parseArgs(args, deleteFindingSchema);
|
|
91
124
|
const apiClient = getApiClient();
|
|
92
125
|
const response = await apiClient.deleteFinding(finding_id);
|
|
93
126
|
if (!response.ok) {
|
|
@@ -95,6 +128,27 @@ export const deleteFinding = async (args, ctx) => {
|
|
|
95
128
|
}
|
|
96
129
|
return { result: response.data };
|
|
97
130
|
};
|
|
131
|
+
/**
|
|
132
|
+
* Query aggregated project knowledge in a single call.
|
|
133
|
+
* Returns findings, Q&A, decisions, completed tasks, and resolved blockers.
|
|
134
|
+
* Use this instead of multiple separate tool calls to reduce token usage.
|
|
135
|
+
*/
|
|
136
|
+
export const queryKnowledgeBase = async (args, _ctx) => {
|
|
137
|
+
const { project_id, scope, categories, limit, search_query } = parseArgs(args, queryKnowledgeBaseSchema);
|
|
138
|
+
// Validate limit range
|
|
139
|
+
const effectiveLimit = Math.min(Math.max(1, limit ?? 5), 20);
|
|
140
|
+
const apiClient = getApiClient();
|
|
141
|
+
const response = await apiClient.queryKnowledgeBase(project_id, {
|
|
142
|
+
scope: scope,
|
|
143
|
+
categories: categories,
|
|
144
|
+
limit: effectiveLimit,
|
|
145
|
+
search_query
|
|
146
|
+
});
|
|
147
|
+
if (!response.ok) {
|
|
148
|
+
throw new Error(response.error || 'Failed to query knowledge base');
|
|
149
|
+
}
|
|
150
|
+
return { result: response.data };
|
|
151
|
+
};
|
|
98
152
|
/**
|
|
99
153
|
* Findings handlers registry
|
|
100
154
|
*/
|
|
@@ -104,4 +158,5 @@ export const findingHandlers = {
|
|
|
104
158
|
get_findings_stats: getFindingsStats,
|
|
105
159
|
update_finding: updateFinding,
|
|
106
160
|
delete_finding: deleteFinding,
|
|
161
|
+
query_knowledge_base: queryKnowledgeBase,
|
|
107
162
|
};
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* - get_git_issues: List git issues for a project
|
|
8
8
|
* - delete_git_issue: Remove a git issue
|
|
9
9
|
*/
|
|
10
|
-
import {
|
|
10
|
+
import { parseArgs, uuidValidator, createEnumValidator } from '../validators.js';
|
|
11
11
|
import { getApiClient } from '../api-client.js';
|
|
12
12
|
const VALID_GIT_ISSUE_TYPES = [
|
|
13
13
|
'merge_conflict',
|
|
@@ -17,25 +17,41 @@ const VALID_GIT_ISSUE_TYPES = [
|
|
|
17
17
|
'pr_not_mergeable',
|
|
18
18
|
];
|
|
19
19
|
const VALID_GIT_ISSUE_STATUSES = ['open', 'resolved'];
|
|
20
|
+
// Argument schemas for type-safe parsing
|
|
21
|
+
const addGitIssueSchema = {
|
|
22
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
23
|
+
issue_type: { type: 'string', required: true, validate: createEnumValidator(VALID_GIT_ISSUE_TYPES) },
|
|
24
|
+
branch: { type: 'string', required: true },
|
|
25
|
+
target_branch: { type: 'string' },
|
|
26
|
+
pr_url: { type: 'string' },
|
|
27
|
+
conflicting_files: { type: 'array' },
|
|
28
|
+
error_message: { type: 'string' },
|
|
29
|
+
task_id: { type: 'string', validate: uuidValidator },
|
|
30
|
+
};
|
|
31
|
+
const resolveGitIssueSchema = {
|
|
32
|
+
git_issue_id: { type: 'string', required: true, validate: uuidValidator },
|
|
33
|
+
resolution_note: { type: 'string' },
|
|
34
|
+
auto_resolved: { type: 'boolean' },
|
|
35
|
+
};
|
|
36
|
+
const getGitIssuesSchema = {
|
|
37
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
38
|
+
status: { type: 'string', default: 'open', validate: createEnumValidator(VALID_GIT_ISSUE_STATUSES) },
|
|
39
|
+
issue_type: { type: 'string', validate: createEnumValidator(VALID_GIT_ISSUE_TYPES) },
|
|
40
|
+
branch: { type: 'string' },
|
|
41
|
+
limit: { type: 'number', default: 50 },
|
|
42
|
+
};
|
|
43
|
+
const deleteGitIssueSchema = {
|
|
44
|
+
git_issue_id: { type: 'string', required: true, validate: uuidValidator },
|
|
45
|
+
};
|
|
20
46
|
export const addGitIssue = async (args, ctx) => {
|
|
21
|
-
const { project_id, issue_type, branch, target_branch, pr_url, conflicting_files, error_message, task_id
|
|
22
|
-
validateRequired(project_id, 'project_id');
|
|
23
|
-
validateUUID(project_id, 'project_id');
|
|
24
|
-
validateRequired(issue_type, 'issue_type');
|
|
25
|
-
validateRequired(branch, 'branch');
|
|
26
|
-
if (!VALID_GIT_ISSUE_TYPES.includes(issue_type)) {
|
|
27
|
-
throw new Error(`Invalid issue_type. Valid types: ${VALID_GIT_ISSUE_TYPES.join(', ')}`);
|
|
28
|
-
}
|
|
29
|
-
if (task_id) {
|
|
30
|
-
validateUUID(task_id, 'task_id');
|
|
31
|
-
}
|
|
47
|
+
const { project_id, issue_type, branch, target_branch, pr_url, conflicting_files, error_message, task_id } = parseArgs(args, addGitIssueSchema);
|
|
32
48
|
const apiClient = getApiClient();
|
|
33
49
|
const response = await apiClient.addGitIssue(project_id, {
|
|
34
50
|
issue_type: issue_type,
|
|
35
51
|
branch,
|
|
36
52
|
target_branch,
|
|
37
53
|
pr_url,
|
|
38
|
-
conflicting_files,
|
|
54
|
+
conflicting_files: conflicting_files,
|
|
39
55
|
error_message,
|
|
40
56
|
task_id
|
|
41
57
|
}, ctx.session.currentSessionId || undefined);
|
|
@@ -45,9 +61,7 @@ export const addGitIssue = async (args, ctx) => {
|
|
|
45
61
|
return { result: response.data };
|
|
46
62
|
};
|
|
47
63
|
export const resolveGitIssue = async (args, ctx) => {
|
|
48
|
-
const { git_issue_id, resolution_note, auto_resolved } = args;
|
|
49
|
-
validateRequired(git_issue_id, 'git_issue_id');
|
|
50
|
-
validateUUID(git_issue_id, 'git_issue_id');
|
|
64
|
+
const { git_issue_id, resolution_note, auto_resolved } = parseArgs(args, resolveGitIssueSchema);
|
|
51
65
|
const apiClient = getApiClient();
|
|
52
66
|
const response = await apiClient.resolveGitIssue(git_issue_id, {
|
|
53
67
|
resolution_note,
|
|
@@ -58,20 +72,12 @@ export const resolveGitIssue = async (args, ctx) => {
|
|
|
58
72
|
}
|
|
59
73
|
return { result: response.data };
|
|
60
74
|
};
|
|
61
|
-
export const getGitIssues = async (args,
|
|
62
|
-
const { project_id, status
|
|
63
|
-
validateRequired(project_id, 'project_id');
|
|
64
|
-
validateUUID(project_id, 'project_id');
|
|
65
|
-
if (status && !VALID_GIT_ISSUE_STATUSES.includes(status)) {
|
|
66
|
-
throw new Error(`Invalid status. Valid statuses: ${VALID_GIT_ISSUE_STATUSES.join(', ')}`);
|
|
67
|
-
}
|
|
68
|
-
if (issue_type && !VALID_GIT_ISSUE_TYPES.includes(issue_type)) {
|
|
69
|
-
throw new Error(`Invalid issue_type. Valid types: ${VALID_GIT_ISSUE_TYPES.join(', ')}`);
|
|
70
|
-
}
|
|
75
|
+
export const getGitIssues = async (args, _ctx) => {
|
|
76
|
+
const { project_id, status, issue_type, branch, limit } = parseArgs(args, getGitIssuesSchema);
|
|
71
77
|
const apiClient = getApiClient();
|
|
72
78
|
const response = await apiClient.getGitIssues(project_id, {
|
|
73
|
-
status,
|
|
74
|
-
issue_type,
|
|
79
|
+
status: status,
|
|
80
|
+
issue_type: issue_type,
|
|
75
81
|
branch,
|
|
76
82
|
limit
|
|
77
83
|
});
|
|
@@ -80,10 +86,8 @@ export const getGitIssues = async (args, ctx) => {
|
|
|
80
86
|
}
|
|
81
87
|
return { result: response.data };
|
|
82
88
|
};
|
|
83
|
-
export const deleteGitIssue = async (args,
|
|
84
|
-
const { git_issue_id } = args;
|
|
85
|
-
validateRequired(git_issue_id, 'git_issue_id');
|
|
86
|
-
validateUUID(git_issue_id, 'git_issue_id');
|
|
89
|
+
export const deleteGitIssue = async (args, _ctx) => {
|
|
90
|
+
const { git_issue_id } = parseArgs(args, deleteGitIssueSchema);
|
|
87
91
|
const apiClient = getApiClient();
|
|
88
92
|
const response = await apiClient.deleteGitIssue(git_issue_id);
|
|
89
93
|
if (!response.ok) {
|
package/dist/handlers/ideas.js
CHANGED
|
@@ -10,34 +10,60 @@
|
|
|
10
10
|
*
|
|
11
11
|
* MIGRATED: Uses Vibescope API client instead of direct Supabase
|
|
12
12
|
*/
|
|
13
|
-
import {
|
|
13
|
+
import { parseArgs, uuidValidator, priorityValidator, minutesValidator, createEnumValidator, } from '../validators.js';
|
|
14
14
|
import { getApiClient } from '../api-client.js';
|
|
15
|
+
const VALID_IDEA_STATUSES = ['raw', 'exploring', 'planned', 'in_development', 'shipped'];
|
|
16
|
+
// Argument schemas for type-safe parsing
|
|
17
|
+
const addIdeaSchema = {
|
|
18
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
19
|
+
title: { type: 'string', required: true },
|
|
20
|
+
description: { type: 'string' },
|
|
21
|
+
status: { type: 'string', validate: createEnumValidator(VALID_IDEA_STATUSES) },
|
|
22
|
+
};
|
|
23
|
+
const updateIdeaSchema = {
|
|
24
|
+
idea_id: { type: 'string', required: true, validate: uuidValidator },
|
|
25
|
+
title: { type: 'string' },
|
|
26
|
+
description: { type: 'string' },
|
|
27
|
+
status: { type: 'string', validate: createEnumValidator(VALID_IDEA_STATUSES) },
|
|
28
|
+
doc_url: { type: 'string' },
|
|
29
|
+
};
|
|
30
|
+
const getIdeasSchema = {
|
|
31
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
32
|
+
status: { type: 'string', validate: createEnumValidator(VALID_IDEA_STATUSES) },
|
|
33
|
+
limit: { type: 'number', default: 50 },
|
|
34
|
+
offset: { type: 'number', default: 0 },
|
|
35
|
+
search_query: { type: 'string' },
|
|
36
|
+
};
|
|
37
|
+
const deleteIdeaSchema = {
|
|
38
|
+
idea_id: { type: 'string', required: true, validate: uuidValidator },
|
|
39
|
+
};
|
|
40
|
+
const convertIdeaToTaskSchema = {
|
|
41
|
+
idea_id: { type: 'string', required: true, validate: uuidValidator },
|
|
42
|
+
priority: { type: 'number', default: 3, validate: priorityValidator },
|
|
43
|
+
estimated_minutes: { type: 'number', validate: minutesValidator },
|
|
44
|
+
update_status: { type: 'boolean', default: true },
|
|
45
|
+
};
|
|
15
46
|
export const addIdea = async (args, ctx) => {
|
|
16
|
-
const { project_id, title, description, status } = args;
|
|
17
|
-
validateRequired(project_id, 'project_id');
|
|
18
|
-
validateUUID(project_id, 'project_id');
|
|
19
|
-
validateRequired(title, 'title');
|
|
47
|
+
const { project_id, title, description, status } = parseArgs(args, addIdeaSchema);
|
|
20
48
|
const { session } = ctx;
|
|
21
49
|
const apiClient = getApiClient();
|
|
22
50
|
const response = await apiClient.addIdea(project_id, {
|
|
23
51
|
title,
|
|
24
52
|
description,
|
|
25
|
-
status
|
|
53
|
+
status: status
|
|
26
54
|
}, session.currentSessionId || undefined);
|
|
27
55
|
if (!response.ok) {
|
|
28
56
|
throw new Error(`Failed to add idea: ${response.error}`);
|
|
29
57
|
}
|
|
30
58
|
return { result: { success: true, idea_id: response.data?.idea_id, title } };
|
|
31
59
|
};
|
|
32
|
-
export const updateIdea = async (args,
|
|
33
|
-
const { idea_id, title, description, status, doc_url } = args;
|
|
34
|
-
validateRequired(idea_id, 'idea_id');
|
|
35
|
-
validateUUID(idea_id, 'idea_id');
|
|
60
|
+
export const updateIdea = async (args, _ctx) => {
|
|
61
|
+
const { idea_id, title, description, status, doc_url } = parseArgs(args, updateIdeaSchema);
|
|
36
62
|
const apiClient = getApiClient();
|
|
37
63
|
const response = await apiClient.updateIdea(idea_id, {
|
|
38
64
|
title,
|
|
39
65
|
description,
|
|
40
|
-
status,
|
|
66
|
+
status: status,
|
|
41
67
|
doc_url
|
|
42
68
|
});
|
|
43
69
|
if (!response.ok) {
|
|
@@ -45,13 +71,11 @@ export const updateIdea = async (args, ctx) => {
|
|
|
45
71
|
}
|
|
46
72
|
return { result: { success: true, idea_id } };
|
|
47
73
|
};
|
|
48
|
-
export const getIdeas = async (args,
|
|
49
|
-
const { project_id, status, limit
|
|
50
|
-
validateRequired(project_id, 'project_id');
|
|
51
|
-
validateUUID(project_id, 'project_id');
|
|
74
|
+
export const getIdeas = async (args, _ctx) => {
|
|
75
|
+
const { project_id, status, limit, offset, search_query } = parseArgs(args, getIdeasSchema);
|
|
52
76
|
const apiClient = getApiClient();
|
|
53
77
|
const response = await apiClient.getIdeas(project_id, {
|
|
54
|
-
status,
|
|
78
|
+
status: status,
|
|
55
79
|
limit,
|
|
56
80
|
offset,
|
|
57
81
|
search_query
|
|
@@ -65,10 +89,8 @@ export const getIdeas = async (args, ctx) => {
|
|
|
65
89
|
},
|
|
66
90
|
};
|
|
67
91
|
};
|
|
68
|
-
export const deleteIdea = async (args,
|
|
69
|
-
const { idea_id } = args;
|
|
70
|
-
validateRequired(idea_id, 'idea_id');
|
|
71
|
-
validateUUID(idea_id, 'idea_id');
|
|
92
|
+
export const deleteIdea = async (args, _ctx) => {
|
|
93
|
+
const { idea_id } = parseArgs(args, deleteIdeaSchema);
|
|
72
94
|
const apiClient = getApiClient();
|
|
73
95
|
const response = await apiClient.deleteIdea(idea_id);
|
|
74
96
|
if (!response.ok) {
|
|
@@ -76,12 +98,8 @@ export const deleteIdea = async (args, ctx) => {
|
|
|
76
98
|
}
|
|
77
99
|
return { result: { success: true } };
|
|
78
100
|
};
|
|
79
|
-
export const convertIdeaToTask = async (args,
|
|
80
|
-
const { idea_id, priority
|
|
81
|
-
validateRequired(idea_id, 'idea_id');
|
|
82
|
-
validateUUID(idea_id, 'idea_id');
|
|
83
|
-
validatePriority(priority);
|
|
84
|
-
validateEstimatedMinutes(estimated_minutes);
|
|
101
|
+
export const convertIdeaToTask = async (args, _ctx) => {
|
|
102
|
+
const { idea_id, priority, estimated_minutes, update_status } = parseArgs(args, convertIdeaToTaskSchema);
|
|
85
103
|
const apiClient = getApiClient();
|
|
86
104
|
// Use proxy for convert_idea_to_task operation
|
|
87
105
|
const response = await apiClient.proxy('convert_idea_to_task', {
|
package/dist/handlers/index.d.ts
CHANGED
|
@@ -24,6 +24,8 @@ export * from './organizations.js';
|
|
|
24
24
|
export * from './cost.js';
|
|
25
25
|
export * from './git-issues.js';
|
|
26
26
|
export * from './sprints.js';
|
|
27
|
+
export * from './file-checkouts.js';
|
|
28
|
+
export * from './roles.js';
|
|
27
29
|
import type { HandlerRegistry } from './types.js';
|
|
28
30
|
/**
|
|
29
31
|
* Build the complete handler registry from all modules
|
package/dist/handlers/index.js
CHANGED
|
@@ -24,6 +24,8 @@ export * from './organizations.js';
|
|
|
24
24
|
export * from './cost.js';
|
|
25
25
|
export * from './git-issues.js';
|
|
26
26
|
export * from './sprints.js';
|
|
27
|
+
export * from './file-checkouts.js';
|
|
28
|
+
export * from './roles.js';
|
|
27
29
|
import { milestoneHandlers } from './milestones.js';
|
|
28
30
|
import { sessionHandlers } from './session.js';
|
|
29
31
|
import { ideaHandlers } from './ideas.js';
|
|
@@ -43,6 +45,8 @@ import { organizationHandlers } from './organizations.js';
|
|
|
43
45
|
import { costHandlers } from './cost.js';
|
|
44
46
|
import { gitIssueHandlers } from './git-issues.js';
|
|
45
47
|
import { sprintHandlers } from './sprints.js';
|
|
48
|
+
import { fileCheckoutHandlers } from './file-checkouts.js';
|
|
49
|
+
import { roleHandlers } from './roles.js';
|
|
46
50
|
/**
|
|
47
51
|
* Build the complete handler registry from all modules
|
|
48
52
|
*/
|
|
@@ -67,5 +71,7 @@ export function buildHandlerRegistry() {
|
|
|
67
71
|
...costHandlers,
|
|
68
72
|
...gitIssueHandlers,
|
|
69
73
|
...sprintHandlers,
|
|
74
|
+
...fileCheckoutHandlers,
|
|
75
|
+
...roleHandlers,
|
|
70
76
|
};
|
|
71
77
|
}
|
|
@@ -10,13 +10,34 @@
|
|
|
10
10
|
*
|
|
11
11
|
* MIGRATED: Uses Vibescope API client instead of direct Supabase
|
|
12
12
|
*/
|
|
13
|
-
import {
|
|
13
|
+
import { parseArgs, uuidValidator, createEnumValidator, ValidationError, } from '../validators.js';
|
|
14
14
|
import { getApiClient } from '../api-client.js';
|
|
15
|
+
const VALID_MILESTONE_STATUSES = ['pending', 'in_progress', 'completed'];
|
|
16
|
+
// Argument schemas for type-safe parsing
|
|
17
|
+
const addMilestoneSchema = {
|
|
18
|
+
task_id: { type: 'string', required: true, validate: uuidValidator },
|
|
19
|
+
title: { type: 'string', required: true },
|
|
20
|
+
description: { type: 'string' },
|
|
21
|
+
order_index: { type: 'number' },
|
|
22
|
+
};
|
|
23
|
+
const updateMilestoneSchema = {
|
|
24
|
+
milestone_id: { type: 'string', required: true, validate: uuidValidator },
|
|
25
|
+
title: { type: 'string' },
|
|
26
|
+
description: { type: 'string' },
|
|
27
|
+
status: { type: 'string', validate: createEnumValidator(VALID_MILESTONE_STATUSES) },
|
|
28
|
+
order_index: { type: 'number' },
|
|
29
|
+
};
|
|
30
|
+
const completeMilestoneSchema = {
|
|
31
|
+
milestone_id: { type: 'string', required: true, validate: uuidValidator },
|
|
32
|
+
};
|
|
33
|
+
const deleteMilestoneSchema = {
|
|
34
|
+
milestone_id: { type: 'string', required: true, validate: uuidValidator },
|
|
35
|
+
};
|
|
36
|
+
const getMilestonesSchema = {
|
|
37
|
+
task_id: { type: 'string', required: true, validate: uuidValidator },
|
|
38
|
+
};
|
|
15
39
|
export const addMilestone = async (args, ctx) => {
|
|
16
|
-
const { task_id, title, description, order_index } = args;
|
|
17
|
-
validateRequired(task_id, 'task_id');
|
|
18
|
-
validateUUID(task_id, 'task_id');
|
|
19
|
-
validateRequired(title, 'title');
|
|
40
|
+
const { task_id, title, description, order_index } = parseArgs(args, addMilestoneSchema);
|
|
20
41
|
const { session } = ctx;
|
|
21
42
|
const apiClient = getApiClient();
|
|
22
43
|
const response = await apiClient.addMilestone(task_id, {
|
|
@@ -34,16 +55,8 @@ export const addMilestone = async (args, ctx) => {
|
|
|
34
55
|
},
|
|
35
56
|
};
|
|
36
57
|
};
|
|
37
|
-
export const updateMilestone = async (args,
|
|
38
|
-
const { milestone_id, title, description, status, order_index } = args;
|
|
39
|
-
validateRequired(milestone_id, 'milestone_id');
|
|
40
|
-
validateUUID(milestone_id, 'milestone_id');
|
|
41
|
-
// Validate status if provided
|
|
42
|
-
if (status !== undefined) {
|
|
43
|
-
if (!['pending', 'in_progress', 'completed'].includes(status)) {
|
|
44
|
-
throw new ValidationError('status must be pending, in_progress, or completed');
|
|
45
|
-
}
|
|
46
|
-
}
|
|
58
|
+
export const updateMilestone = async (args, _ctx) => {
|
|
59
|
+
const { milestone_id, title, description, status, order_index } = parseArgs(args, updateMilestoneSchema);
|
|
47
60
|
// Check that at least one field is provided
|
|
48
61
|
if (title === undefined && description === undefined && status === undefined && order_index === undefined) {
|
|
49
62
|
throw new ValidationError('At least one field to update is required');
|
|
@@ -65,10 +78,8 @@ export const updateMilestone = async (args, ctx) => {
|
|
|
65
78
|
},
|
|
66
79
|
};
|
|
67
80
|
};
|
|
68
|
-
export const completeMilestone = async (args,
|
|
69
|
-
const { milestone_id } = args;
|
|
70
|
-
validateRequired(milestone_id, 'milestone_id');
|
|
71
|
-
validateUUID(milestone_id, 'milestone_id');
|
|
81
|
+
export const completeMilestone = async (args, _ctx) => {
|
|
82
|
+
const { milestone_id } = parseArgs(args, completeMilestoneSchema);
|
|
72
83
|
const apiClient = getApiClient();
|
|
73
84
|
const response = await apiClient.completeMilestone(milestone_id);
|
|
74
85
|
if (!response.ok) {
|
|
@@ -81,10 +92,8 @@ export const completeMilestone = async (args, ctx) => {
|
|
|
81
92
|
},
|
|
82
93
|
};
|
|
83
94
|
};
|
|
84
|
-
export const deleteMilestone = async (args,
|
|
85
|
-
const { milestone_id } = args;
|
|
86
|
-
validateRequired(milestone_id, 'milestone_id');
|
|
87
|
-
validateUUID(milestone_id, 'milestone_id');
|
|
95
|
+
export const deleteMilestone = async (args, _ctx) => {
|
|
96
|
+
const { milestone_id } = parseArgs(args, deleteMilestoneSchema);
|
|
88
97
|
const apiClient = getApiClient();
|
|
89
98
|
const response = await apiClient.deleteMilestone(milestone_id);
|
|
90
99
|
if (!response.ok) {
|
|
@@ -97,10 +106,8 @@ export const deleteMilestone = async (args, ctx) => {
|
|
|
97
106
|
},
|
|
98
107
|
};
|
|
99
108
|
};
|
|
100
|
-
export const getMilestones = async (args,
|
|
101
|
-
const { task_id } = args;
|
|
102
|
-
validateRequired(task_id, 'task_id');
|
|
103
|
-
validateUUID(task_id, 'task_id');
|
|
109
|
+
export const getMilestones = async (args, _ctx) => {
|
|
110
|
+
const { task_id } = parseArgs(args, getMilestonesSchema);
|
|
104
111
|
const apiClient = getApiClient();
|
|
105
112
|
const response = await apiClient.getMilestones(task_id);
|
|
106
113
|
if (!response.ok) {
|