@vibescope/mcp-server 0.0.1 → 0.1.0

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.
Files changed (170) hide show
  1. package/README.md +113 -98
  2. package/dist/api-client.d.ts +1114 -0
  3. package/dist/api-client.js +698 -0
  4. package/dist/cli.d.ts +1 -6
  5. package/dist/cli.js +39 -240
  6. package/dist/config/tool-categories.d.ts +31 -0
  7. package/dist/config/tool-categories.js +253 -0
  8. package/dist/handlers/blockers.js +57 -58
  9. package/dist/handlers/bodies-of-work.d.ts +2 -0
  10. package/dist/handlers/bodies-of-work.js +106 -476
  11. package/dist/handlers/cost.d.ts +1 -0
  12. package/dist/handlers/cost.js +35 -113
  13. package/dist/handlers/decisions.d.ts +2 -0
  14. package/dist/handlers/decisions.js +28 -27
  15. package/dist/handlers/deployment.js +112 -828
  16. package/dist/handlers/discovery.js +31 -0
  17. package/dist/handlers/fallback.d.ts +2 -0
  18. package/dist/handlers/fallback.js +39 -134
  19. package/dist/handlers/findings.js +43 -67
  20. package/dist/handlers/git-issues.d.ts +9 -13
  21. package/dist/handlers/git-issues.js +80 -225
  22. package/dist/handlers/ideas.d.ts +3 -0
  23. package/dist/handlers/ideas.js +53 -134
  24. package/dist/handlers/index.d.ts +2 -0
  25. package/dist/handlers/index.js +6 -0
  26. package/dist/handlers/milestones.d.ts +2 -0
  27. package/dist/handlers/milestones.js +51 -98
  28. package/dist/handlers/organizations.js +79 -275
  29. package/dist/handlers/progress.d.ts +2 -0
  30. package/dist/handlers/progress.js +25 -123
  31. package/dist/handlers/project.js +42 -221
  32. package/dist/handlers/requests.d.ts +2 -0
  33. package/dist/handlers/requests.js +23 -83
  34. package/dist/handlers/session.js +99 -585
  35. package/dist/handlers/sprints.d.ts +32 -0
  36. package/dist/handlers/sprints.js +274 -0
  37. package/dist/handlers/tasks.d.ts +7 -10
  38. package/dist/handlers/tasks.js +230 -900
  39. package/dist/handlers/tool-docs.d.ts +8 -0
  40. package/dist/handlers/tool-docs.js +657 -0
  41. package/dist/handlers/types.d.ts +11 -3
  42. package/dist/handlers/validation.d.ts +1 -1
  43. package/dist/handlers/validation.js +26 -153
  44. package/dist/index.js +473 -160
  45. package/dist/knowledge.js +106 -9
  46. package/dist/tools.js +4 -0
  47. package/dist/validators.d.ts +21 -0
  48. package/dist/validators.js +91 -0
  49. package/package.json +2 -3
  50. package/src/api-client.ts +1752 -0
  51. package/src/cli.test.ts +128 -302
  52. package/src/cli.ts +41 -285
  53. package/src/handlers/__test-setup__.ts +210 -0
  54. package/src/handlers/__test-utils__.ts +4 -134
  55. package/src/handlers/blockers.test.ts +114 -124
  56. package/src/handlers/blockers.ts +68 -70
  57. package/src/handlers/bodies-of-work.test.ts +236 -831
  58. package/src/handlers/bodies-of-work.ts +194 -525
  59. package/src/handlers/cost.test.ts +149 -113
  60. package/src/handlers/cost.ts +44 -132
  61. package/src/handlers/decisions.test.ts +111 -209
  62. package/src/handlers/decisions.ts +35 -27
  63. package/src/handlers/deployment.test.ts +193 -239
  64. package/src/handlers/deployment.ts +140 -895
  65. package/src/handlers/discovery.test.ts +20 -67
  66. package/src/handlers/discovery.ts +32 -0
  67. package/src/handlers/fallback.test.ts +128 -361
  68. package/src/handlers/fallback.ts +62 -148
  69. package/src/handlers/findings.test.ts +127 -345
  70. package/src/handlers/findings.ts +49 -66
  71. package/src/handlers/git-issues.test.ts +623 -0
  72. package/src/handlers/git-issues.ts +174 -0
  73. package/src/handlers/ideas.test.ts +229 -343
  74. package/src/handlers/ideas.ts +69 -143
  75. package/src/handlers/index.ts +6 -0
  76. package/src/handlers/milestones.test.ts +167 -281
  77. package/src/handlers/milestones.ts +54 -93
  78. package/src/handlers/organizations.test.ts +275 -467
  79. package/src/handlers/organizations.ts +84 -294
  80. package/src/handlers/progress.test.ts +112 -218
  81. package/src/handlers/progress.ts +29 -142
  82. package/src/handlers/project.test.ts +203 -226
  83. package/src/handlers/project.ts +48 -238
  84. package/src/handlers/requests.test.ts +74 -342
  85. package/src/handlers/requests.ts +25 -83
  86. package/src/handlers/session.test.ts +241 -206
  87. package/src/handlers/session.ts +110 -657
  88. package/src/handlers/sprints.test.ts +711 -0
  89. package/src/handlers/sprints.ts +497 -0
  90. package/src/handlers/tasks.test.ts +608 -353
  91. package/src/handlers/tasks.ts +248 -1025
  92. package/src/handlers/types.ts +12 -4
  93. package/src/handlers/validation.test.ts +189 -572
  94. package/src/handlers/validation.ts +29 -166
  95. package/src/index.ts +473 -184
  96. package/src/knowledge.ts +107 -9
  97. package/src/tools.ts +2506 -0
  98. package/src/validators.test.ts +223 -223
  99. package/src/validators.ts +127 -0
  100. package/tsconfig.json +1 -1
  101. package/vitest.config.ts +14 -13
  102. package/dist/cli.test.d.ts +0 -1
  103. package/dist/cli.test.js +0 -367
  104. package/dist/handlers/__test-utils__.d.ts +0 -72
  105. package/dist/handlers/__test-utils__.js +0 -176
  106. package/dist/handlers/checkouts.d.ts +0 -37
  107. package/dist/handlers/checkouts.js +0 -377
  108. package/dist/handlers/knowledge-query.d.ts +0 -22
  109. package/dist/handlers/knowledge-query.js +0 -253
  110. package/dist/handlers/knowledge.d.ts +0 -12
  111. package/dist/handlers/knowledge.js +0 -108
  112. package/dist/handlers/roles.d.ts +0 -30
  113. package/dist/handlers/roles.js +0 -281
  114. package/dist/handlers/tasks.test.d.ts +0 -1
  115. package/dist/handlers/tasks.test.js +0 -431
  116. package/dist/utils.test.d.ts +0 -1
  117. package/dist/utils.test.js +0 -532
  118. package/dist/validators.test.d.ts +0 -1
  119. package/dist/validators.test.js +0 -176
  120. package/src/tmpclaude-0078-cwd +0 -1
  121. package/src/tmpclaude-0ee1-cwd +0 -1
  122. package/src/tmpclaude-2dd5-cwd +0 -1
  123. package/src/tmpclaude-344c-cwd +0 -1
  124. package/src/tmpclaude-3860-cwd +0 -1
  125. package/src/tmpclaude-4b63-cwd +0 -1
  126. package/src/tmpclaude-5c73-cwd +0 -1
  127. package/src/tmpclaude-5ee3-cwd +0 -1
  128. package/src/tmpclaude-6795-cwd +0 -1
  129. package/src/tmpclaude-709e-cwd +0 -1
  130. package/src/tmpclaude-9839-cwd +0 -1
  131. package/src/tmpclaude-d829-cwd +0 -1
  132. package/src/tmpclaude-e072-cwd +0 -1
  133. package/src/tmpclaude-f6ee-cwd +0 -1
  134. package/tmpclaude-0439-cwd +0 -1
  135. package/tmpclaude-132f-cwd +0 -1
  136. package/tmpclaude-15bb-cwd +0 -1
  137. package/tmpclaude-165a-cwd +0 -1
  138. package/tmpclaude-1ba9-cwd +0 -1
  139. package/tmpclaude-21a3-cwd +0 -1
  140. package/tmpclaude-2a38-cwd +0 -1
  141. package/tmpclaude-2adf-cwd +0 -1
  142. package/tmpclaude-2f56-cwd +0 -1
  143. package/tmpclaude-3626-cwd +0 -1
  144. package/tmpclaude-3727-cwd +0 -1
  145. package/tmpclaude-40bc-cwd +0 -1
  146. package/tmpclaude-436f-cwd +0 -1
  147. package/tmpclaude-4783-cwd +0 -1
  148. package/tmpclaude-4b6d-cwd +0 -1
  149. package/tmpclaude-4ba4-cwd +0 -1
  150. package/tmpclaude-51e6-cwd +0 -1
  151. package/tmpclaude-5ecf-cwd +0 -1
  152. package/tmpclaude-6f97-cwd +0 -1
  153. package/tmpclaude-7fb2-cwd +0 -1
  154. package/tmpclaude-825c-cwd +0 -1
  155. package/tmpclaude-8baf-cwd +0 -1
  156. package/tmpclaude-8d9f-cwd +0 -1
  157. package/tmpclaude-975c-cwd +0 -1
  158. package/tmpclaude-9983-cwd +0 -1
  159. package/tmpclaude-a045-cwd +0 -1
  160. package/tmpclaude-ac4a-cwd +0 -1
  161. package/tmpclaude-b593-cwd +0 -1
  162. package/tmpclaude-b891-cwd +0 -1
  163. package/tmpclaude-c032-cwd +0 -1
  164. package/tmpclaude-cf43-cwd +0 -1
  165. package/tmpclaude-d040-cwd +0 -1
  166. package/tmpclaude-dcdd-cwd +0 -1
  167. package/tmpclaude-dcee-cwd +0 -1
  168. package/tmpclaude-e16b-cwd +0 -1
  169. package/tmpclaude-ecd2-cwd +0 -1
  170. package/tmpclaude-f48d-cwd +0 -1
