@vibescope/mcp-server 0.2.3 → 0.2.4
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 -0
- package/README.md +45 -2
- package/dist/api-client.d.ts +276 -8
- package/dist/api-client.js +123 -8
- package/dist/handlers/blockers.d.ts +11 -0
- package/dist/handlers/blockers.js +37 -2
- package/dist/handlers/bodies-of-work.d.ts +2 -0
- package/dist/handlers/bodies-of-work.js +30 -1
- package/dist/handlers/connectors.js +2 -2
- package/dist/handlers/decisions.d.ts +11 -0
- package/dist/handlers/decisions.js +37 -2
- package/dist/handlers/deployment.d.ts +6 -0
- package/dist/handlers/deployment.js +33 -5
- package/dist/handlers/discovery.js +27 -11
- package/dist/handlers/fallback.js +12 -6
- package/dist/handlers/file-checkouts.d.ts +1 -0
- package/dist/handlers/file-checkouts.js +17 -2
- package/dist/handlers/findings.d.ts +5 -0
- package/dist/handlers/findings.js +19 -2
- package/dist/handlers/git-issues.js +4 -2
- package/dist/handlers/ideas.d.ts +5 -0
- package/dist/handlers/ideas.js +19 -2
- package/dist/handlers/progress.js +2 -2
- package/dist/handlers/project.d.ts +1 -0
- package/dist/handlers/project.js +35 -2
- package/dist/handlers/requests.js +6 -3
- package/dist/handlers/roles.js +13 -2
- package/dist/handlers/session.d.ts +12 -0
- package/dist/handlers/session.js +288 -25
- package/dist/handlers/sprints.d.ts +2 -0
- package/dist/handlers/sprints.js +30 -1
- package/dist/handlers/tasks.d.ts +25 -2
- package/dist/handlers/tasks.js +228 -35
- package/dist/handlers/tool-docs.js +72 -5
- package/dist/templates/agent-guidelines.d.ts +18 -0
- package/dist/templates/agent-guidelines.js +207 -0
- package/dist/tools.js +478 -125
- package/dist/utils.d.ts +5 -2
- package/dist/utils.js +90 -51
- package/package.json +51 -46
- package/scripts/version-bump.ts +203 -0
- package/src/api-client.ts +371 -12
- package/src/handlers/__test-setup__.ts +5 -0
- package/src/handlers/blockers.test.ts +76 -0
- package/src/handlers/blockers.ts +56 -2
- package/src/handlers/bodies-of-work.ts +59 -1
- package/src/handlers/connectors.ts +2 -2
- package/src/handlers/decisions.test.ts +71 -2
- package/src/handlers/decisions.ts +56 -2
- package/src/handlers/deployment.test.ts +81 -0
- package/src/handlers/deployment.ts +38 -5
- package/src/handlers/discovery.ts +27 -11
- package/src/handlers/fallback.test.ts +11 -10
- package/src/handlers/fallback.ts +14 -8
- package/src/handlers/file-checkouts.test.ts +83 -3
- package/src/handlers/file-checkouts.ts +22 -2
- package/src/handlers/findings.test.ts +2 -2
- package/src/handlers/findings.ts +38 -2
- package/src/handlers/git-issues.test.ts +2 -2
- package/src/handlers/git-issues.ts +4 -2
- package/src/handlers/ideas.test.ts +1 -1
- package/src/handlers/ideas.ts +34 -2
- package/src/handlers/progress.ts +2 -2
- package/src/handlers/project.ts +47 -2
- package/src/handlers/requests.test.ts +38 -7
- package/src/handlers/requests.ts +6 -3
- package/src/handlers/roles.test.ts +1 -1
- package/src/handlers/roles.ts +20 -2
- package/src/handlers/session.test.ts +303 -4
- package/src/handlers/session.ts +348 -35
- package/src/handlers/sprints.ts +61 -1
- package/src/handlers/tasks.test.ts +0 -73
- package/src/handlers/tasks.ts +269 -40
- package/src/handlers/tool-docs.ts +77 -5
- package/src/handlers/types.test.ts +259 -0
- package/src/templates/agent-guidelines.ts +210 -0
- package/src/tools.ts +479 -125
- package/src/utils.test.ts +7 -5
- package/src/utils.ts +95 -51
package/dist/api-client.js
CHANGED
|
@@ -114,6 +114,61 @@ export class VibescopeApiClient {
|
|
|
114
114
|
async getTask(taskId) {
|
|
115
115
|
return this.request('GET', `/api/mcp/tasks/${taskId}`);
|
|
116
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Get a single task by ID with optional subtasks and milestones
|
|
119
|
+
*/
|
|
120
|
+
async getTaskById(taskId, params) {
|
|
121
|
+
return this.proxy('get_task', {
|
|
122
|
+
task_id: taskId,
|
|
123
|
+
include_subtasks: params?.include_subtasks,
|
|
124
|
+
include_milestones: params?.include_milestones,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Search tasks by text query with pagination
|
|
129
|
+
*/
|
|
130
|
+
async searchTasks(projectId, params) {
|
|
131
|
+
return this.proxy('search_tasks', {
|
|
132
|
+
project_id: projectId,
|
|
133
|
+
query: params.query,
|
|
134
|
+
status: params.status,
|
|
135
|
+
limit: params.limit,
|
|
136
|
+
offset: params.offset,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Get tasks filtered by priority with pagination
|
|
141
|
+
*/
|
|
142
|
+
async getTasksByPriority(projectId, params) {
|
|
143
|
+
return this.proxy('get_tasks_by_priority', {
|
|
144
|
+
project_id: projectId,
|
|
145
|
+
priority: params?.priority,
|
|
146
|
+
priority_max: params?.priority_max,
|
|
147
|
+
status: params?.status,
|
|
148
|
+
limit: params?.limit,
|
|
149
|
+
offset: params?.offset,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Get recent tasks (newest or oldest) with pagination
|
|
154
|
+
*/
|
|
155
|
+
async getRecentTasks(projectId, params) {
|
|
156
|
+
return this.proxy('get_recent_tasks', {
|
|
157
|
+
project_id: projectId,
|
|
158
|
+
order: params?.order,
|
|
159
|
+
status: params?.status,
|
|
160
|
+
limit: params?.limit,
|
|
161
|
+
offset: params?.offset,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Get task statistics for a project
|
|
166
|
+
*/
|
|
167
|
+
async getTaskStats(projectId) {
|
|
168
|
+
return this.proxy('get_task_stats', {
|
|
169
|
+
project_id: projectId,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
117
172
|
async updateTask(taskId, updates) {
|
|
118
173
|
return this.request('PATCH', `/api/mcp/tasks/${taskId}`, updates);
|
|
119
174
|
}
|
|
@@ -173,6 +228,11 @@ export class VibescopeApiClient {
|
|
|
173
228
|
async deleteBlocker(blockerId) {
|
|
174
229
|
return this.proxy('delete_blocker', { blocker_id: blockerId });
|
|
175
230
|
}
|
|
231
|
+
async getBlockersStats(projectId) {
|
|
232
|
+
return this.proxy('get_blockers_stats', {
|
|
233
|
+
project_id: projectId
|
|
234
|
+
});
|
|
235
|
+
}
|
|
176
236
|
// ============================================================================
|
|
177
237
|
// Decision endpoints
|
|
178
238
|
// ============================================================================
|
|
@@ -188,6 +248,11 @@ export class VibescopeApiClient {
|
|
|
188
248
|
async deleteDecision(decisionId) {
|
|
189
249
|
return this.proxy('delete_decision', { decision_id: decisionId });
|
|
190
250
|
}
|
|
251
|
+
async getDecisionsStats(projectId) {
|
|
252
|
+
return this.proxy('get_decisions_stats', {
|
|
253
|
+
project_id: projectId
|
|
254
|
+
});
|
|
255
|
+
}
|
|
191
256
|
// ============================================================================
|
|
192
257
|
// Idea endpoints
|
|
193
258
|
// ============================================================================
|
|
@@ -274,8 +339,12 @@ export class VibescopeApiClient {
|
|
|
274
339
|
// ============================================================================
|
|
275
340
|
// Request endpoints
|
|
276
341
|
// ============================================================================
|
|
277
|
-
async getPendingRequests(projectId, sessionId) {
|
|
278
|
-
return this.proxy('get_pending_requests', {
|
|
342
|
+
async getPendingRequests(projectId, sessionId, limit, offset) {
|
|
343
|
+
return this.proxy('get_pending_requests', {
|
|
344
|
+
project_id: projectId,
|
|
345
|
+
...(limit !== undefined && { limit }),
|
|
346
|
+
...(offset !== undefined && { offset }),
|
|
347
|
+
}, sessionId ? {
|
|
279
348
|
session_id: sessionId,
|
|
280
349
|
persona: null,
|
|
281
350
|
instance_id: ''
|
|
@@ -334,8 +403,11 @@ export class VibescopeApiClient {
|
|
|
334
403
|
...params
|
|
335
404
|
});
|
|
336
405
|
}
|
|
337
|
-
async getActivitySchedules(projectId) {
|
|
338
|
-
return this.proxy('get_activity_schedules', {
|
|
406
|
+
async getActivitySchedules(projectId, params) {
|
|
407
|
+
return this.proxy('get_activity_schedules', {
|
|
408
|
+
project_id: projectId,
|
|
409
|
+
...params
|
|
410
|
+
});
|
|
339
411
|
}
|
|
340
412
|
// ============================================================================
|
|
341
413
|
// Subtask endpoints
|
|
@@ -439,6 +511,16 @@ export class VibescopeApiClient {
|
|
|
439
511
|
...params
|
|
440
512
|
});
|
|
441
513
|
}
|
|
514
|
+
/**
|
|
515
|
+
* Report actual API token usage for accurate cost tracking.
|
|
516
|
+
* This records token usage to the session and attributes cost to the current task.
|
|
517
|
+
*/
|
|
518
|
+
async reportTokenUsage(sessionId, params) {
|
|
519
|
+
return this.proxy('report_token_usage', {
|
|
520
|
+
session_id: sessionId,
|
|
521
|
+
...params
|
|
522
|
+
});
|
|
523
|
+
}
|
|
442
524
|
// ============================================================================
|
|
443
525
|
// Organization endpoints
|
|
444
526
|
// ============================================================================
|
|
@@ -653,6 +735,11 @@ export class VibescopeApiClient {
|
|
|
653
735
|
...params
|
|
654
736
|
});
|
|
655
737
|
}
|
|
738
|
+
async getDeploymentRequirementsStats(projectId) {
|
|
739
|
+
return this.proxy('get_deployment_requirements_stats', {
|
|
740
|
+
project_id: projectId
|
|
741
|
+
});
|
|
742
|
+
}
|
|
656
743
|
async completeDeploymentRequirement(requirementId) {
|
|
657
744
|
return this.proxy('complete_deployment_requirement', { requirement_id: requirementId });
|
|
658
745
|
}
|
|
@@ -662,10 +749,12 @@ export class VibescopeApiClient {
|
|
|
662
749
|
...params
|
|
663
750
|
});
|
|
664
751
|
}
|
|
665
|
-
async getScheduledDeployments(projectId,
|
|
752
|
+
async getScheduledDeployments(projectId, params) {
|
|
666
753
|
return this.proxy('get_scheduled_deployments', {
|
|
667
754
|
project_id: projectId,
|
|
668
|
-
include_disabled: includeDisabled
|
|
755
|
+
include_disabled: params?.includeDisabled,
|
|
756
|
+
limit: params?.limit,
|
|
757
|
+
offset: params?.offset
|
|
669
758
|
});
|
|
670
759
|
}
|
|
671
760
|
async updateScheduledDeployment(scheduleId, updates) {
|
|
@@ -696,6 +785,9 @@ export class VibescopeApiClient {
|
|
|
696
785
|
readme_content: readmeContent
|
|
697
786
|
});
|
|
698
787
|
}
|
|
788
|
+
async getProjectSummary(projectId) {
|
|
789
|
+
return this.proxy('get_project_summary', { project_id: projectId });
|
|
790
|
+
}
|
|
699
791
|
// ============================================================================
|
|
700
792
|
// Help Topics (database-backed)
|
|
701
793
|
// ============================================================================
|
|
@@ -735,11 +827,21 @@ export class VibescopeApiClient {
|
|
|
735
827
|
async abandonCheckout(params) {
|
|
736
828
|
return this.proxy('abandon_checkout', params);
|
|
737
829
|
}
|
|
830
|
+
async getFileCheckoutsStats(projectId) {
|
|
831
|
+
return this.proxy('get_file_checkouts_stats', { project_id: projectId });
|
|
832
|
+
}
|
|
738
833
|
// ============================================================================
|
|
739
834
|
// Worktree Management
|
|
740
835
|
// ============================================================================
|
|
741
|
-
async getStaleWorktrees(projectId) {
|
|
742
|
-
|
|
836
|
+
async getStaleWorktrees(projectId, params) {
|
|
837
|
+
const queryParams = new URLSearchParams({ project_id: projectId });
|
|
838
|
+
if (params?.hostname !== undefined)
|
|
839
|
+
queryParams.set('hostname', params.hostname);
|
|
840
|
+
if (params?.limit !== undefined)
|
|
841
|
+
queryParams.set('limit', String(params.limit));
|
|
842
|
+
if (params?.offset !== undefined)
|
|
843
|
+
queryParams.set('offset', String(params.offset));
|
|
844
|
+
return this.request('GET', `/api/mcp/worktrees/stale?${queryParams.toString()}`);
|
|
743
845
|
}
|
|
744
846
|
async clearWorktreePath(taskId) {
|
|
745
847
|
return this.request('PATCH', `/api/mcp/tasks/${taskId}`, { worktree_path: null });
|
|
@@ -777,6 +879,19 @@ export class VibescopeApiClient {
|
|
|
777
879
|
async getConnectorEvents(params) {
|
|
778
880
|
return this.proxy('get_connector_events', params);
|
|
779
881
|
}
|
|
882
|
+
// ============================================================================
|
|
883
|
+
// Agent onboarding endpoints
|
|
884
|
+
// ============================================================================
|
|
885
|
+
/**
|
|
886
|
+
* Confirm that agent setup is complete for a project.
|
|
887
|
+
* This marks the agent type as onboarded so future sessions don't receive setup instructions.
|
|
888
|
+
*/
|
|
889
|
+
async confirmAgentSetup(projectId, agentType) {
|
|
890
|
+
return this.proxy('confirm_agent_setup', {
|
|
891
|
+
project_id: projectId,
|
|
892
|
+
agent_type: agentType
|
|
893
|
+
});
|
|
894
|
+
}
|
|
780
895
|
}
|
|
781
896
|
// Singleton instance
|
|
782
897
|
let apiClient = null;
|
|
@@ -10,8 +10,19 @@
|
|
|
10
10
|
import type { Handler, HandlerRegistry } from './types.js';
|
|
11
11
|
export declare const addBlocker: Handler;
|
|
12
12
|
export declare const resolveBlocker: Handler;
|
|
13
|
+
/**
|
|
14
|
+
* Get a single blocker by ID.
|
|
15
|
+
* More token-efficient than get_blockers when you need details for a specific blocker.
|
|
16
|
+
*/
|
|
17
|
+
export declare const getBlocker: Handler;
|
|
13
18
|
export declare const getBlockers: Handler;
|
|
14
19
|
export declare const deleteBlocker: Handler;
|
|
20
|
+
/**
|
|
21
|
+
* Get aggregate statistics about blockers for a project.
|
|
22
|
+
* Returns total count and breakdown by status without the actual blocker data.
|
|
23
|
+
* This is much more token-efficient than get_blockers for understanding the overall state.
|
|
24
|
+
*/
|
|
25
|
+
export declare const getBlockersStats: Handler;
|
|
15
26
|
/**
|
|
16
27
|
* Blockers handlers registry
|
|
17
28
|
*/
|
|
@@ -19,16 +19,22 @@ const resolveBlockerSchema = {
|
|
|
19
19
|
blocker_id: { type: 'string', required: true, validate: uuidValidator },
|
|
20
20
|
resolution_note: { type: 'string' },
|
|
21
21
|
};
|
|
22
|
+
const getBlockerSchema = {
|
|
23
|
+
blocker_id: { type: 'string', required: true, validate: uuidValidator },
|
|
24
|
+
};
|
|
22
25
|
const getBlockersSchema = {
|
|
23
26
|
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
24
27
|
status: { type: 'string', default: 'open', validate: createEnumValidator(VALID_BLOCKER_STATUSES) },
|
|
25
|
-
limit: { type: 'number', default:
|
|
28
|
+
limit: { type: 'number', default: 10 },
|
|
26
29
|
offset: { type: 'number', default: 0 },
|
|
27
30
|
search_query: { type: 'string' },
|
|
28
31
|
};
|
|
29
32
|
const deleteBlockerSchema = {
|
|
30
33
|
blocker_id: { type: 'string', required: true, validate: uuidValidator },
|
|
31
34
|
};
|
|
35
|
+
const getBlockersStatsSchema = {
|
|
36
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
37
|
+
};
|
|
32
38
|
export const addBlocker = async (args, ctx) => {
|
|
33
39
|
const { project_id, description } = parseArgs(args, addBlockerSchema);
|
|
34
40
|
const apiClient = getApiClient();
|
|
@@ -47,12 +53,25 @@ export const resolveBlocker = async (args, _ctx) => {
|
|
|
47
53
|
}
|
|
48
54
|
return success(response.data);
|
|
49
55
|
};
|
|
56
|
+
/**
|
|
57
|
+
* Get a single blocker by ID.
|
|
58
|
+
* More token-efficient than get_blockers when you need details for a specific blocker.
|
|
59
|
+
*/
|
|
60
|
+
export const getBlocker = async (args, _ctx) => {
|
|
61
|
+
const { blocker_id } = parseArgs(args, getBlockerSchema);
|
|
62
|
+
const apiClient = getApiClient();
|
|
63
|
+
const response = await apiClient.proxy('get_blocker', { blocker_id });
|
|
64
|
+
if (!response.ok) {
|
|
65
|
+
return error(response.error || 'Failed to get blocker');
|
|
66
|
+
}
|
|
67
|
+
return success(response.data);
|
|
68
|
+
};
|
|
50
69
|
export const getBlockers = async (args, _ctx) => {
|
|
51
70
|
const { project_id, status, limit, offset, search_query } = parseArgs(args, getBlockersSchema);
|
|
52
71
|
const apiClient = getApiClient();
|
|
53
72
|
const response = await apiClient.getBlockers(project_id, {
|
|
54
73
|
status,
|
|
55
|
-
limit,
|
|
74
|
+
limit: Math.min(limit ?? 10, 200),
|
|
56
75
|
offset,
|
|
57
76
|
search_query
|
|
58
77
|
});
|
|
@@ -70,12 +89,28 @@ export const deleteBlocker = async (args, _ctx) => {
|
|
|
70
89
|
}
|
|
71
90
|
return success(response.data);
|
|
72
91
|
};
|
|
92
|
+
/**
|
|
93
|
+
* Get aggregate statistics about blockers for a project.
|
|
94
|
+
* Returns total count and breakdown by status without the actual blocker data.
|
|
95
|
+
* This is much more token-efficient than get_blockers for understanding the overall state.
|
|
96
|
+
*/
|
|
97
|
+
export const getBlockersStats = async (args, _ctx) => {
|
|
98
|
+
const { project_id } = parseArgs(args, getBlockersStatsSchema);
|
|
99
|
+
const apiClient = getApiClient();
|
|
100
|
+
const response = await apiClient.getBlockersStats(project_id);
|
|
101
|
+
if (!response.ok) {
|
|
102
|
+
return error(response.error || 'Failed to get blockers stats');
|
|
103
|
+
}
|
|
104
|
+
return success(response.data);
|
|
105
|
+
};
|
|
73
106
|
/**
|
|
74
107
|
* Blockers handlers registry
|
|
75
108
|
*/
|
|
76
109
|
export const blockerHandlers = {
|
|
77
110
|
add_blocker: addBlocker,
|
|
78
111
|
resolve_blocker: resolveBlocker,
|
|
112
|
+
get_blocker: getBlocker,
|
|
79
113
|
get_blockers: getBlockers,
|
|
114
|
+
get_blockers_stats: getBlockersStats,
|
|
80
115
|
delete_blocker: deleteBlocker,
|
|
81
116
|
};
|
|
@@ -30,6 +30,8 @@ export declare const addTaskDependency: Handler;
|
|
|
30
30
|
export declare const removeTaskDependency: Handler;
|
|
31
31
|
export declare const getTaskDependencies: Handler;
|
|
32
32
|
export declare const getNextBodyOfWorkTask: Handler;
|
|
33
|
+
export declare const archiveBodyOfWork: Handler;
|
|
34
|
+
export declare const unarchiveBodyOfWork: Handler;
|
|
33
35
|
/**
|
|
34
36
|
* Bodies of Work handlers registry
|
|
35
37
|
*/
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
*/
|
|
20
20
|
import { parseArgs, uuidValidator, createEnumValidator } from '../validators.js';
|
|
21
21
|
import { getApiClient } from '../api-client.js';
|
|
22
|
-
const BODY_OF_WORK_STATUSES = ['draft', 'active', 'completed', 'cancelled'];
|
|
22
|
+
const BODY_OF_WORK_STATUSES = ['draft', 'active', 'completed', 'cancelled', 'archived'];
|
|
23
23
|
const TASK_PHASES = ['pre', 'core', 'post'];
|
|
24
24
|
const DEPLOY_ENVIRONMENTS = ['development', 'staging', 'production'];
|
|
25
25
|
const VERSION_BUMPS = ['patch', 'minor', 'major'];
|
|
@@ -259,6 +259,33 @@ export const getNextBodyOfWorkTask = async (args, ctx) => {
|
|
|
259
259
|
}
|
|
260
260
|
return { result: response.data };
|
|
261
261
|
};
|
|
262
|
+
// ============================================================================
|
|
263
|
+
// Archive / Unarchive Handlers
|
|
264
|
+
// ============================================================================
|
|
265
|
+
const archiveBodyOfWorkSchema = {
|
|
266
|
+
body_of_work_id: { type: 'string', required: true, validate: uuidValidator },
|
|
267
|
+
};
|
|
268
|
+
const unarchiveBodyOfWorkSchema = {
|
|
269
|
+
body_of_work_id: { type: 'string', required: true, validate: uuidValidator },
|
|
270
|
+
};
|
|
271
|
+
export const archiveBodyOfWork = async (args, ctx) => {
|
|
272
|
+
const { body_of_work_id } = parseArgs(args, archiveBodyOfWorkSchema);
|
|
273
|
+
const apiClient = getApiClient();
|
|
274
|
+
const response = await apiClient.proxy('archive_body_of_work', { body_of_work_id });
|
|
275
|
+
if (!response.ok) {
|
|
276
|
+
return { result: { error: response.error || 'Failed to archive body of work' }, isError: true };
|
|
277
|
+
}
|
|
278
|
+
return { result: response.data };
|
|
279
|
+
};
|
|
280
|
+
export const unarchiveBodyOfWork = async (args, ctx) => {
|
|
281
|
+
const { body_of_work_id } = parseArgs(args, unarchiveBodyOfWorkSchema);
|
|
282
|
+
const apiClient = getApiClient();
|
|
283
|
+
const response = await apiClient.proxy('unarchive_body_of_work', { body_of_work_id });
|
|
284
|
+
if (!response.ok) {
|
|
285
|
+
return { result: { error: response.error || 'Failed to unarchive body of work' }, isError: true };
|
|
286
|
+
}
|
|
287
|
+
return { result: response.data };
|
|
288
|
+
};
|
|
262
289
|
/**
|
|
263
290
|
* Bodies of Work handlers registry
|
|
264
291
|
*/
|
|
@@ -275,4 +302,6 @@ export const bodiesOfWorkHandlers = {
|
|
|
275
302
|
remove_task_dependency: removeTaskDependency,
|
|
276
303
|
get_task_dependencies: getTaskDependencies,
|
|
277
304
|
get_next_body_of_work_task: getNextBodyOfWorkTask,
|
|
305
|
+
archive_body_of_work: archiveBodyOfWork,
|
|
306
|
+
unarchive_body_of_work: unarchiveBodyOfWork,
|
|
278
307
|
};
|
|
@@ -68,7 +68,7 @@ export const getConnectors = async (args, _ctx) => {
|
|
|
68
68
|
const response = await apiClient.getConnectors(project_id, {
|
|
69
69
|
type,
|
|
70
70
|
status,
|
|
71
|
-
limit,
|
|
71
|
+
limit: Math.min(limit ?? 50, 50),
|
|
72
72
|
offset
|
|
73
73
|
});
|
|
74
74
|
if (!response.ok) {
|
|
@@ -161,7 +161,7 @@ export const getConnectorEvents = async (args, _ctx) => {
|
|
|
161
161
|
connector_id,
|
|
162
162
|
project_id,
|
|
163
163
|
status,
|
|
164
|
-
limit,
|
|
164
|
+
limit: Math.min(limit ?? 50, 50),
|
|
165
165
|
offset
|
|
166
166
|
});
|
|
167
167
|
if (!response.ok) {
|
|
@@ -10,8 +10,19 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { Handler, HandlerRegistry } from './types.js';
|
|
12
12
|
export declare const logDecision: Handler;
|
|
13
|
+
/**
|
|
14
|
+
* Get a single decision by ID.
|
|
15
|
+
* More token-efficient than get_decisions when you need details for a specific decision.
|
|
16
|
+
*/
|
|
17
|
+
export declare const getDecision: Handler;
|
|
13
18
|
export declare const getDecisions: Handler;
|
|
14
19
|
export declare const deleteDecision: Handler;
|
|
20
|
+
/**
|
|
21
|
+
* Get aggregate statistics about decisions for a project.
|
|
22
|
+
* Returns total count without the actual decision data.
|
|
23
|
+
* This is more token-efficient than get_decisions for understanding overall state.
|
|
24
|
+
*/
|
|
25
|
+
export declare const getDecisionsStats: Handler;
|
|
15
26
|
/**
|
|
16
27
|
* Decisions handlers registry
|
|
17
28
|
*/
|
|
@@ -18,15 +18,21 @@ const logDecisionSchema = {
|
|
|
18
18
|
rationale: { type: 'string' },
|
|
19
19
|
alternatives_considered: { type: 'array' },
|
|
20
20
|
};
|
|
21
|
+
const getDecisionSchema = {
|
|
22
|
+
decision_id: { type: 'string', required: true, validate: uuidValidator },
|
|
23
|
+
};
|
|
21
24
|
const getDecisionsSchema = {
|
|
22
25
|
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
23
|
-
limit: { type: 'number', default:
|
|
26
|
+
limit: { type: 'number', default: 10 },
|
|
24
27
|
offset: { type: 'number', default: 0 },
|
|
25
28
|
search_query: { type: 'string' },
|
|
26
29
|
};
|
|
27
30
|
const deleteDecisionSchema = {
|
|
28
31
|
decision_id: { type: 'string', required: true, validate: uuidValidator },
|
|
29
32
|
};
|
|
33
|
+
const getDecisionsStatsSchema = {
|
|
34
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
35
|
+
};
|
|
30
36
|
export const logDecision = async (args, ctx) => {
|
|
31
37
|
const { project_id, title, description, rationale, alternatives_considered } = parseArgs(args, logDecisionSchema);
|
|
32
38
|
const { session } = ctx;
|
|
@@ -42,11 +48,24 @@ export const logDecision = async (args, ctx) => {
|
|
|
42
48
|
}
|
|
43
49
|
return { result: { success: true, title, decision_id: response.data?.decision_id } };
|
|
44
50
|
};
|
|
51
|
+
/**
|
|
52
|
+
* Get a single decision by ID.
|
|
53
|
+
* More token-efficient than get_decisions when you need details for a specific decision.
|
|
54
|
+
*/
|
|
55
|
+
export const getDecision = async (args, _ctx) => {
|
|
56
|
+
const { decision_id } = parseArgs(args, getDecisionSchema);
|
|
57
|
+
const apiClient = getApiClient();
|
|
58
|
+
const response = await apiClient.proxy('get_decision', { decision_id });
|
|
59
|
+
if (!response.ok) {
|
|
60
|
+
return { result: { error: response.error || 'Failed to get decision' }, isError: true };
|
|
61
|
+
}
|
|
62
|
+
return { result: response.data };
|
|
63
|
+
};
|
|
45
64
|
export const getDecisions = async (args, _ctx) => {
|
|
46
65
|
const { project_id, limit, offset, search_query } = parseArgs(args, getDecisionsSchema);
|
|
47
66
|
const apiClient = getApiClient();
|
|
48
67
|
const response = await apiClient.getDecisions(project_id, {
|
|
49
|
-
limit,
|
|
68
|
+
limit: Math.min(limit ?? 10, 200),
|
|
50
69
|
offset,
|
|
51
70
|
search_query
|
|
52
71
|
});
|
|
@@ -68,11 +87,27 @@ export const deleteDecision = async (args, _ctx) => {
|
|
|
68
87
|
}
|
|
69
88
|
return { result: { success: true } };
|
|
70
89
|
};
|
|
90
|
+
/**
|
|
91
|
+
* Get aggregate statistics about decisions for a project.
|
|
92
|
+
* Returns total count without the actual decision data.
|
|
93
|
+
* This is more token-efficient than get_decisions for understanding overall state.
|
|
94
|
+
*/
|
|
95
|
+
export const getDecisionsStats = async (args, _ctx) => {
|
|
96
|
+
const { project_id } = parseArgs(args, getDecisionsStatsSchema);
|
|
97
|
+
const apiClient = getApiClient();
|
|
98
|
+
const response = await apiClient.getDecisionsStats(project_id);
|
|
99
|
+
if (!response.ok) {
|
|
100
|
+
return { result: { error: response.error || 'Failed to get decisions stats' }, isError: true };
|
|
101
|
+
}
|
|
102
|
+
return { result: response.data };
|
|
103
|
+
};
|
|
71
104
|
/**
|
|
72
105
|
* Decisions handlers registry
|
|
73
106
|
*/
|
|
74
107
|
export const decisionHandlers = {
|
|
75
108
|
log_decision: logDecision,
|
|
109
|
+
get_decision: getDecision,
|
|
76
110
|
get_decisions: getDecisions,
|
|
111
|
+
get_decisions_stats: getDecisionsStats,
|
|
77
112
|
delete_decision: deleteDecision,
|
|
78
113
|
};
|
|
@@ -24,6 +24,12 @@ export declare const cancelDeployment: Handler;
|
|
|
24
24
|
export declare const addDeploymentRequirement: Handler;
|
|
25
25
|
export declare const completeDeploymentRequirement: Handler;
|
|
26
26
|
export declare const getDeploymentRequirements: Handler;
|
|
27
|
+
/**
|
|
28
|
+
* Get aggregate statistics about deployment requirements for a project.
|
|
29
|
+
* Returns total count and breakdowns by status, stage, and type.
|
|
30
|
+
* More token-efficient than get_deployment_requirements when you just need to understand the overall state.
|
|
31
|
+
*/
|
|
32
|
+
export declare const getDeploymentRequirementsStats: Handler;
|
|
27
33
|
export declare const scheduleDeployment: Handler;
|
|
28
34
|
export declare const getScheduledDeployments: Handler;
|
|
29
35
|
export declare const updateScheduledDeployment: Handler;
|
|
@@ -63,7 +63,7 @@ const addDeploymentRequirementSchema = {
|
|
|
63
63
|
file_path: { type: 'string' },
|
|
64
64
|
stage: { type: 'string', default: 'preparation', validate: createEnumValidator(REQUIREMENT_STAGES) },
|
|
65
65
|
blocking: { type: 'boolean', default: false },
|
|
66
|
-
recurring: { type: 'boolean', default:
|
|
66
|
+
recurring: { type: 'boolean', default: true },
|
|
67
67
|
};
|
|
68
68
|
const completeDeploymentRequirementSchema = {
|
|
69
69
|
requirement_id: { type: 'string', required: true, validate: uuidValidator },
|
|
@@ -72,6 +72,11 @@ const getDeploymentRequirementsSchema = {
|
|
|
72
72
|
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
73
73
|
status: { type: 'string', default: 'pending', validate: createEnumValidator(REQUIREMENT_STATUSES) },
|
|
74
74
|
stage: { type: 'string', validate: createEnumValidator([...REQUIREMENT_STAGES, 'all']) },
|
|
75
|
+
limit: { type: 'number', default: 50 },
|
|
76
|
+
offset: { type: 'number', default: 0 },
|
|
77
|
+
};
|
|
78
|
+
const getDeploymentRequirementsStatsSchema = {
|
|
79
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
75
80
|
};
|
|
76
81
|
const scheduleDeploymentSchema = {
|
|
77
82
|
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
@@ -87,6 +92,8 @@ const scheduleDeploymentSchema = {
|
|
|
87
92
|
const getScheduledDeploymentsSchema = {
|
|
88
93
|
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
89
94
|
include_disabled: { type: 'boolean', default: false },
|
|
95
|
+
limit: { type: 'number', default: 50 },
|
|
96
|
+
offset: { type: 'number', default: 0 },
|
|
90
97
|
};
|
|
91
98
|
const updateScheduledDeploymentSchema = {
|
|
92
99
|
schedule_id: { type: 'string', required: true, validate: uuidValidator },
|
|
@@ -216,17 +223,33 @@ export const completeDeploymentRequirement = async (args, ctx) => {
|
|
|
216
223
|
return { result: response.data };
|
|
217
224
|
};
|
|
218
225
|
export const getDeploymentRequirements = async (args, ctx) => {
|
|
219
|
-
const { project_id, status, stage } = parseArgs(args, getDeploymentRequirementsSchema);
|
|
226
|
+
const { project_id, status, stage, limit, offset } = parseArgs(args, getDeploymentRequirementsSchema);
|
|
220
227
|
const apiClient = getApiClient();
|
|
221
228
|
const response = await apiClient.getDeploymentRequirements(project_id, {
|
|
222
229
|
status: status,
|
|
223
|
-
stage: stage
|
|
230
|
+
stage: stage,
|
|
231
|
+
limit,
|
|
232
|
+
offset
|
|
224
233
|
});
|
|
225
234
|
if (!response.ok) {
|
|
226
235
|
return { result: { error: response.error || 'Failed to get deployment requirements' }, isError: true };
|
|
227
236
|
}
|
|
228
237
|
return { result: response.data };
|
|
229
238
|
};
|
|
239
|
+
/**
|
|
240
|
+
* Get aggregate statistics about deployment requirements for a project.
|
|
241
|
+
* Returns total count and breakdowns by status, stage, and type.
|
|
242
|
+
* More token-efficient than get_deployment_requirements when you just need to understand the overall state.
|
|
243
|
+
*/
|
|
244
|
+
export const getDeploymentRequirementsStats = async (args, ctx) => {
|
|
245
|
+
const { project_id } = parseArgs(args, getDeploymentRequirementsStatsSchema);
|
|
246
|
+
const apiClient = getApiClient();
|
|
247
|
+
const response = await apiClient.getDeploymentRequirementsStats(project_id);
|
|
248
|
+
if (!response.ok) {
|
|
249
|
+
return { result: { error: response.error || 'Failed to get deployment requirements stats' }, isError: true };
|
|
250
|
+
}
|
|
251
|
+
return { result: response.data };
|
|
252
|
+
};
|
|
230
253
|
// ============================================================================
|
|
231
254
|
// Scheduled Deployments
|
|
232
255
|
// ============================================================================
|
|
@@ -269,9 +292,13 @@ export const scheduleDeployment = async (args, ctx) => {
|
|
|
269
292
|
return { result: response.data };
|
|
270
293
|
};
|
|
271
294
|
export const getScheduledDeployments = async (args, ctx) => {
|
|
272
|
-
const { project_id, include_disabled } = parseArgs(args, getScheduledDeploymentsSchema);
|
|
295
|
+
const { project_id, include_disabled, limit, offset } = parseArgs(args, getScheduledDeploymentsSchema);
|
|
273
296
|
const apiClient = getApiClient();
|
|
274
|
-
const response = await apiClient.getScheduledDeployments(project_id,
|
|
297
|
+
const response = await apiClient.getScheduledDeployments(project_id, {
|
|
298
|
+
includeDisabled: include_disabled,
|
|
299
|
+
limit,
|
|
300
|
+
offset
|
|
301
|
+
});
|
|
275
302
|
if (!response.ok) {
|
|
276
303
|
return { result: { error: response.error || 'Failed to get scheduled deployments' }, isError: true };
|
|
277
304
|
}
|
|
@@ -359,6 +386,7 @@ export const deploymentHandlers = {
|
|
|
359
386
|
add_deployment_requirement: addDeploymentRequirement,
|
|
360
387
|
complete_deployment_requirement: completeDeploymentRequirement,
|
|
361
388
|
get_deployment_requirements: getDeploymentRequirements,
|
|
389
|
+
get_deployment_requirements_stats: getDeploymentRequirementsStats,
|
|
362
390
|
// Scheduled deployments
|
|
363
391
|
schedule_deployment: scheduleDeployment,
|
|
364
392
|
get_scheduled_deployments: getScheduledDeployments,
|