@vibescope/mcp-server 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -7
- package/dist/api-client.d.ts +251 -1
- package/dist/api-client.js +82 -3
- package/dist/handlers/blockers.js +9 -8
- package/dist/handlers/bodies-of-work.js +96 -63
- package/dist/handlers/connectors.d.ts +45 -0
- package/dist/handlers/connectors.js +183 -0
- package/dist/handlers/cost.d.ts +10 -0
- package/dist/handlers/cost.js +112 -50
- package/dist/handlers/decisions.js +32 -19
- package/dist/handlers/deployment.js +144 -122
- package/dist/handlers/discovery.d.ts +7 -0
- package/dist/handlers/discovery.js +96 -7
- package/dist/handlers/fallback.js +29 -23
- package/dist/handlers/file-checkouts.d.ts +20 -0
- package/dist/handlers/file-checkouts.js +133 -0
- package/dist/handlers/findings.d.ts +6 -0
- package/dist/handlers/findings.js +96 -40
- package/dist/handlers/git-issues.js +40 -36
- package/dist/handlers/ideas.js +49 -31
- package/dist/handlers/index.d.ts +3 -0
- package/dist/handlers/index.js +9 -0
- package/dist/handlers/milestones.js +39 -32
- package/dist/handlers/organizations.js +99 -91
- package/dist/handlers/progress.js +24 -13
- package/dist/handlers/project.js +68 -28
- package/dist/handlers/requests.js +18 -14
- package/dist/handlers/roles.d.ts +18 -0
- package/dist/handlers/roles.js +130 -0
- package/dist/handlers/session.js +58 -17
- package/dist/handlers/sprints.js +93 -81
- package/dist/handlers/tasks.d.ts +2 -0
- package/dist/handlers/tasks.js +189 -91
- package/dist/handlers/types.d.ts +64 -2
- package/dist/handlers/types.js +48 -1
- package/dist/handlers/validation.js +21 -17
- package/dist/index.js +7 -2716
- package/dist/token-tracking.d.ts +74 -0
- package/dist/token-tracking.js +122 -0
- package/dist/tools.js +685 -9
- package/dist/utils.d.ts +5 -0
- package/dist/utils.js +17 -0
- package/docs/TOOLS.md +2053 -0
- package/package.json +4 -1
- package/scripts/generate-docs.ts +212 -0
- package/src/api-client.test.ts +718 -0
- package/src/api-client.ts +320 -6
- package/src/handlers/__test-setup__.ts +16 -0
- package/src/handlers/blockers.test.ts +31 -19
- package/src/handlers/blockers.ts +9 -8
- package/src/handlers/bodies-of-work.test.ts +55 -32
- package/src/handlers/bodies-of-work.ts +115 -115
- package/src/handlers/connectors.test.ts +834 -0
- package/src/handlers/connectors.ts +229 -0
- package/src/handlers/cost.test.ts +34 -44
- package/src/handlers/cost.ts +136 -85
- package/src/handlers/decisions.test.ts +37 -27
- package/src/handlers/decisions.ts +35 -30
- package/src/handlers/deployment.ts +180 -208
- package/src/handlers/discovery.test.ts +4 -5
- package/src/handlers/discovery.ts +98 -8
- package/src/handlers/fallback.test.ts +26 -22
- package/src/handlers/fallback.ts +36 -33
- package/src/handlers/file-checkouts.test.ts +670 -0
- package/src/handlers/file-checkouts.ts +165 -0
- package/src/handlers/findings.test.ts +178 -19
- package/src/handlers/findings.ts +112 -74
- package/src/handlers/git-issues.test.ts +51 -43
- package/src/handlers/git-issues.ts +44 -84
- package/src/handlers/ideas.test.ts +28 -23
- package/src/handlers/ideas.ts +61 -59
- package/src/handlers/index.ts +9 -0
- package/src/handlers/milestones.test.ts +33 -28
- package/src/handlers/milestones.ts +52 -50
- package/src/handlers/organizations.test.ts +104 -83
- package/src/handlers/organizations.ts +117 -142
- package/src/handlers/progress.test.ts +20 -14
- package/src/handlers/progress.ts +26 -24
- package/src/handlers/project.test.ts +34 -27
- package/src/handlers/project.ts +95 -63
- package/src/handlers/requests.test.ts +27 -18
- package/src/handlers/requests.ts +21 -17
- package/src/handlers/roles.test.ts +303 -0
- package/src/handlers/roles.ts +208 -0
- package/src/handlers/session.test.ts +47 -0
- package/src/handlers/session.ts +71 -26
- package/src/handlers/sprints.test.ts +71 -50
- package/src/handlers/sprints.ts +113 -146
- package/src/handlers/tasks.test.ts +77 -15
- package/src/handlers/tasks.ts +231 -156
- package/src/handlers/tool-categories.test.ts +66 -0
- package/src/handlers/types.ts +81 -2
- package/src/handlers/validation.test.ts +78 -45
- package/src/handlers/validation.ts +23 -25
- package/src/index.ts +12 -2732
- package/src/token-tracking.test.ts +453 -0
- package/src/token-tracking.ts +164 -0
- package/src/tools.ts +685 -9
- package/src/utils.test.ts +2 -2
- package/src/utils.ts +17 -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
package/src/handlers/types.ts
CHANGED
|
@@ -74,14 +74,93 @@ export interface HandlerContext {
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
/**
|
|
77
|
-
*
|
|
77
|
+
* Success result with typed data
|
|
78
78
|
*/
|
|
79
|
-
export interface
|
|
79
|
+
export interface SuccessResult<T = unknown> {
|
|
80
|
+
result: T;
|
|
81
|
+
content?: Array<{ type: string; text: string }>;
|
|
82
|
+
isError?: false;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Error result with error information
|
|
87
|
+
*/
|
|
88
|
+
export interface ErrorResult {
|
|
89
|
+
result: { error: string; [key: string]: unknown };
|
|
90
|
+
content?: Array<{ type: string; text: string }>;
|
|
91
|
+
isError: true;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Result returned by handlers - discriminated union for type safety
|
|
96
|
+
* Use the helper functions success() and error() to create properly typed results.
|
|
97
|
+
*/
|
|
98
|
+
export type HandlerResult<T = unknown> = SuccessResult<T> | ErrorResult;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Legacy HandlerResult interface for backward compatibility
|
|
102
|
+
* @deprecated Use HandlerResult<T> discriminated union instead
|
|
103
|
+
*/
|
|
104
|
+
export interface LegacyHandlerResult {
|
|
80
105
|
result?: unknown;
|
|
81
106
|
content?: Array<{ type: string; text: string }>;
|
|
82
107
|
isError?: boolean;
|
|
83
108
|
}
|
|
84
109
|
|
|
110
|
+
// ============================================================================
|
|
111
|
+
// Result Factory Functions - use these for type-safe handler results
|
|
112
|
+
// ============================================================================
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Create a success result with typed data
|
|
116
|
+
* @example
|
|
117
|
+
* return success({ tasks: data, total_count: count });
|
|
118
|
+
*/
|
|
119
|
+
export function success<T>(data: T): SuccessResult<T> {
|
|
120
|
+
return { result: data };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Create an error result
|
|
125
|
+
* @example
|
|
126
|
+
* return error('Task not found');
|
|
127
|
+
* return error('Validation failed', { field: 'title', reason: 'too long' });
|
|
128
|
+
*/
|
|
129
|
+
export function error(message: string, details?: Record<string, unknown>): ErrorResult {
|
|
130
|
+
return {
|
|
131
|
+
result: { error: message, ...details },
|
|
132
|
+
isError: true
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// ============================================================================
|
|
137
|
+
// Type Predicates - use for runtime type narrowing
|
|
138
|
+
// ============================================================================
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Check if a handler result is a success (not an error)
|
|
142
|
+
* @example
|
|
143
|
+
* const result = await handler(args, ctx);
|
|
144
|
+
* if (isSuccess(result)) {
|
|
145
|
+
* console.log(result.result); // typed as T
|
|
146
|
+
* }
|
|
147
|
+
*/
|
|
148
|
+
export function isSuccess<T>(result: HandlerResult<T>): result is SuccessResult<T> {
|
|
149
|
+
return !result.isError;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Check if a handler result is an error
|
|
154
|
+
* @example
|
|
155
|
+
* const result = await handler(args, ctx);
|
|
156
|
+
* if (isError(result)) {
|
|
157
|
+
* console.log(result.result.error); // string
|
|
158
|
+
* }
|
|
159
|
+
*/
|
|
160
|
+
export function isError(result: HandlerResult<unknown>): result is ErrorResult {
|
|
161
|
+
return result.isError === true;
|
|
162
|
+
}
|
|
163
|
+
|
|
85
164
|
/**
|
|
86
165
|
* Handler function type
|
|
87
166
|
*/
|
|
@@ -116,16 +116,19 @@ describe('getTasksAwaitingValidation', () => {
|
|
|
116
116
|
expect(mockApiClient.getTasksAwaitingValidation).toHaveBeenCalledWith(VALID_UUID);
|
|
117
117
|
});
|
|
118
118
|
|
|
119
|
-
it('should
|
|
119
|
+
it('should return error when API call fails', async () => {
|
|
120
120
|
mockApiClient.getTasksAwaitingValidation.mockResolvedValue({
|
|
121
121
|
ok: false,
|
|
122
122
|
error: 'Failed to fetch tasks awaiting validation',
|
|
123
123
|
});
|
|
124
124
|
const ctx = createMockContext();
|
|
125
125
|
|
|
126
|
-
await
|
|
127
|
-
|
|
128
|
-
).
|
|
126
|
+
const result = await getTasksAwaitingValidation({ project_id: VALID_UUID }, ctx);
|
|
127
|
+
|
|
128
|
+
expect(result.isError).toBe(true);
|
|
129
|
+
expect(result.result).toMatchObject({
|
|
130
|
+
error: 'Failed to fetch tasks awaiting validation',
|
|
131
|
+
});
|
|
129
132
|
});
|
|
130
133
|
});
|
|
131
134
|
|
|
@@ -150,52 +153,64 @@ describe('claimValidation', () => {
|
|
|
150
153
|
).rejects.toThrow(ValidationError);
|
|
151
154
|
});
|
|
152
155
|
|
|
153
|
-
it('should
|
|
156
|
+
it('should return error when task not found', async () => {
|
|
154
157
|
mockApiClient.claimValidation.mockResolvedValue({
|
|
155
158
|
ok: false,
|
|
156
159
|
error: 'Task not found',
|
|
157
160
|
});
|
|
158
161
|
const ctx = createMockContext();
|
|
159
162
|
|
|
160
|
-
await
|
|
161
|
-
|
|
162
|
-
).
|
|
163
|
+
const result = await claimValidation({ task_id: VALID_UUID }, ctx);
|
|
164
|
+
|
|
165
|
+
expect(result.isError).toBe(true);
|
|
166
|
+
expect(result.result).toMatchObject({
|
|
167
|
+
error: 'Task not found',
|
|
168
|
+
});
|
|
163
169
|
});
|
|
164
170
|
|
|
165
|
-
it('should
|
|
171
|
+
it('should return error when task is not completed', async () => {
|
|
166
172
|
mockApiClient.claimValidation.mockResolvedValue({
|
|
167
173
|
ok: false,
|
|
168
174
|
error: 'Can only claim completed tasks for review',
|
|
169
175
|
});
|
|
170
176
|
const ctx = createMockContext();
|
|
171
177
|
|
|
172
|
-
await
|
|
173
|
-
|
|
174
|
-
).
|
|
178
|
+
const result = await claimValidation({ task_id: VALID_UUID }, ctx);
|
|
179
|
+
|
|
180
|
+
expect(result.isError).toBe(true);
|
|
181
|
+
expect(result.result).toMatchObject({
|
|
182
|
+
error: 'Can only claim completed tasks for review',
|
|
183
|
+
});
|
|
175
184
|
});
|
|
176
185
|
|
|
177
|
-
it('should
|
|
186
|
+
it('should return error when task is already validated', async () => {
|
|
178
187
|
mockApiClient.claimValidation.mockResolvedValue({
|
|
179
188
|
ok: false,
|
|
180
189
|
error: 'Task has already been validated',
|
|
181
190
|
});
|
|
182
191
|
const ctx = createMockContext();
|
|
183
192
|
|
|
184
|
-
await
|
|
185
|
-
|
|
186
|
-
).
|
|
193
|
+
const result = await claimValidation({ task_id: VALID_UUID }, ctx);
|
|
194
|
+
|
|
195
|
+
expect(result.isError).toBe(true);
|
|
196
|
+
expect(result.result).toMatchObject({
|
|
197
|
+
error: 'Task has already been validated',
|
|
198
|
+
});
|
|
187
199
|
});
|
|
188
200
|
|
|
189
|
-
it('should
|
|
201
|
+
it('should return error when task is being reviewed by another agent', async () => {
|
|
190
202
|
mockApiClient.claimValidation.mockResolvedValue({
|
|
191
203
|
ok: false,
|
|
192
204
|
error: 'Task is already being reviewed by another agent',
|
|
193
205
|
});
|
|
194
206
|
const ctx = createMockContext({ sessionId: 'session-123' });
|
|
195
207
|
|
|
196
|
-
await
|
|
197
|
-
|
|
198
|
-
).
|
|
208
|
+
const result = await claimValidation({ task_id: VALID_UUID }, ctx);
|
|
209
|
+
|
|
210
|
+
expect(result.isError).toBe(true);
|
|
211
|
+
expect(result.result).toMatchObject({
|
|
212
|
+
error: 'Task is already being reviewed by another agent',
|
|
213
|
+
});
|
|
199
214
|
});
|
|
200
215
|
|
|
201
216
|
it('should allow same agent to re-claim their own review', async () => {
|
|
@@ -268,16 +283,19 @@ describe('claimValidation', () => {
|
|
|
268
283
|
);
|
|
269
284
|
});
|
|
270
285
|
|
|
271
|
-
it('should
|
|
286
|
+
it('should return error when claim fails', async () => {
|
|
272
287
|
mockApiClient.claimValidation.mockResolvedValue({
|
|
273
288
|
ok: false,
|
|
274
289
|
error: 'Failed to claim task for validation',
|
|
275
290
|
});
|
|
276
291
|
const ctx = createMockContext();
|
|
277
292
|
|
|
278
|
-
await
|
|
279
|
-
|
|
280
|
-
).
|
|
293
|
+
const result = await claimValidation({ task_id: VALID_UUID }, ctx);
|
|
294
|
+
|
|
295
|
+
expect(result.isError).toBe(true);
|
|
296
|
+
expect(result.result).toMatchObject({
|
|
297
|
+
error: 'Failed to claim task for validation',
|
|
298
|
+
});
|
|
281
299
|
});
|
|
282
300
|
});
|
|
283
301
|
|
|
@@ -309,43 +327,52 @@ describe('validateTask', () => {
|
|
|
309
327
|
|
|
310
328
|
await expect(
|
|
311
329
|
validateTask({ task_id: VALID_UUID }, ctx)
|
|
312
|
-
).rejects.toThrow(
|
|
330
|
+
).rejects.toThrow(ValidationError);
|
|
313
331
|
});
|
|
314
332
|
|
|
315
|
-
it('should
|
|
333
|
+
it('should return error when task not found', async () => {
|
|
316
334
|
mockApiClient.validateTask.mockResolvedValue({
|
|
317
335
|
ok: false,
|
|
318
336
|
error: 'Task not found',
|
|
319
337
|
});
|
|
320
338
|
const ctx = createMockContext();
|
|
321
339
|
|
|
322
|
-
await
|
|
323
|
-
|
|
324
|
-
).
|
|
340
|
+
const result = await validateTask({ task_id: VALID_UUID, approved: true }, ctx);
|
|
341
|
+
|
|
342
|
+
expect(result.isError).toBe(true);
|
|
343
|
+
expect(result.result).toMatchObject({
|
|
344
|
+
error: 'Task not found',
|
|
345
|
+
});
|
|
325
346
|
});
|
|
326
347
|
|
|
327
|
-
it('should
|
|
348
|
+
it('should return error when task is not completed', async () => {
|
|
328
349
|
mockApiClient.validateTask.mockResolvedValue({
|
|
329
350
|
ok: false,
|
|
330
351
|
error: 'Can only validate completed tasks',
|
|
331
352
|
});
|
|
332
353
|
const ctx = createMockContext();
|
|
333
354
|
|
|
334
|
-
await
|
|
335
|
-
|
|
336
|
-
).
|
|
355
|
+
const result = await validateTask({ task_id: VALID_UUID, approved: true }, ctx);
|
|
356
|
+
|
|
357
|
+
expect(result.isError).toBe(true);
|
|
358
|
+
expect(result.result).toMatchObject({
|
|
359
|
+
error: 'Can only validate completed tasks',
|
|
360
|
+
});
|
|
337
361
|
});
|
|
338
362
|
|
|
339
|
-
it('should
|
|
363
|
+
it('should return error when task already validated', async () => {
|
|
340
364
|
mockApiClient.validateTask.mockResolvedValue({
|
|
341
365
|
ok: false,
|
|
342
366
|
error: 'Task has already been validated',
|
|
343
367
|
});
|
|
344
368
|
const ctx = createMockContext();
|
|
345
369
|
|
|
346
|
-
await
|
|
347
|
-
|
|
348
|
-
).
|
|
370
|
+
const result = await validateTask({ task_id: VALID_UUID, approved: true }, ctx);
|
|
371
|
+
|
|
372
|
+
expect(result.isError).toBe(true);
|
|
373
|
+
expect(result.result).toMatchObject({
|
|
374
|
+
error: 'Task has already been validated',
|
|
375
|
+
});
|
|
349
376
|
});
|
|
350
377
|
|
|
351
378
|
describe('when approved', () => {
|
|
@@ -471,28 +498,34 @@ describe('validateTask', () => {
|
|
|
471
498
|
});
|
|
472
499
|
});
|
|
473
500
|
|
|
474
|
-
it('should
|
|
501
|
+
it('should return error when validation fails on approval', async () => {
|
|
475
502
|
mockApiClient.validateTask.mockResolvedValue({
|
|
476
503
|
ok: false,
|
|
477
504
|
error: 'Failed to validate task',
|
|
478
505
|
});
|
|
479
506
|
const ctx = createMockContext();
|
|
480
507
|
|
|
481
|
-
await
|
|
482
|
-
|
|
483
|
-
).
|
|
508
|
+
const result = await validateTask({ task_id: VALID_UUID, approved: true }, ctx);
|
|
509
|
+
|
|
510
|
+
expect(result.isError).toBe(true);
|
|
511
|
+
expect(result.result).toMatchObject({
|
|
512
|
+
error: 'Failed to validate task',
|
|
513
|
+
});
|
|
484
514
|
});
|
|
485
515
|
|
|
486
|
-
it('should
|
|
516
|
+
it('should return error when validation fails on rejection', async () => {
|
|
487
517
|
mockApiClient.validateTask.mockResolvedValue({
|
|
488
518
|
ok: false,
|
|
489
519
|
error: 'Failed to validate task',
|
|
490
520
|
});
|
|
491
521
|
const ctx = createMockContext();
|
|
492
522
|
|
|
493
|
-
await
|
|
494
|
-
|
|
495
|
-
).
|
|
523
|
+
const result = await validateTask({ task_id: VALID_UUID, approved: false }, ctx);
|
|
524
|
+
|
|
525
|
+
expect(result.isError).toBe(true);
|
|
526
|
+
expect(result.result).toMatchObject({
|
|
527
|
+
error: 'Failed to validate task',
|
|
528
|
+
});
|
|
496
529
|
});
|
|
497
530
|
|
|
498
531
|
describe('PR requirement', () => {
|
|
@@ -8,30 +8,40 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import type { Handler, HandlerRegistry } from './types.js';
|
|
11
|
-
import {
|
|
11
|
+
import { parseArgs, uuidValidator } from '../validators.js';
|
|
12
12
|
import { getApiClient } from '../api-client.js';
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
// Argument schemas for type-safe parsing
|
|
15
|
+
const getTasksAwaitingValidationSchema = {
|
|
16
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const claimValidationSchema = {
|
|
20
|
+
task_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
21
|
+
};
|
|
16
22
|
|
|
17
|
-
|
|
18
|
-
|
|
23
|
+
const validateTaskSchema = {
|
|
24
|
+
task_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
25
|
+
approved: { type: 'boolean' as const, required: true as const },
|
|
26
|
+
validation_notes: { type: 'string' as const },
|
|
27
|
+
skip_pr_check: { type: 'boolean' as const },
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const getTasksAwaitingValidation: Handler = async (args, _ctx) => {
|
|
31
|
+
const { project_id } = parseArgs(args, getTasksAwaitingValidationSchema);
|
|
19
32
|
|
|
20
33
|
const apiClient = getApiClient();
|
|
21
34
|
const response = await apiClient.getTasksAwaitingValidation(project_id);
|
|
22
35
|
|
|
23
36
|
if (!response.ok) {
|
|
24
|
-
|
|
37
|
+
return { result: { error: response.error || 'Failed to fetch tasks awaiting validation' }, isError: true };
|
|
25
38
|
}
|
|
26
39
|
|
|
27
40
|
return { result: response.data };
|
|
28
41
|
};
|
|
29
42
|
|
|
30
43
|
export const claimValidation: Handler = async (args, ctx) => {
|
|
31
|
-
const { task_id } = args
|
|
32
|
-
|
|
33
|
-
validateRequired(task_id, 'task_id');
|
|
34
|
-
validateUUID(task_id, 'task_id');
|
|
44
|
+
const { task_id } = parseArgs(args, claimValidationSchema);
|
|
35
45
|
|
|
36
46
|
const { session } = ctx;
|
|
37
47
|
const currentSessionId = session.currentSessionId;
|
|
@@ -40,26 +50,14 @@ export const claimValidation: Handler = async (args, ctx) => {
|
|
|
40
50
|
const response = await apiClient.claimValidation(task_id, currentSessionId || undefined);
|
|
41
51
|
|
|
42
52
|
if (!response.ok) {
|
|
43
|
-
|
|
53
|
+
return { result: { error: response.error || 'Failed to claim task for validation' }, isError: true };
|
|
44
54
|
}
|
|
45
55
|
|
|
46
56
|
return { result: response.data };
|
|
47
57
|
};
|
|
48
58
|
|
|
49
59
|
export const validateTask: Handler = async (args, ctx) => {
|
|
50
|
-
const { task_id,
|
|
51
|
-
task_id: string;
|
|
52
|
-
validation_notes?: string;
|
|
53
|
-
approved: boolean;
|
|
54
|
-
skip_pr_check?: boolean;
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
validateRequired(task_id, 'task_id');
|
|
58
|
-
validateUUID(task_id, 'task_id');
|
|
59
|
-
|
|
60
|
-
if (approved === undefined) {
|
|
61
|
-
throw new Error('approved is required');
|
|
62
|
-
}
|
|
60
|
+
const { task_id, approved, validation_notes, skip_pr_check } = parseArgs(args, validateTaskSchema);
|
|
63
61
|
|
|
64
62
|
const { session } = ctx;
|
|
65
63
|
const currentSessionId = session.currentSessionId;
|
|
@@ -83,7 +81,7 @@ export const validateTask: Handler = async (args, ctx) => {
|
|
|
83
81
|
},
|
|
84
82
|
};
|
|
85
83
|
}
|
|
86
|
-
|
|
84
|
+
return { result: { error: response.error || 'Failed to validate task' }, isError: true };
|
|
87
85
|
}
|
|
88
86
|
|
|
89
87
|
return { result: response.data };
|