@vibescope/mcp-server 0.4.5 → 0.4.6
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/CHANGELOG.md +84 -84
- package/README.md +194 -194
- package/dist/api-client/project.d.ts +1 -0
- package/dist/api-client.d.ts +1 -0
- package/dist/cli-init.js +21 -21
- package/dist/cli.js +26 -26
- package/dist/handlers/chat.d.ts +2 -0
- package/dist/handlers/chat.js +25 -0
- package/dist/handlers/discovery.js +12 -0
- package/dist/handlers/project.js +4 -2
- package/dist/handlers/tool-docs.js +1203 -1137
- package/dist/index.js +73 -73
- package/dist/templates/agent-guidelines.d.ts +1 -1
- package/dist/templates/agent-guidelines.js +205 -187
- package/dist/templates/help-content.js +1621 -1621
- package/dist/tools/bodies-of-work.js +6 -6
- package/dist/tools/chat.d.ts +1 -0
- package/dist/tools/chat.js +24 -0
- package/dist/tools/cloud-agents.js +22 -22
- package/dist/tools/features.d.ts +13 -0
- package/dist/tools/features.js +151 -0
- package/dist/tools/index.d.ts +3 -1
- package/dist/tools/index.js +4 -1
- package/dist/tools/milestones.js +2 -2
- package/dist/tools/project.js +4 -0
- package/dist/tools/requests.js +1 -1
- package/dist/tools/session.js +11 -11
- package/dist/tools/sprints.js +9 -9
- package/dist/tools/tasks.js +35 -35
- package/dist/tools/worktrees.js +14 -14
- package/dist/tools.d.ts +2 -0
- package/dist/tools.js +3602 -0
- package/dist/utils.js +11 -11
- package/docs/TOOLS.md +2663 -2559
- package/package.json +53 -53
- package/scripts/generate-docs.ts +212 -212
- package/scripts/version-bump.ts +203 -203
- package/src/api-client/blockers.ts +86 -86
- package/src/api-client/bodies-of-work.ts +194 -194
- package/src/api-client/chat.ts +50 -50
- package/src/api-client/connectors.ts +152 -152
- package/src/api-client/cost.ts +185 -185
- package/src/api-client/decisions.ts +87 -87
- package/src/api-client/deployment.ts +313 -313
- package/src/api-client/discovery.ts +81 -81
- package/src/api-client/fallback.ts +52 -52
- package/src/api-client/file-checkouts.ts +115 -115
- package/src/api-client/findings.ts +100 -100
- package/src/api-client/git-issues.ts +88 -88
- package/src/api-client/ideas.ts +112 -112
- package/src/api-client/index.ts +592 -592
- package/src/api-client/milestones.ts +83 -83
- package/src/api-client/organizations.ts +185 -185
- package/src/api-client/progress.ts +94 -94
- package/src/api-client/project.ts +180 -179
- package/src/api-client/requests.ts +54 -54
- package/src/api-client/session.ts +220 -220
- package/src/api-client/sprints.ts +227 -227
- package/src/api-client/subtasks.ts +57 -57
- package/src/api-client/tasks.ts +450 -450
- package/src/api-client/types.ts +32 -32
- package/src/api-client/validation.ts +60 -60
- package/src/api-client/worktrees.ts +53 -53
- package/src/api-client.test.ts +847 -847
- package/src/api-client.ts +2707 -2706
- package/src/cli-init.ts +557 -557
- package/src/cli.test.ts +284 -284
- package/src/cli.ts +204 -204
- package/src/handlers/__test-setup__.ts +240 -240
- package/src/handlers/__test-utils__.ts +89 -89
- package/src/handlers/blockers.test.ts +468 -468
- package/src/handlers/blockers.ts +172 -172
- package/src/handlers/bodies-of-work.test.ts +704 -704
- package/src/handlers/bodies-of-work.ts +526 -526
- package/src/handlers/chat.test.ts +185 -185
- package/src/handlers/chat.ts +101 -69
- package/src/handlers/cloud-agents.test.ts +438 -438
- package/src/handlers/cloud-agents.ts +156 -156
- package/src/handlers/connectors.test.ts +834 -834
- package/src/handlers/connectors.ts +229 -229
- package/src/handlers/cost.test.ts +462 -462
- package/src/handlers/cost.ts +285 -285
- package/src/handlers/decisions.test.ts +382 -382
- package/src/handlers/decisions.ts +153 -153
- package/src/handlers/deployment.test.ts +551 -551
- package/src/handlers/deployment.ts +570 -570
- package/src/handlers/discovery.test.ts +206 -206
- package/src/handlers/discovery.ts +427 -415
- package/src/handlers/fallback.test.ts +537 -537
- package/src/handlers/fallback.ts +194 -194
- package/src/handlers/file-checkouts.test.ts +750 -750
- package/src/handlers/file-checkouts.ts +185 -185
- package/src/handlers/findings.test.ts +633 -633
- package/src/handlers/findings.ts +239 -239
- package/src/handlers/git-issues.test.ts +631 -631
- package/src/handlers/git-issues.ts +136 -136
- package/src/handlers/ideas.test.ts +644 -644
- package/src/handlers/ideas.ts +207 -207
- package/src/handlers/index.ts +93 -93
- package/src/handlers/milestones.test.ts +475 -475
- package/src/handlers/milestones.ts +180 -180
- package/src/handlers/organizations.test.ts +826 -826
- package/src/handlers/organizations.ts +315 -315
- package/src/handlers/progress.test.ts +269 -269
- package/src/handlers/progress.ts +77 -77
- package/src/handlers/project.test.ts +546 -546
- package/src/handlers/project.ts +242 -239
- package/src/handlers/requests.test.ts +303 -303
- package/src/handlers/requests.ts +99 -99
- package/src/handlers/roles.test.ts +305 -305
- package/src/handlers/roles.ts +219 -219
- package/src/handlers/session.test.ts +998 -998
- package/src/handlers/session.ts +1105 -1105
- package/src/handlers/sprints.test.ts +732 -732
- package/src/handlers/sprints.ts +537 -537
- package/src/handlers/tasks.test.ts +931 -931
- package/src/handlers/tasks.ts +1133 -1133
- package/src/handlers/tool-categories.test.ts +66 -66
- package/src/handlers/tool-docs.test.ts +511 -511
- package/src/handlers/tool-docs.ts +1571 -1499
- package/src/handlers/types.test.ts +259 -259
- package/src/handlers/types.ts +176 -176
- package/src/handlers/validation.test.ts +582 -582
- package/src/handlers/validation.ts +164 -164
- package/src/handlers/version.ts +63 -63
- package/src/index.test.ts +674 -674
- package/src/index.ts +807 -807
- package/src/setup.test.ts +233 -233
- package/src/setup.ts +404 -404
- package/src/templates/agent-guidelines.ts +233 -215
- package/src/templates/help-content.ts +1751 -1751
- package/src/token-tracking.test.ts +463 -463
- package/src/token-tracking.ts +167 -167
- package/src/tools/blockers.ts +122 -122
- package/src/tools/bodies-of-work.ts +283 -283
- package/src/tools/chat.ts +72 -46
- package/src/tools/cloud-agents.ts +101 -101
- package/src/tools/connectors.ts +191 -191
- package/src/tools/cost.ts +111 -111
- package/src/tools/decisions.ts +111 -111
- package/src/tools/deployment.ts +455 -455
- package/src/tools/discovery.ts +76 -76
- package/src/tools/fallback.ts +111 -111
- package/src/tools/features.ts +154 -0
- package/src/tools/file-checkouts.ts +145 -145
- package/src/tools/findings.ts +101 -101
- package/src/tools/git-issues.ts +130 -130
- package/src/tools/ideas.ts +162 -162
- package/src/tools/index.ts +141 -137
- package/src/tools/milestones.ts +118 -118
- package/src/tools/organizations.ts +224 -224
- package/src/tools/progress.ts +73 -73
- package/src/tools/project.ts +206 -202
- package/src/tools/requests.ts +68 -68
- package/src/tools/roles.ts +112 -112
- package/src/tools/session.ts +181 -181
- package/src/tools/sprints.ts +298 -298
- package/src/tools/tasks.ts +550 -550
- package/src/tools/tools.test.ts +222 -222
- package/src/tools/types.ts +9 -9
- package/src/tools/validation.ts +75 -75
- package/src/tools/version.ts +34 -34
- package/src/tools/worktrees.ts +66 -66
- package/src/tools.test.ts +416 -416
- package/src/utils.test.ts +1014 -1014
- package/src/utils.ts +586 -586
- package/src/validators.test.ts +223 -223
- package/src/validators.ts +249 -249
- package/src/version.ts +109 -109
- package/tsconfig.json +16 -16
- package/vitest.config.ts +14 -14
package/src/handlers/blockers.ts
CHANGED
|
@@ -1,172 +1,172 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Blockers Handlers
|
|
3
|
-
*
|
|
4
|
-
* Handles blocker management:
|
|
5
|
-
* - add_blocker
|
|
6
|
-
* - resolve_blocker
|
|
7
|
-
* - get_blockers
|
|
8
|
-
* - delete_blocker
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import type { Handler, HandlerRegistry } from './types.js';
|
|
12
|
-
import { success, error } from './types.js';
|
|
13
|
-
import {
|
|
14
|
-
parseArgs,
|
|
15
|
-
uuidValidator,
|
|
16
|
-
createEnumValidator,
|
|
17
|
-
VALID_BLOCKER_STATUSES,
|
|
18
|
-
} from '../validators.js';
|
|
19
|
-
import { getApiClient } from '../api-client.js';
|
|
20
|
-
import { autoPostActivity } from './chat.js';
|
|
21
|
-
|
|
22
|
-
// Argument schemas for type-safe parsing
|
|
23
|
-
const addBlockerSchema = {
|
|
24
|
-
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
25
|
-
description: { type: 'string' as const, required: true as const },
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const resolveBlockerSchema = {
|
|
29
|
-
blocker_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
30
|
-
resolution_note: { type: 'string' as const },
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const getBlockerSchema = {
|
|
34
|
-
blocker_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const getBlockersSchema = {
|
|
38
|
-
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
39
|
-
status: { type: 'string' as const, default: 'open', validate: createEnumValidator(VALID_BLOCKER_STATUSES) },
|
|
40
|
-
limit: { type: 'number' as const, default: 10 },
|
|
41
|
-
offset: { type: 'number' as const, default: 0 },
|
|
42
|
-
search_query: { type: 'string' as const },
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const deleteBlockerSchema = {
|
|
46
|
-
blocker_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
const getBlockersStatsSchema = {
|
|
50
|
-
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
export const addBlocker: Handler = async (args, ctx) => {
|
|
54
|
-
const { project_id, description } = parseArgs(args, addBlockerSchema);
|
|
55
|
-
|
|
56
|
-
const apiClient = getApiClient();
|
|
57
|
-
const response = await apiClient.addBlocker(project_id, description, ctx.session.currentSessionId || undefined);
|
|
58
|
-
|
|
59
|
-
if (!response.ok) {
|
|
60
|
-
return error(response.error || 'Failed to add blocker');
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Auto-post blocker activity to project chat
|
|
64
|
-
const persona = ctx.session.currentPersona || 'Agent';
|
|
65
|
-
void autoPostActivity(
|
|
66
|
-
project_id,
|
|
67
|
-
`🚧 **${persona}** reported a blocker: ${description}`,
|
|
68
|
-
ctx.session.currentSessionId
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
return success(response.data);
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
export const resolveBlocker: Handler = async (args, _ctx) => {
|
|
75
|
-
const { blocker_id, resolution_note } = parseArgs(args, resolveBlockerSchema);
|
|
76
|
-
|
|
77
|
-
const apiClient = getApiClient();
|
|
78
|
-
const response = await apiClient.resolveBlocker(blocker_id, resolution_note);
|
|
79
|
-
|
|
80
|
-
if (!response.ok) {
|
|
81
|
-
return error(response.error || 'Failed to resolve blocker');
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return success(response.data);
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Get a single blocker by ID.
|
|
89
|
-
* More token-efficient than get_blockers when you need details for a specific blocker.
|
|
90
|
-
*/
|
|
91
|
-
export const getBlocker: Handler = async (args, _ctx) => {
|
|
92
|
-
const { blocker_id } = parseArgs(args, getBlockerSchema);
|
|
93
|
-
|
|
94
|
-
const apiClient = getApiClient();
|
|
95
|
-
const response = await apiClient.proxy<{
|
|
96
|
-
blocker: {
|
|
97
|
-
id: string;
|
|
98
|
-
description: string;
|
|
99
|
-
status: string;
|
|
100
|
-
resolution_note?: string;
|
|
101
|
-
created_at: string;
|
|
102
|
-
resolved_at?: string;
|
|
103
|
-
};
|
|
104
|
-
}>('get_blocker', { blocker_id });
|
|
105
|
-
|
|
106
|
-
if (!response.ok) {
|
|
107
|
-
return error(response.error || 'Failed to get blocker');
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return success(response.data);
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
export const getBlockers: Handler = async (args, _ctx) => {
|
|
114
|
-
const { project_id, status, limit, offset, search_query } = parseArgs(args, getBlockersSchema);
|
|
115
|
-
|
|
116
|
-
const apiClient = getApiClient();
|
|
117
|
-
const response = await apiClient.getBlockers(project_id, {
|
|
118
|
-
status,
|
|
119
|
-
limit: Math.min(limit ?? 10, 200),
|
|
120
|
-
offset,
|
|
121
|
-
search_query
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
if (!response.ok) {
|
|
125
|
-
return error(response.error || 'Failed to fetch blockers');
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return success(response.data);
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
export const deleteBlocker: Handler = async (args, _ctx) => {
|
|
132
|
-
const { blocker_id } = parseArgs(args, deleteBlockerSchema);
|
|
133
|
-
|
|
134
|
-
const apiClient = getApiClient();
|
|
135
|
-
const response = await apiClient.deleteBlocker(blocker_id);
|
|
136
|
-
|
|
137
|
-
if (!response.ok) {
|
|
138
|
-
return error(response.error || 'Failed to delete blocker');
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return success(response.data);
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Get aggregate statistics about blockers for a project.
|
|
146
|
-
* Returns total count and breakdown by status without the actual blocker data.
|
|
147
|
-
* This is much more token-efficient than get_blockers for understanding the overall state.
|
|
148
|
-
*/
|
|
149
|
-
export const getBlockersStats: Handler = async (args, _ctx) => {
|
|
150
|
-
const { project_id } = parseArgs(args, getBlockersStatsSchema);
|
|
151
|
-
|
|
152
|
-
const apiClient = getApiClient();
|
|
153
|
-
const response = await apiClient.getBlockersStats(project_id);
|
|
154
|
-
|
|
155
|
-
if (!response.ok) {
|
|
156
|
-
return error(response.error || 'Failed to get blockers stats');
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
return success(response.data);
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Blockers handlers registry
|
|
164
|
-
*/
|
|
165
|
-
export const blockerHandlers: HandlerRegistry = {
|
|
166
|
-
add_blocker: addBlocker,
|
|
167
|
-
resolve_blocker: resolveBlocker,
|
|
168
|
-
get_blocker: getBlocker,
|
|
169
|
-
get_blockers: getBlockers,
|
|
170
|
-
get_blockers_stats: getBlockersStats,
|
|
171
|
-
delete_blocker: deleteBlocker,
|
|
172
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* Blockers Handlers
|
|
3
|
+
*
|
|
4
|
+
* Handles blocker management:
|
|
5
|
+
* - add_blocker
|
|
6
|
+
* - resolve_blocker
|
|
7
|
+
* - get_blockers
|
|
8
|
+
* - delete_blocker
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { Handler, HandlerRegistry } from './types.js';
|
|
12
|
+
import { success, error } from './types.js';
|
|
13
|
+
import {
|
|
14
|
+
parseArgs,
|
|
15
|
+
uuidValidator,
|
|
16
|
+
createEnumValidator,
|
|
17
|
+
VALID_BLOCKER_STATUSES,
|
|
18
|
+
} from '../validators.js';
|
|
19
|
+
import { getApiClient } from '../api-client.js';
|
|
20
|
+
import { autoPostActivity } from './chat.js';
|
|
21
|
+
|
|
22
|
+
// Argument schemas for type-safe parsing
|
|
23
|
+
const addBlockerSchema = {
|
|
24
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
25
|
+
description: { type: 'string' as const, required: true as const },
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const resolveBlockerSchema = {
|
|
29
|
+
blocker_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
30
|
+
resolution_note: { type: 'string' as const },
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const getBlockerSchema = {
|
|
34
|
+
blocker_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const getBlockersSchema = {
|
|
38
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
39
|
+
status: { type: 'string' as const, default: 'open', validate: createEnumValidator(VALID_BLOCKER_STATUSES) },
|
|
40
|
+
limit: { type: 'number' as const, default: 10 },
|
|
41
|
+
offset: { type: 'number' as const, default: 0 },
|
|
42
|
+
search_query: { type: 'string' as const },
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const deleteBlockerSchema = {
|
|
46
|
+
blocker_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const getBlockersStatsSchema = {
|
|
50
|
+
project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const addBlocker: Handler = async (args, ctx) => {
|
|
54
|
+
const { project_id, description } = parseArgs(args, addBlockerSchema);
|
|
55
|
+
|
|
56
|
+
const apiClient = getApiClient();
|
|
57
|
+
const response = await apiClient.addBlocker(project_id, description, ctx.session.currentSessionId || undefined);
|
|
58
|
+
|
|
59
|
+
if (!response.ok) {
|
|
60
|
+
return error(response.error || 'Failed to add blocker');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Auto-post blocker activity to project chat
|
|
64
|
+
const persona = ctx.session.currentPersona || 'Agent';
|
|
65
|
+
void autoPostActivity(
|
|
66
|
+
project_id,
|
|
67
|
+
`🚧 **${persona}** reported a blocker: ${description}`,
|
|
68
|
+
ctx.session.currentSessionId
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
return success(response.data);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const resolveBlocker: Handler = async (args, _ctx) => {
|
|
75
|
+
const { blocker_id, resolution_note } = parseArgs(args, resolveBlockerSchema);
|
|
76
|
+
|
|
77
|
+
const apiClient = getApiClient();
|
|
78
|
+
const response = await apiClient.resolveBlocker(blocker_id, resolution_note);
|
|
79
|
+
|
|
80
|
+
if (!response.ok) {
|
|
81
|
+
return error(response.error || 'Failed to resolve blocker');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return success(response.data);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Get a single blocker by ID.
|
|
89
|
+
* More token-efficient than get_blockers when you need details for a specific blocker.
|
|
90
|
+
*/
|
|
91
|
+
export const getBlocker: Handler = async (args, _ctx) => {
|
|
92
|
+
const { blocker_id } = parseArgs(args, getBlockerSchema);
|
|
93
|
+
|
|
94
|
+
const apiClient = getApiClient();
|
|
95
|
+
const response = await apiClient.proxy<{
|
|
96
|
+
blocker: {
|
|
97
|
+
id: string;
|
|
98
|
+
description: string;
|
|
99
|
+
status: string;
|
|
100
|
+
resolution_note?: string;
|
|
101
|
+
created_at: string;
|
|
102
|
+
resolved_at?: string;
|
|
103
|
+
};
|
|
104
|
+
}>('get_blocker', { blocker_id });
|
|
105
|
+
|
|
106
|
+
if (!response.ok) {
|
|
107
|
+
return error(response.error || 'Failed to get blocker');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return success(response.data);
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export const getBlockers: Handler = async (args, _ctx) => {
|
|
114
|
+
const { project_id, status, limit, offset, search_query } = parseArgs(args, getBlockersSchema);
|
|
115
|
+
|
|
116
|
+
const apiClient = getApiClient();
|
|
117
|
+
const response = await apiClient.getBlockers(project_id, {
|
|
118
|
+
status,
|
|
119
|
+
limit: Math.min(limit ?? 10, 200),
|
|
120
|
+
offset,
|
|
121
|
+
search_query
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
if (!response.ok) {
|
|
125
|
+
return error(response.error || 'Failed to fetch blockers');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return success(response.data);
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export const deleteBlocker: Handler = async (args, _ctx) => {
|
|
132
|
+
const { blocker_id } = parseArgs(args, deleteBlockerSchema);
|
|
133
|
+
|
|
134
|
+
const apiClient = getApiClient();
|
|
135
|
+
const response = await apiClient.deleteBlocker(blocker_id);
|
|
136
|
+
|
|
137
|
+
if (!response.ok) {
|
|
138
|
+
return error(response.error || 'Failed to delete blocker');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return success(response.data);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Get aggregate statistics about blockers for a project.
|
|
146
|
+
* Returns total count and breakdown by status without the actual blocker data.
|
|
147
|
+
* This is much more token-efficient than get_blockers for understanding the overall state.
|
|
148
|
+
*/
|
|
149
|
+
export const getBlockersStats: Handler = async (args, _ctx) => {
|
|
150
|
+
const { project_id } = parseArgs(args, getBlockersStatsSchema);
|
|
151
|
+
|
|
152
|
+
const apiClient = getApiClient();
|
|
153
|
+
const response = await apiClient.getBlockersStats(project_id);
|
|
154
|
+
|
|
155
|
+
if (!response.ok) {
|
|
156
|
+
return error(response.error || 'Failed to get blockers stats');
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return success(response.data);
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Blockers handlers registry
|
|
164
|
+
*/
|
|
165
|
+
export const blockerHandlers: HandlerRegistry = {
|
|
166
|
+
add_blocker: addBlocker,
|
|
167
|
+
resolve_blocker: resolveBlocker,
|
|
168
|
+
get_blocker: getBlocker,
|
|
169
|
+
get_blockers: getBlockers,
|
|
170
|
+
get_blockers_stats: getBlockersStats,
|
|
171
|
+
delete_blocker: deleteBlocker,
|
|
172
|
+
};
|