@@ -1,247 +1,102 @@
1
1
  /**
2
2
  * Git Issues Handlers
3
3
  *
4
- * Handles git-related issue tracking:
5
- * - get_git_issues
6
- * - create_git_issue
7
- * - resolve_git_issue
8
- * - dismiss_git_issue
4
+ * Handles git issue management:
5
+ * - add_git_issue: Record a git-related issue (conflicts, push failures, etc.)
6
+ * - resolve_git_issue: Mark a git issue as resolved
7
+ * - get_git_issues: List git issues for a project
8
+ * - delete_git_issue: Remove a git issue
9
9
  */
10
10
  import { validateRequired, validateUUID } from '../validators.js';
11
- export const getGitIssues = async (args, ctx) => {
12
- const { project_id, status = 'open', include_resolved = false } = args;
11
+ import { getApiClient } from '../api-client.js';
12
+ const VALID_GIT_ISSUE_TYPES = [
13
+ 'merge_conflict',
14
+ 'push_failed',
15
+ 'rebase_needed',
16
+ 'branch_diverged',
17
+ 'pr_not_mergeable',
18
+ ];
19
+ const VALID_GIT_ISSUE_STATUSES = ['open', 'resolved'];
20
+ export const addGitIssue = async (args, ctx) => {
21
+ const { project_id, issue_type, branch, target_branch, pr_url, conflicting_files, error_message, task_id, } = args;
13
22
  validateRequired(project_id, 'project_id');
14
23
  validateUUID(project_id, 'project_id');
15
- const { supabase } = ctx;
16
- let query = supabase
17
- .from('git_issues')
18
- .select(`
19
- id,
20
- task_id,
21
- issue_type,
22
- severity,
23
- branch_name,
24
- pr_number,
25
- pr_url,
26
- target_branch,
27
- conflicting_files,
28
- error_message,
29
- status,
30
- created_at,
31
- resolved_at,
32
- auto_resolved,
33
- resolution_note
34
- `)
35
- .eq('project_id', project_id)
36
- .order('created_at', { ascending: false });
37
- if (status !== 'all' && !include_resolved) {
38
- query = query.eq('status', status);
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(', ')}`);
39
28
  }
40
- const { data: issues, error } = await query.limit(50);
41
- if (error)
42
- throw new Error(`Failed to fetch git issues: ${error.message}`);
43
- // Group by severity for summary
44
- const summary = {
45
- critical: 0,
46
- high: 0,
47
- medium: 0,
48
- low: 0,
49
- };
50
- const openIssues = (issues || []).filter(i => i.status === 'open');
51
- openIssues.forEach(issue => {
52
- const sev = issue.severity;
53
- if (sev in summary)
54
- summary[sev]++;
55
- });
56
- return {
57
- result: {
58
- issues: issues || [],
59
- open_count: openIssues.length,
60
- severity_summary: summary,
61
- has_critical: summary.critical > 0,
62
- has_blocking: summary.critical > 0 || summary.high > 0,
63
- },
64
- };
29
+ if (task_id) {
30
+ validateUUID(task_id, 'task_id');
31
+ }
32
+ const apiClient = getApiClient();
33
+ const response = await apiClient.addGitIssue(project_id, {
34
+ issue_type: issue_type,
35
+ branch,
36
+ target_branch,
37
+ pr_url,
38
+ conflicting_files,
39
+ error_message,
40
+ task_id
41
+ }, ctx.session.currentSessionId || undefined);
42
+ if (!response.ok) {
43
+ throw new Error(response.error || 'Failed to add git issue');
44
+ }
45
+ return { result: response.data };
65
46
  };
66
- export const createGitIssue = async (args, ctx) => {
67
- const { project_id, task_id, issue_type, severity = 'medium', branch_name, pr_number, pr_url, target_branch, conflicting_files, error_message, } = args;
47
+ 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');
51
+ const apiClient = getApiClient();
52
+ const response = await apiClient.resolveGitIssue(git_issue_id, {
53
+ resolution_note,
54
+ auto_resolved
55
+ }, ctx.session.currentSessionId || undefined);
56
+ if (!response.ok) {
57
+ throw new Error(response.error || 'Failed to resolve git issue');
58
+ }
59
+ return { result: response.data };
60
+ };
61
+ export const getGitIssues = async (args, ctx) => {
62
+ const { project_id, status = 'open', issue_type, branch, limit = 50, } = args;
68
63
  validateRequired(project_id, 'project_id');
69
64
  validateUUID(project_id, 'project_id');
70
- validateRequired(issue_type, 'issue_type');
71
- const { supabase, session } = ctx;
72
- // Check if similar issue already exists (avoid duplicates)
73
- if (branch_name || pr_number) {
74
- const { data: existing } = await supabase
75
- .from('git_issues')
76
- .select('id')
77
- .eq('project_id', project_id)
78
- .eq('status', 'open')
79
- .eq('issue_type', issue_type)
80
- .or(`branch_name.eq.${branch_name},pr_number.eq.${pr_number}`)
81
- .limit(1)
82
- .maybeSingle();
83
- if (existing) {
84
- return {
85
- result: {
86
- success: false,
87
- already_exists: true,
88
- existing_issue_id: existing.id,
89
- message: 'A similar git issue already exists for this branch/PR',
90
- },
91
- };
92
- }
65
+ if (status && !VALID_GIT_ISSUE_STATUSES.includes(status)) {
66
+ throw new Error(`Invalid status. Valid statuses: ${VALID_GIT_ISSUE_STATUSES.join(', ')}`);
93
67
  }
94
- const { data: issue, error } = await supabase
95
- .from('git_issues')
96
- .insert({
97
- project_id,
98
- task_id: task_id || null,
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
+ }
71
+ const apiClient = getApiClient();
72
+ const response = await apiClient.getGitIssues(project_id, {
73
+ status,
99
74
  issue_type,
100
- severity,
101
- branch_name: branch_name || null,
102
- pr_number: pr_number || null,
103
- pr_url: pr_url || null,
104
- target_branch: target_branch || null,
105
- conflicting_files: conflicting_files || [],
106
- error_message: error_message || null,
107
- created_by: 'agent',
108
- created_by_session_id: session.currentSessionId,
109
- })
110
- .select('id, issue_type, severity, branch_name, pr_number')
111
- .single();
112
- if (error)
113
- throw new Error(`Failed to create git issue: ${error.message}`);
114
- // Log progress
115
- await supabase.from('progress_logs').insert({
116
- project_id,
117
- task_id: task_id || null,
118
- summary: `Git issue created: ${issue_type} on ${branch_name || `PR #${pr_number}`}`,
119
- details: error_message || null,
120
- created_by: 'agent',
121
- created_by_session_id: session.currentSessionId,
75
+ branch,
76
+ limit
122
77
  });
123
- return {
124
- result: {
125
- success: true,
126
- issue_id: issue.id,
127
- issue_type: issue.issue_type,
128
- severity: issue.severity,
129
- branch: issue.branch_name,
130
- pr_number: issue.pr_number,
131
- },
132
- };
133
- };
134
- export const resolveGitIssue = async (args, ctx) => {
135
- const { issue_id, resolution_note, auto_resolved = false } = args;
136
- validateRequired(issue_id, 'issue_id');
137
- validateUUID(issue_id, 'issue_id');
138
- const { supabase, session } = ctx;
139
- // Get the issue first
140
- const { data: issue, error: fetchError } = await supabase
141
- .from('git_issues')
142
- .select('id, project_id, task_id, issue_type, branch_name, pr_number, status')
143
- .eq('id', issue_id)
144
- .single();
145
- if (fetchError || !issue)
146
- throw new Error('Git issue not found');
147
- if (issue.status !== 'open') {
148
- return {
149
- result: {
150
- success: false,
151
- error: `Issue is already ${issue.status}`,
152
- },
153
- };
78
+ if (!response.ok) {
79
+ throw new Error(response.error || 'Failed to fetch git issues');
154
80
  }
155
- const { error: updateError } = await supabase
156
- .from('git_issues')
157
- .update({
158
- status: 'resolved',
159
- resolved_at: new Date().toISOString(),
160
- resolved_by_session_id: session.currentSessionId,
161
- auto_resolved,
162
- resolution_note: resolution_note || null,
163
- })
164
- .eq('id', issue_id);
165
- if (updateError)
166
- throw new Error(`Failed to resolve git issue: ${updateError.message}`);
167
- // Log progress
168
- await supabase.from('progress_logs').insert({
169
- project_id: issue.project_id,
170
- task_id: issue.task_id,
171
- summary: `Git issue resolved: ${issue.issue_type} on ${issue.branch_name || `PR #${issue.pr_number}`}${auto_resolved ? ' (auto)' : ''}`,
172
- details: resolution_note || null,
173
- created_by: 'agent',
174
- created_by_session_id: session.currentSessionId,
175
- });
176
- return {
177
- result: {
178
- success: true,
179
- resolved_issue_id: issue_id,
180
- auto_resolved,
181
- },
182
- };
183
- };
184
- export const dismissGitIssue = async (args, ctx) => {
185
- const { issue_id, reason } = args;
186
- validateRequired(issue_id, 'issue_id');
187
- validateUUID(issue_id, 'issue_id');
188
- const { supabase, session } = ctx;
189
- const { error } = await supabase
190
- .from('git_issues')
191
- .update({
192
- status: 'dismissed',
193
- resolved_at: new Date().toISOString(),
194
- resolved_by_session_id: session.currentSessionId,
195
- resolution_note: reason || 'Dismissed',
196
- })
197
- .eq('id', issue_id);
198
- if (error)
199
- throw new Error(`Failed to dismiss git issue: ${error.message}`);
200
- return {
201
- result: {
202
- success: true,
203
- dismissed_issue_id: issue_id,
204
- },
205
- };
81
+ return { result: response.data };
206
82
  };
207
- /**
208
- * Auto-resolve git issues for a branch when it becomes mergeable
209
- */
210
- export async function autoResolveGitIssuesForBranch(supabase, projectId, branchName, sessionId) {
211
- const { data: issues } = await supabase
212
- .from('git_issues')
213
- .select('id')
214
- .eq('project_id', projectId)
215
- .eq('branch_name', branchName)
216
- .eq('status', 'open')
217
- .in('issue_type', ['merge_conflict', 'rebase_needed']);
218
- if (!issues || issues.length === 0)
219
- return 0;
220
- const { error } = await supabase
221
- .from('git_issues')
222
- .update({
223
- status: 'resolved',
224
- resolved_at: new Date().toISOString(),
225
- resolved_by_session_id: sessionId,
226
- auto_resolved: true,
227
- resolution_note: 'Auto-resolved: branch is now mergeable',
228
- })
229
- .eq('project_id', projectId)
230
- .eq('branch_name', branchName)
231
- .eq('status', 'open')
232
- .in('issue_type', ['merge_conflict', 'rebase_needed']);
233
- if (error) {
234
- console.error('Failed to auto-resolve git issues:', error);
235
- return 0;
83
+ export const deleteGitIssue = async (args, ctx) => {
84
+ const { git_issue_id } = args;
85
+ validateRequired(git_issue_id, 'git_issue_id');
86
+ validateUUID(git_issue_id, 'git_issue_id');
87
+ const apiClient = getApiClient();
88
+ const response = await apiClient.deleteGitIssue(git_issue_id);
89
+ if (!response.ok) {
90
+ throw new Error(response.error || 'Failed to delete git issue');
236
91
  }
237
- return issues.length;
238
- }
92
+ return { result: response.data };
93
+ };
239
94
  /**
240
95
  * Git Issues handlers registry
241
96
  */
242
- export const gitIssuesHandlers = {
243
- get_git_issues: getGitIssues,
244
- create_git_issue: createGitIssue,
97
+ export const gitIssueHandlers = {
98
+ add_git_issue: addGitIssue,
245
99
  resolve_git_issue: resolveGitIssue,
246
- dismiss_git_issue: dismissGitIssue,
100
+ get_git_issues: getGitIssues,
101
+ delete_git_issue: deleteGitIssue,
247
102
  };
@@ -6,6 +6,9 @@
6
6
  * - update_idea
7
7
  * - get_ideas
8
8
  * - delete_idea
9
+ * - convert_idea_to_task
10
+ *
11
+ * MIGRATED: Uses Vibescope API client instead of direct Supabase
9
12
  */
10
13
  import type { Handler, HandlerRegistry } from './types.js';
11
14
  export declare const addIdea: Handler;
@@ -6,94 +6,74 @@
6
6
  * - update_idea
7
7
  * - get_ideas
8
8
  * - delete_idea
9
+ * - convert_idea_to_task
10
+ *
11
+ * MIGRATED: Uses Vibescope API client instead of direct Supabase
9
12
  */
10
13
  import { validateRequired, validateUUID, validatePriority, validateEstimatedMinutes } from '../validators.js';
14
+ import { getApiClient } from '../api-client.js';
11
15
  export const addIdea = async (args, ctx) => {
12
16
  const { project_id, title, description, status } = args;
13
17
  validateRequired(project_id, 'project_id');
14
18
  validateUUID(project_id, 'project_id');
15
19
  validateRequired(title, 'title');
16
- const { supabase, session } = ctx;
17
- const { data, error } = await supabase
18
- .from('ideas')
19
- .insert({
20
- project_id,
20
+ const { session } = ctx;
21
+ const apiClient = getApiClient();
22
+ const response = await apiClient.addIdea(project_id, {
21
23
  title,
22
- description: description || null,
23
- status: status || 'raw',
24
- created_by: 'agent',
25
- created_by_session_id: session.currentSessionId,
26
- })
27
- .select('id')
28
- .single();
29
- if (error)
30
- throw new Error(`Failed to add idea: ${error.message}`);
31
- return { result: { success: true, idea_id: data.id, title } };
24
+ description,
25
+ status
26
+ }, session.currentSessionId || undefined);
27
+ if (!response.ok) {
28
+ throw new Error(`Failed to add idea: ${response.error}`);
29
+ }
30
+ return { result: { success: true, idea_id: response.data?.idea_id, title } };
32
31
  };
33
32
  export const updateIdea = async (args, ctx) => {
34
33
  const { idea_id, title, description, status, doc_url } = args;
35
34
  validateRequired(idea_id, 'idea_id');
36
35
  validateUUID(idea_id, 'idea_id');
37
- const { supabase } = ctx;
38
- // Get current idea status
39
- const { data: existingIdea } = await supabase
40
- .from('ideas')
41
- .select('status')
42
- .eq('id', idea_id)
43
- .single();
44
- if (!existingIdea) {
45
- throw new Error(`Idea not found: ${idea_id}`);
46
- }
47
- // Build update object
48
- const updates = { updated_at: new Date().toISOString() };
49
- if (title !== undefined)
50
- updates.title = title;
51
- if (description !== undefined)
52
- updates.description = description;
53
- if (doc_url !== undefined)
54
- updates.doc_url = doc_url;
55
- if (status !== undefined) {
56
- updates.status = status;
57
- // Set planned_at when transitioning to planned status
58
- if (status === 'planned' && existingIdea.status !== 'planned') {
59
- updates.planned_at = new Date().toISOString();
60
- }
36
+ const apiClient = getApiClient();
37
+ const response = await apiClient.updateIdea(idea_id, {
38
+ title,
39
+ description,
40
+ status,
41
+ doc_url
42
+ });
43
+ if (!response.ok) {
44
+ throw new Error(`Failed to update idea: ${response.error}`);
61
45
  }
62
- const { error } = await supabase
63
- .from('ideas')
64
- .update(updates)
65
- .eq('id', idea_id);
66
- if (error)
67
- throw new Error(`Failed to update idea: ${error.message}`);
68
46
  return { result: { success: true, idea_id } };
69
47
  };
70
48
  export const getIdeas = async (args, ctx) => {
71
- const { project_id, status } = args;
49
+ const { project_id, status, limit = 50, offset = 0, search_query } = args;
72
50
  validateRequired(project_id, 'project_id');
73
51
  validateUUID(project_id, 'project_id');
74
- const { supabase } = ctx;
75
- let query = supabase
76
- .from('ideas')
77
- .select('id, title, description, status, doc_url')
78
- .eq('project_id', project_id);
79
- if (status) {
80
- query = query.eq('status', status);
52
+ const apiClient = getApiClient();
53
+ const response = await apiClient.getIdeas(project_id, {
54
+ status,
55
+ limit,
56
+ offset,
57
+ search_query
58
+ });
59
+ if (!response.ok) {
60
+ throw new Error(`Failed to fetch ideas: ${response.error}`);
81
61
  }
82
- const { data, error } = await query.order('created_at', { ascending: false });
83
- if (error)
84
- throw new Error(`Failed to fetch ideas: ${error.message}`);
85
- return { result: { ideas: data || [] } };
62
+ return {
63
+ result: {
64
+ ideas: response.data?.ideas || [],
65
+ },
66
+ };
86
67
  };
87
68
  export const deleteIdea = async (args, ctx) => {
88
69
  const { idea_id } = args;
89
70
  validateRequired(idea_id, 'idea_id');
90
71
  validateUUID(idea_id, 'idea_id');
91
- const { error } = await ctx.supabase
92
- .from('ideas')
93
- .delete()
94
- .eq('id', idea_id);
95
- if (error)
96
- throw new Error(`Failed to delete idea: ${error.message}`);
72
+ const apiClient = getApiClient();
73
+ const response = await apiClient.deleteIdea(idea_id);
74
+ if (!response.ok) {
75
+ throw new Error(`Failed to delete idea: ${response.error}`);
76
+ }
97
77
  return { result: { success: true } };
98
78
  };
99
79
  export const convertIdeaToTask = async (args, ctx) => {
@@ -102,79 +82,18 @@ export const convertIdeaToTask = async (args, ctx) => {
102
82
  validateUUID(idea_id, 'idea_id');
103
83
  validatePriority(priority);
104
84
  validateEstimatedMinutes(estimated_minutes);
105
- const { supabase, session } = ctx;
106
- const currentSessionId = session.currentSessionId;
107
- // Get the idea
108
- const { data: idea, error: fetchError } = await supabase
109
- .from('ideas')
110
- .select('id, project_id, title, description, status, converted_to_task_id')
111
- .eq('id', idea_id)
112
- .single();
113
- if (fetchError || !idea) {
114
- throw new Error(`Idea not found: ${idea_id}`);
115
- }
116
- // Check if already converted
117
- if (idea.converted_to_task_id) {
118
- return {
119
- result: {
120
- success: false,
121
- error: 'Idea has already been converted to a task',
122
- existing_task_id: idea.converted_to_task_id,
123
- hint: 'Use get_tasks to find the existing task',
124
- },
125
- };
126
- }
127
- // Create the task
128
- const { data: task, error: taskError } = await supabase
129
- .from('tasks')
130
- .insert({
131
- project_id: idea.project_id,
132
- title: idea.title,
133
- description: idea.description || `Converted from idea: ${idea.title}`,
85
+ const apiClient = getApiClient();
86
+ // Use proxy for convert_idea_to_task operation
87
+ const response = await apiClient.proxy('convert_idea_to_task', {
88
+ idea_id,
134
89
  priority,
135
- estimated_minutes: estimated_minutes || null,
136
- created_by: 'agent',
137
- created_by_session_id: currentSessionId,
138
- })
139
- .select('id, title')
140
- .single();
141
- if (taskError || !task) {
142
- throw new Error(`Failed to create task: ${taskError?.message}`);
143
- }
144
- // Update the idea with the task reference and optionally update status
145
- const ideaUpdates = {
146
- converted_to_task_id: task.id,
147
- updated_at: new Date().toISOString(),
148
- };
149
- if (update_status && idea.status !== 'shipped') {
150
- ideaUpdates.status = 'in_development';
151
- }
152
- const { error: updateError } = await supabase
153
- .from('ideas')
154
- .update(ideaUpdates)
155
- .eq('id', idea_id);
156
- if (updateError) {
157
- // Log but don't fail - task was created successfully
158
- console.error(`Failed to update idea after conversion: ${updateError.message}`);
159
- }
160
- // Log progress
161
- await supabase.from('progress_logs').insert({
162
- project_id: idea.project_id,
163
- task_id: task.id,
164
- summary: `Converted idea "${idea.title}" to task`,
165
- created_by: 'agent',
166
- created_by_session_id: currentSessionId,
90
+ estimated_minutes,
91
+ update_status
167
92
  });
168
- return {
169
- result: {
170
- success: true,
171
- task_id: task.id,
172
- task_title: task.title,
173
- idea_id: idea.id,
174
- idea_status: update_status ? 'in_development' : idea.status,
175
- message: `Created task from idea. Start with: update_task(task_id: "${task.id}", status: "in_progress")`,
176
- },
177
- };
93
+ if (!response.ok) {
94
+ throw new Error(`Failed to convert idea: ${response.error}`);
95
+ }
96
+ return { result: response.data };
178
97
  };
179
98
  /**
180
99
  * Ideas handlers registry
@@ -22,6 +22,8 @@ export * from './bodies-of-work.js';
22
22
  export * from './discovery.js';
23
23
  export * from './organizations.js';
24
24
  export * from './cost.js';
25
+ export * from './git-issues.js';
26
+ export * from './sprints.js';
25
27
  import type { HandlerRegistry } from './types.js';
26
28
  /**
27
29
  * Build the complete handler registry from all modules
@@ -22,6 +22,8 @@ export * from './bodies-of-work.js';
22
22
  export * from './discovery.js';
23
23
  export * from './organizations.js';
24
24
  export * from './cost.js';
25
+ export * from './git-issues.js';
26
+ export * from './sprints.js';
25
27
  import { milestoneHandlers } from './milestones.js';
26
28
  import { sessionHandlers } from './session.js';
27
29
  import { ideaHandlers } from './ideas.js';
@@ -39,6 +41,8 @@ import { bodiesOfWorkHandlers } from './bodies-of-work.js';
39
41
  import { discoveryHandlers } from './discovery.js';
40
42
  import { organizationHandlers } from './organizations.js';
41
43
  import { costHandlers } from './cost.js';
44
+ import { gitIssueHandlers } from './git-issues.js';
45
+ import { sprintHandlers } from './sprints.js';
42
46
  /**
43
47
  * Build the complete handler registry from all modules
44
48
  */
@@ -61,5 +65,7 @@ export function buildHandlerRegistry() {
61
65
  ...discoveryHandlers,
62
66
  ...organizationHandlers,
63
67
  ...costHandlers,
68
+ ...gitIssueHandlers,
69
+ ...sprintHandlers,
64
70
  };
65
71
  }
@@ -7,6 +7,8 @@
7
7
  * - complete_milestone
8
8
  * - delete_milestone
9
9
  * - get_milestones
10
+ *
11
+ * MIGRATED: Uses Vibescope API client instead of direct Supabase
10
12
  */
11
13
  import type { Handler, HandlerRegistry } from './types.js';
12
14
  export declare const addMilestone: Handler;