@vibescope/mcp-server 0.0.1 → 0.2.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 (173) hide show
  1. package/README.md +113 -98
  2. package/dist/api-client.d.ts +1169 -0
  3. package/dist/api-client.js +713 -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 +108 -477
  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 +113 -828
  16. package/dist/handlers/discovery.d.ts +3 -0
  17. package/dist/handlers/discovery.js +26 -627
  18. package/dist/handlers/fallback.d.ts +2 -0
  19. package/dist/handlers/fallback.js +56 -142
  20. package/dist/handlers/findings.d.ts +8 -1
  21. package/dist/handlers/findings.js +65 -68
  22. package/dist/handlers/git-issues.d.ts +9 -13
  23. package/dist/handlers/git-issues.js +80 -225
  24. package/dist/handlers/ideas.d.ts +3 -0
  25. package/dist/handlers/ideas.js +53 -134
  26. package/dist/handlers/index.d.ts +2 -0
  27. package/dist/handlers/index.js +6 -0
  28. package/dist/handlers/milestones.d.ts +2 -0
  29. package/dist/handlers/milestones.js +51 -98
  30. package/dist/handlers/organizations.js +79 -275
  31. package/dist/handlers/progress.d.ts +2 -0
  32. package/dist/handlers/progress.js +25 -123
  33. package/dist/handlers/project.js +42 -221
  34. package/dist/handlers/requests.d.ts +2 -0
  35. package/dist/handlers/requests.js +23 -83
  36. package/dist/handlers/session.js +119 -590
  37. package/dist/handlers/sprints.d.ts +32 -0
  38. package/dist/handlers/sprints.js +275 -0
  39. package/dist/handlers/tasks.d.ts +7 -10
  40. package/dist/handlers/tasks.js +245 -894
  41. package/dist/handlers/tool-docs.d.ts +9 -0
  42. package/dist/handlers/tool-docs.js +904 -0
  43. package/dist/handlers/types.d.ts +11 -3
  44. package/dist/handlers/validation.d.ts +1 -1
  45. package/dist/handlers/validation.js +38 -153
  46. package/dist/index.js +493 -162
  47. package/dist/knowledge.js +106 -9
  48. package/dist/tools.js +34 -4
  49. package/dist/validators.d.ts +21 -0
  50. package/dist/validators.js +91 -0
  51. package/package.json +2 -3
  52. package/src/api-client.ts +1822 -0
  53. package/src/cli.test.ts +128 -302
  54. package/src/cli.ts +41 -285
  55. package/src/handlers/__test-setup__.ts +215 -0
  56. package/src/handlers/__test-utils__.ts +4 -134
  57. package/src/handlers/blockers.test.ts +114 -124
  58. package/src/handlers/blockers.ts +68 -70
  59. package/src/handlers/bodies-of-work.test.ts +236 -831
  60. package/src/handlers/bodies-of-work.ts +210 -525
  61. package/src/handlers/cost.test.ts +149 -113
  62. package/src/handlers/cost.ts +44 -132
  63. package/src/handlers/decisions.test.ts +111 -209
  64. package/src/handlers/decisions.ts +35 -27
  65. package/src/handlers/deployment.test.ts +193 -239
  66. package/src/handlers/deployment.ts +143 -896
  67. package/src/handlers/discovery.test.ts +20 -67
  68. package/src/handlers/discovery.ts +29 -714
  69. package/src/handlers/fallback.test.ts +206 -361
  70. package/src/handlers/fallback.ts +81 -156
  71. package/src/handlers/findings.test.ts +229 -320
  72. package/src/handlers/findings.ts +76 -64
  73. package/src/handlers/git-issues.test.ts +623 -0
  74. package/src/handlers/git-issues.ts +174 -0
  75. package/src/handlers/ideas.test.ts +229 -343
  76. package/src/handlers/ideas.ts +69 -143
  77. package/src/handlers/index.ts +6 -0
  78. package/src/handlers/milestones.test.ts +167 -281
  79. package/src/handlers/milestones.ts +54 -93
  80. package/src/handlers/organizations.test.ts +275 -467
  81. package/src/handlers/organizations.ts +84 -294
  82. package/src/handlers/progress.test.ts +112 -218
  83. package/src/handlers/progress.ts +29 -142
  84. package/src/handlers/project.test.ts +203 -226
  85. package/src/handlers/project.ts +48 -238
  86. package/src/handlers/requests.test.ts +74 -342
  87. package/src/handlers/requests.ts +25 -83
  88. package/src/handlers/session.test.ts +276 -206
  89. package/src/handlers/session.ts +136 -662
  90. package/src/handlers/sprints.test.ts +711 -0
  91. package/src/handlers/sprints.ts +510 -0
  92. package/src/handlers/tasks.test.ts +669 -353
  93. package/src/handlers/tasks.ts +263 -1015
  94. package/src/handlers/tool-docs.ts +1024 -0
  95. package/src/handlers/types.ts +12 -4
  96. package/src/handlers/validation.test.ts +237 -568
  97. package/src/handlers/validation.ts +43 -167
  98. package/src/index.ts +493 -186
  99. package/src/tools.ts +2532 -0
  100. package/src/validators.test.ts +223 -223
  101. package/src/validators.ts +127 -0
  102. package/tsconfig.json +1 -1
  103. package/vitest.config.ts +14 -13
  104. package/dist/cli.test.d.ts +0 -1
  105. package/dist/cli.test.js +0 -367
  106. package/dist/handlers/__test-utils__.d.ts +0 -72
  107. package/dist/handlers/__test-utils__.js +0 -176
  108. package/dist/handlers/checkouts.d.ts +0 -37
  109. package/dist/handlers/checkouts.js +0 -377
  110. package/dist/handlers/knowledge-query.d.ts +0 -22
  111. package/dist/handlers/knowledge-query.js +0 -253
  112. package/dist/handlers/knowledge.d.ts +0 -12
  113. package/dist/handlers/knowledge.js +0 -108
  114. package/dist/handlers/roles.d.ts +0 -30
  115. package/dist/handlers/roles.js +0 -281
  116. package/dist/handlers/tasks.test.d.ts +0 -1
  117. package/dist/handlers/tasks.test.js +0 -431
  118. package/dist/utils.test.d.ts +0 -1
  119. package/dist/utils.test.js +0 -532
  120. package/dist/validators.test.d.ts +0 -1
  121. package/dist/validators.test.js +0 -176
  122. package/src/knowledge.ts +0 -132
  123. package/src/tmpclaude-0078-cwd +0 -1
  124. package/src/tmpclaude-0ee1-cwd +0 -1
  125. package/src/tmpclaude-2dd5-cwd +0 -1
  126. package/src/tmpclaude-344c-cwd +0 -1
  127. package/src/tmpclaude-3860-cwd +0 -1
  128. package/src/tmpclaude-4b63-cwd +0 -1
  129. package/src/tmpclaude-5c73-cwd +0 -1
  130. package/src/tmpclaude-5ee3-cwd +0 -1
  131. package/src/tmpclaude-6795-cwd +0 -1
  132. package/src/tmpclaude-709e-cwd +0 -1
  133. package/src/tmpclaude-9839-cwd +0 -1
  134. package/src/tmpclaude-d829-cwd +0 -1
  135. package/src/tmpclaude-e072-cwd +0 -1
  136. package/src/tmpclaude-f6ee-cwd +0 -1
  137. package/tmpclaude-0439-cwd +0 -1
  138. package/tmpclaude-132f-cwd +0 -1
  139. package/tmpclaude-15bb-cwd +0 -1
  140. package/tmpclaude-165a-cwd +0 -1
  141. package/tmpclaude-1ba9-cwd +0 -1
  142. package/tmpclaude-21a3-cwd +0 -1
  143. package/tmpclaude-2a38-cwd +0 -1
  144. package/tmpclaude-2adf-cwd +0 -1
  145. package/tmpclaude-2f56-cwd +0 -1
  146. package/tmpclaude-3626-cwd +0 -1
  147. package/tmpclaude-3727-cwd +0 -1
  148. package/tmpclaude-40bc-cwd +0 -1
  149. package/tmpclaude-436f-cwd +0 -1
  150. package/tmpclaude-4783-cwd +0 -1
  151. package/tmpclaude-4b6d-cwd +0 -1
  152. package/tmpclaude-4ba4-cwd +0 -1
  153. package/tmpclaude-51e6-cwd +0 -1
  154. package/tmpclaude-5ecf-cwd +0 -1
  155. package/tmpclaude-6f97-cwd +0 -1
  156. package/tmpclaude-7fb2-cwd +0 -1
  157. package/tmpclaude-825c-cwd +0 -1
  158. package/tmpclaude-8baf-cwd +0 -1
  159. package/tmpclaude-8d9f-cwd +0 -1
  160. package/tmpclaude-975c-cwd +0 -1
  161. package/tmpclaude-9983-cwd +0 -1
  162. package/tmpclaude-a045-cwd +0 -1
  163. package/tmpclaude-ac4a-cwd +0 -1
  164. package/tmpclaude-b593-cwd +0 -1
  165. package/tmpclaude-b891-cwd +0 -1
  166. package/tmpclaude-c032-cwd +0 -1
  167. package/tmpclaude-cf43-cwd +0 -1
  168. package/tmpclaude-d040-cwd +0 -1
  169. package/tmpclaude-dcdd-cwd +0 -1
  170. package/tmpclaude-dcee-cwd +0 -1
  171. package/tmpclaude-e16b-cwd +0 -1
  172. package/tmpclaude-ecd2-cwd +0 -1
  173. 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;