@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
@@ -11,7 +11,10 @@ import {
11
11
  deleteCostAlert,
12
12
  getTaskCosts,
13
13
  } from './cost.js';
14
- import { createMockSupabase, createMockContext, testUUID } from './__test-utils__.js';
14
+ import { createMockContext } from './__test-utils__.js';
15
+ import { mockApiClient } from './__test-setup__.js';
16
+
17
+ const VALID_UUID = '123e4567-e89b-12d3-a456-426614174000';
15
18
 
16
19
  describe('Cost Handlers', () => {
17
20
  beforeEach(() => {
@@ -24,8 +27,7 @@ describe('Cost Handlers', () => {
24
27
 
25
28
  describe('getCostSummary', () => {
26
29
  it('should return error when project_id is missing', async () => {
27
- const supabase = createMockSupabase();
28
- const ctx = createMockContext(supabase);
30
+ const ctx = createMockContext();
29
31
 
30
32
  const result = await getCostSummary({}, ctx);
31
33
 
@@ -50,13 +52,22 @@ describe('Cost Handlers', () => {
50
52
  estimated_cost_usd: '0.30',
51
53
  },
52
54
  ];
53
-
54
- const supabase = createMockSupabase({
55
- selectResult: { data: mockData, error: null },
55
+ mockApiClient.getCostSummary.mockResolvedValue({
56
+ ok: true,
57
+ data: {
58
+ period: 'daily',
59
+ summary: mockData,
60
+ totals: {
61
+ sessions: 8,
62
+ tokens: 16000,
63
+ calls: 80,
64
+ cost: 0.8,
65
+ },
66
+ },
56
67
  });
57
- const ctx = createMockContext(supabase);
68
+ const ctx = createMockContext();
58
69
 
59
- const result = await getCostSummary({ project_id: testUUID() }, ctx);
70
+ const result = await getCostSummary({ project_id: VALID_UUID }, ctx);
60
71
 
61
72
  expect(result.isError).toBeUndefined();
62
73
  expect(result.result.period).toBe('daily');
@@ -70,45 +81,54 @@ describe('Cost Handlers', () => {
70
81
  });
71
82
 
72
83
  it('should handle weekly period', async () => {
73
- const supabase = createMockSupabase({
74
- selectResult: { data: [], error: null },
84
+ mockApiClient.getCostSummary.mockResolvedValue({
85
+ ok: true,
86
+ data: { period: 'weekly', summary: [], totals: { sessions: 0, tokens: 0, calls: 0, cost: 0 } },
75
87
  });
76
- const ctx = createMockContext(supabase);
88
+ const ctx = createMockContext();
77
89
 
78
90
  const result = await getCostSummary(
79
- { project_id: testUUID(), period: 'weekly' },
91
+ { project_id: VALID_UUID, period: 'weekly' },
80
92
  ctx
81
93
  );
82
94
 
83
95
  expect(result.result.period).toBe('weekly');
84
- expect(supabase.from).toHaveBeenCalledWith('weekly_cost_summary');
96
+ expect(mockApiClient.getCostSummary).toHaveBeenCalledWith(
97
+ VALID_UUID,
98
+ expect.objectContaining({ period: 'weekly' })
99
+ );
85
100
  });
86
101
 
87
102
  it('should handle monthly period', async () => {
88
- const supabase = createMockSupabase({
89
- selectResult: { data: [], error: null },
103
+ mockApiClient.getCostSummary.mockResolvedValue({
104
+ ok: true,
105
+ data: { period: 'monthly', summary: [], totals: { sessions: 0, tokens: 0, calls: 0, cost: 0 } },
90
106
  });
91
- const ctx = createMockContext(supabase);
107
+ const ctx = createMockContext();
92
108
 
93
109
  const result = await getCostSummary(
94
- { project_id: testUUID(), period: 'monthly' },
110
+ { project_id: VALID_UUID, period: 'monthly' },
95
111
  ctx
96
112
  );
97
113
 
98
114
  expect(result.result.period).toBe('monthly');
99
- expect(supabase.from).toHaveBeenCalledWith('monthly_cost_summary');
115
+ expect(mockApiClient.getCostSummary).toHaveBeenCalledWith(
116
+ VALID_UUID,
117
+ expect.objectContaining({ period: 'monthly' })
118
+ );
100
119
  });
101
120
 
102
- it('should return error on database failure', async () => {
103
- const supabase = createMockSupabase({
104
- selectResult: { data: null, error: { message: 'Database error' } },
121
+ it('should return error on API failure', async () => {
122
+ mockApiClient.getCostSummary.mockResolvedValue({
123
+ ok: false,
124
+ error: 'Database error',
105
125
  });
106
- const ctx = createMockContext(supabase);
126
+ const ctx = createMockContext();
107
127
 
108
- const result = await getCostSummary({ project_id: testUUID() }, ctx);
128
+ const result = await getCostSummary({ project_id: VALID_UUID }, ctx);
109
129
 
110
130
  expect(result.isError).toBe(true);
111
- expect(result.result.error).toContain('Failed to get cost summary');
131
+ expect(result.result.error).toBe('Database error');
112
132
  });
113
133
  });
114
134
 
@@ -122,11 +142,11 @@ describe('Cost Handlers', () => {
122
142
  { id: 'alert-1', threshold_amount: 10, threshold_period: 'daily' },
123
143
  { id: 'alert-2', threshold_amount: 50, threshold_period: 'weekly' },
124
144
  ];
125
-
126
- const supabase = createMockSupabase({
127
- selectResult: { data: mockAlerts, error: null },
145
+ mockApiClient.getCostAlerts.mockResolvedValue({
146
+ ok: true,
147
+ data: { alerts: mockAlerts, count: 2 },
128
148
  });
129
- const ctx = createMockContext(supabase);
149
+ const ctx = createMockContext();
130
150
 
131
151
  const result = await getCostAlerts({}, ctx);
132
152
 
@@ -134,27 +154,29 @@ describe('Cost Handlers', () => {
134
154
  expect(result.result.count).toBe(2);
135
155
  });
136
156
 
137
- it('should filter by project_id when provided', async () => {
138
- const supabase = createMockSupabase({
139
- selectResult: { data: [], error: null },
157
+ it('should call getCostAlerts with no args (project filtering done server-side)', async () => {
158
+ mockApiClient.getCostAlerts.mockResolvedValue({
159
+ ok: true,
160
+ data: { alerts: [], count: 0 },
140
161
  });
141
- const ctx = createMockContext(supabase);
162
+ const ctx = createMockContext();
142
163
 
143
- await getCostAlerts({ project_id: testUUID() }, ctx);
164
+ await getCostAlerts({ project_id: VALID_UUID }, ctx);
144
165
 
145
- expect(supabase.eq).toHaveBeenCalledWith('project_id', testUUID());
166
+ expect(mockApiClient.getCostAlerts).toHaveBeenCalledWith();
146
167
  });
147
168
 
148
- it('should return error on database failure', async () => {
149
- const supabase = createMockSupabase({
150
- selectResult: { data: null, error: { message: 'Query failed' } },
169
+ it('should return error on API failure', async () => {
170
+ mockApiClient.getCostAlerts.mockResolvedValue({
171
+ ok: false,
172
+ error: 'Query failed',
151
173
  });
152
- const ctx = createMockContext(supabase);
174
+ const ctx = createMockContext();
153
175
 
154
176
  const result = await getCostAlerts({}, ctx);
155
177
 
156
178
  expect(result.isError).toBe(true);
157
- expect(result.result.error).toContain('Failed to get cost alerts');
179
+ expect(result.result.error).toBe('Query failed');
158
180
  });
159
181
  });
160
182
 
@@ -164,8 +186,7 @@ describe('Cost Handlers', () => {
164
186
 
165
187
  describe('addCostAlert', () => {
166
188
  it('should return error when threshold_amount is missing', async () => {
167
- const supabase = createMockSupabase();
168
- const ctx = createMockContext(supabase);
189
+ const ctx = createMockContext();
169
190
 
170
191
  const result = await addCostAlert(
171
192
  { threshold_period: 'daily' },
@@ -177,8 +198,7 @@ describe('Cost Handlers', () => {
177
198
  });
178
199
 
179
200
  it('should return error when threshold_amount is not positive', async () => {
180
- const supabase = createMockSupabase();
181
- const ctx = createMockContext(supabase);
201
+ const ctx = createMockContext();
182
202
 
183
203
  const result = await addCostAlert(
184
204
  { threshold_amount: -5, threshold_period: 'daily' },
@@ -190,8 +210,7 @@ describe('Cost Handlers', () => {
190
210
  });
191
211
 
192
212
  it('should return error when threshold_period is invalid', async () => {
193
- const supabase = createMockSupabase();
194
- const ctx = createMockContext(supabase);
213
+ const ctx = createMockContext();
195
214
 
196
215
  const result = await addCostAlert(
197
216
  { threshold_amount: 10, threshold_period: 'yearly' },
@@ -209,11 +228,11 @@ describe('Cost Handlers', () => {
209
228
  threshold_period: 'daily',
210
229
  alert_type: 'warning',
211
230
  };
212
-
213
- const supabase = createMockSupabase({
214
- insertResult: { data: mockAlert, error: null },
231
+ mockApiClient.addCostAlert.mockResolvedValue({
232
+ ok: true,
233
+ data: { success: true, alert: mockAlert, message: 'Alert created' },
215
234
  });
216
- const ctx = createMockContext(supabase);
235
+ const ctx = createMockContext();
217
236
 
218
237
  const result = await addCostAlert(
219
238
  { threshold_amount: 10, threshold_period: 'daily' },
@@ -226,32 +245,36 @@ describe('Cost Handlers', () => {
226
245
  });
227
246
 
228
247
  it('should create alert with project_id', async () => {
229
- const supabase = createMockSupabase({
230
- insertResult: { data: { id: 'new-alert' }, error: null },
248
+ mockApiClient.addCostAlert.mockResolvedValue({
249
+ ok: true,
250
+ data: { success: true, alert: { id: 'new-alert' } },
231
251
  });
232
- const ctx = createMockContext(supabase);
252
+ const ctx = createMockContext();
233
253
 
234
254
  await addCostAlert(
235
255
  {
236
- project_id: testUUID(),
256
+ project_id: VALID_UUID,
237
257
  threshold_amount: 10,
238
258
  threshold_period: 'daily',
239
259
  },
240
260
  ctx
241
261
  );
242
262
 
243
- expect(supabase.insert).toHaveBeenCalledWith(
263
+ expect(mockApiClient.addCostAlert).toHaveBeenCalledWith(
244
264
  expect.objectContaining({
245
- project_id: testUUID(),
265
+ project_id: VALID_UUID,
266
+ threshold_amount: 10,
267
+ threshold_period: 'daily',
246
268
  })
247
269
  );
248
270
  });
249
271
 
250
- it('should return error on database failure', async () => {
251
- const supabase = createMockSupabase({
252
- insertResult: { data: null, error: { message: 'Insert failed' } },
272
+ it('should return error on API failure', async () => {
273
+ mockApiClient.addCostAlert.mockResolvedValue({
274
+ ok: false,
275
+ error: 'Insert failed',
253
276
  });
254
- const ctx = createMockContext(supabase);
277
+ const ctx = createMockContext();
255
278
 
256
279
  const result = await addCostAlert(
257
280
  { threshold_amount: 10, threshold_period: 'daily' },
@@ -259,7 +282,7 @@ describe('Cost Handlers', () => {
259
282
  );
260
283
 
261
284
  expect(result.isError).toBe(true);
262
- expect(result.result.error).toContain('Failed to create cost alert');
285
+ expect(result.result.error).toBe('Insert failed');
263
286
  });
264
287
  });
265
288
 
@@ -269,8 +292,7 @@ describe('Cost Handlers', () => {
269
292
 
270
293
  describe('updateCostAlert', () => {
271
294
  it('should return error when alert_id is missing', async () => {
272
- const supabase = createMockSupabase();
273
- const ctx = createMockContext(supabase);
295
+ const ctx = createMockContext();
274
296
 
275
297
  const result = await updateCostAlert({}, ctx);
276
298
 
@@ -279,10 +301,9 @@ describe('Cost Handlers', () => {
279
301
  });
280
302
 
281
303
  it('should return error when no updates provided', async () => {
282
- const supabase = createMockSupabase();
283
- const ctx = createMockContext(supabase);
304
+ const ctx = createMockContext();
284
305
 
285
- const result = await updateCostAlert({ alert_id: testUUID() }, ctx);
306
+ const result = await updateCostAlert({ alert_id: VALID_UUID }, ctx);
286
307
 
287
308
  expect(result.isError).toBe(true);
288
309
  expect(result.result.error).toBe('No updates provided');
@@ -290,18 +311,18 @@ describe('Cost Handlers', () => {
290
311
 
291
312
  it('should update alert successfully', async () => {
292
313
  const mockUpdatedAlert = {
293
- id: testUUID(),
314
+ id: VALID_UUID,
294
315
  threshold_amount: 20,
295
316
  threshold_period: 'weekly',
296
317
  };
297
-
298
- const supabase = createMockSupabase({
299
- updateResult: { data: mockUpdatedAlert, error: null },
318
+ mockApiClient.updateCostAlert.mockResolvedValue({
319
+ ok: true,
320
+ data: { success: true, alert: mockUpdatedAlert },
300
321
  });
301
- const ctx = createMockContext(supabase);
322
+ const ctx = createMockContext();
302
323
 
303
324
  const result = await updateCostAlert(
304
- { alert_id: testUUID(), threshold_amount: 20 },
325
+ { alert_id: VALID_UUID, threshold_amount: 20 },
305
326
  ctx
306
327
  );
307
328
 
@@ -310,29 +331,34 @@ describe('Cost Handlers', () => {
310
331
  });
311
332
 
312
333
  it('should update enabled status', async () => {
313
- const supabase = createMockSupabase({
314
- updateResult: { data: { id: testUUID(), enabled: false }, error: null },
334
+ mockApiClient.updateCostAlert.mockResolvedValue({
335
+ ok: true,
336
+ data: { success: true, alert: { id: VALID_UUID, enabled: false } },
315
337
  });
316
- const ctx = createMockContext(supabase);
338
+ const ctx = createMockContext();
317
339
 
318
- await updateCostAlert({ alert_id: testUUID(), enabled: false }, ctx);
340
+ await updateCostAlert({ alert_id: VALID_UUID, enabled: false }, ctx);
319
341
 
320
- expect(supabase.update).toHaveBeenCalledWith({ enabled: false });
342
+ expect(mockApiClient.updateCostAlert).toHaveBeenCalledWith(
343
+ VALID_UUID,
344
+ expect.objectContaining({ enabled: false })
345
+ );
321
346
  });
322
347
 
323
- it('should return error on database failure', async () => {
324
- const supabase = createMockSupabase({
325
- updateResult: { data: null, error: { message: 'Update failed' } },
348
+ it('should return error on API failure', async () => {
349
+ mockApiClient.updateCostAlert.mockResolvedValue({
350
+ ok: false,
351
+ error: 'Update failed',
326
352
  });
327
- const ctx = createMockContext(supabase);
353
+ const ctx = createMockContext();
328
354
 
329
355
  const result = await updateCostAlert(
330
- { alert_id: testUUID(), threshold_amount: 20 },
356
+ { alert_id: VALID_UUID, threshold_amount: 20 },
331
357
  ctx
332
358
  );
333
359
 
334
360
  expect(result.isError).toBe(true);
335
- expect(result.result.error).toContain('Failed to update cost alert');
361
+ expect(result.result.error).toBe('Update failed');
336
362
  });
337
363
  });
338
364
 
@@ -342,8 +368,7 @@ describe('Cost Handlers', () => {
342
368
 
343
369
  describe('deleteCostAlert', () => {
344
370
  it('should return error when alert_id is missing', async () => {
345
- const supabase = createMockSupabase();
346
- const ctx = createMockContext(supabase);
371
+ const ctx = createMockContext();
347
372
 
348
373
  const result = await deleteCostAlert({}, ctx);
349
374
 
@@ -352,27 +377,29 @@ describe('Cost Handlers', () => {
352
377
  });
353
378
 
354
379
  it('should delete alert successfully', async () => {
355
- const supabase = createMockSupabase({
356
- deleteResult: { data: null, error: null },
380
+ mockApiClient.deleteCostAlert.mockResolvedValue({
381
+ ok: true,
382
+ data: { success: true, deleted_alert_id: VALID_UUID },
357
383
  });
358
- const ctx = createMockContext(supabase);
384
+ const ctx = createMockContext();
359
385
 
360
- const result = await deleteCostAlert({ alert_id: testUUID() }, ctx);
386
+ const result = await deleteCostAlert({ alert_id: VALID_UUID }, ctx);
361
387
 
362
388
  expect(result.result.success).toBe(true);
363
- expect(result.result.deleted_alert_id).toBe(testUUID());
389
+ expect(result.result.deleted_alert_id).toBe(VALID_UUID);
364
390
  });
365
391
 
366
- it('should return error on database failure', async () => {
367
- const supabase = createMockSupabase({
368
- deleteResult: { data: null, error: { message: 'Delete failed' } },
392
+ it('should return error on API failure', async () => {
393
+ mockApiClient.deleteCostAlert.mockResolvedValue({
394
+ ok: false,
395
+ error: 'Delete failed',
369
396
  });
370
- const ctx = createMockContext(supabase);
397
+ const ctx = createMockContext();
371
398
 
372
- const result = await deleteCostAlert({ alert_id: testUUID() }, ctx);
399
+ const result = await deleteCostAlert({ alert_id: VALID_UUID }, ctx);
373
400
 
374
401
  expect(result.isError).toBe(true);
375
- expect(result.result.error).toContain('Failed to delete cost alert');
402
+ expect(result.result.error).toBe('Delete failed');
376
403
  });
377
404
  });
378
405
 
@@ -382,8 +409,7 @@ describe('Cost Handlers', () => {
382
409
 
383
410
  describe('getTaskCosts', () => {
384
411
  it('should return error when project_id is missing', async () => {
385
- const supabase = createMockSupabase();
386
- const ctx = createMockContext(supabase);
412
+ const ctx = createMockContext();
387
413
 
388
414
  const result = await getTaskCosts({}, ctx);
389
415
 
@@ -396,41 +422,51 @@ describe('Cost Handlers', () => {
396
422
  { id: 'task-1', title: 'Task 1', estimated_cost_usd: '0.50' },
397
423
  { id: 'task-2', title: 'Task 2', estimated_cost_usd: '0.30' },
398
424
  ];
399
-
400
- const supabase = createMockSupabase({
401
- selectResult: { data: mockTasks, error: null },
425
+ mockApiClient.getTaskCosts.mockResolvedValue({
426
+ ok: true,
427
+ data: {
428
+ project_id: VALID_UUID,
429
+ tasks: mockTasks,
430
+ total_cost_usd: 0.8,
431
+ },
402
432
  });
403
- const ctx = createMockContext(supabase);
433
+ const ctx = createMockContext();
404
434
 
405
- const result = await getTaskCosts({ project_id: testUUID() }, ctx);
435
+ const result = await getTaskCosts({ project_id: VALID_UUID }, ctx);
406
436
 
407
- expect(result.result.project_id).toBe(testUUID());
437
+ expect(result.result.project_id).toBe(VALID_UUID);
408
438
  expect(result.result.tasks).toEqual(mockTasks);
409
439
  expect(result.result.total_cost_usd).toBe(0.8);
410
440
  });
411
441
 
412
442
  it('should handle empty task list', async () => {
413
- const supabase = createMockSupabase({
414
- selectResult: { data: [], error: null },
443
+ mockApiClient.getTaskCosts.mockResolvedValue({
444
+ ok: true,
445
+ data: {
446
+ project_id: VALID_UUID,
447
+ tasks: [],
448
+ total_cost_usd: 0,
449
+ },
415
450
  });
416
- const ctx = createMockContext(supabase);
451
+ const ctx = createMockContext();
417
452
 
418
- const result = await getTaskCosts({ project_id: testUUID() }, ctx);
453
+ const result = await getTaskCosts({ project_id: VALID_UUID }, ctx);
419
454
 
420
455
  expect(result.result.tasks).toEqual([]);
421
456
  expect(result.result.total_cost_usd).toBe(0);
422
457
  });
423
458
 
424
- it('should return error on database failure', async () => {
425
- const supabase = createMockSupabase({
426
- selectResult: { data: null, error: { message: 'Query failed' } },
459
+ it('should return error on API failure', async () => {
460
+ mockApiClient.getTaskCosts.mockResolvedValue({
461
+ ok: false,
462
+ error: 'Query failed',
427
463
  });
428
- const ctx = createMockContext(supabase);
464
+ const ctx = createMockContext();
429
465
 
430
- const result = await getTaskCosts({ project_id: testUUID() }, ctx);
466
+ const result = await getTaskCosts({ project_id: VALID_UUID }, ctx);
431
467
 
432
468
  expect(result.isError).toBe(true);
433
- expect(result.result.error).toContain('Failed to get task costs');
469
+ expect(result.result.error).toBe('Query failed');
434
470
  });
435
471
  });
436
472
  });