@vibescope/mcp-server 0.3.0 → 0.3.3
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/dist/api-client/blockers.d.ts +46 -0
- package/dist/api-client/blockers.js +43 -0
- package/dist/api-client/cost.d.ts +112 -0
- package/dist/api-client/cost.js +76 -0
- package/dist/api-client/decisions.d.ts +55 -0
- package/dist/api-client/decisions.js +32 -0
- package/dist/api-client/discovery.d.ts +62 -0
- package/dist/api-client/discovery.js +21 -0
- package/dist/api-client/ideas.d.ts +75 -0
- package/dist/api-client/ideas.js +36 -0
- package/dist/api-client/index.d.ts +749 -0
- package/dist/api-client/index.js +291 -0
- package/dist/api-client/project.d.ts +132 -0
- package/dist/api-client/project.js +45 -0
- package/dist/api-client/session.d.ts +163 -0
- package/dist/api-client/session.js +52 -0
- package/dist/api-client/tasks.d.ts +328 -0
- package/dist/api-client/tasks.js +132 -0
- package/dist/api-client/types.d.ts +25 -0
- package/dist/api-client/types.js +4 -0
- package/dist/api-client/worktrees.d.ts +33 -0
- package/dist/api-client/worktrees.js +26 -0
- package/dist/api-client.d.ts +9 -0
- package/dist/api-client.js +104 -25
- package/dist/cli-init.d.ts +17 -0
- package/dist/cli-init.js +445 -0
- package/dist/cli.js +0 -0
- package/dist/handlers/cloud-agents.d.ts +21 -0
- package/dist/handlers/cloud-agents.js +91 -0
- package/dist/handlers/discovery.js +7 -0
- package/dist/handlers/index.d.ts +1 -0
- package/dist/handlers/index.js +3 -0
- package/dist/handlers/session.js +3 -1
- package/dist/handlers/tasks.js +10 -12
- package/dist/handlers/types.d.ts +2 -1
- package/dist/handlers/validation.js +5 -1
- package/dist/index.js +8 -3
- package/dist/token-tracking.js +2 -2
- package/dist/tools/blockers.d.ts +13 -0
- package/dist/tools/blockers.js +119 -0
- package/dist/tools/bodies-of-work.d.ts +19 -0
- package/dist/tools/bodies-of-work.js +280 -0
- package/dist/tools/cloud-agents.d.ts +9 -0
- package/dist/tools/cloud-agents.js +67 -0
- package/dist/tools/connectors.d.ts +14 -0
- package/dist/tools/connectors.js +188 -0
- package/dist/tools/cost.d.ts +11 -0
- package/dist/tools/cost.js +108 -0
- package/dist/tools/decisions.d.ts +12 -0
- package/dist/tools/decisions.js +108 -0
- package/dist/tools/deployment.d.ts +24 -0
- package/dist/tools/deployment.js +439 -0
- package/dist/tools/discovery.d.ts +10 -0
- package/dist/tools/discovery.js +73 -0
- package/dist/tools/fallback.d.ts +11 -0
- package/dist/tools/fallback.js +108 -0
- package/dist/tools/file-checkouts.d.ts +13 -0
- package/dist/tools/file-checkouts.js +141 -0
- package/dist/tools/findings.d.ts +13 -0
- package/dist/tools/findings.js +98 -0
- package/dist/tools/git-issues.d.ts +11 -0
- package/dist/tools/git-issues.js +127 -0
- package/dist/tools/ideas.d.ts +13 -0
- package/dist/tools/ideas.js +159 -0
- package/dist/tools/index.d.ts +71 -0
- package/dist/tools/index.js +98 -0
- package/dist/tools/milestones.d.ts +12 -0
- package/dist/tools/milestones.js +115 -0
- package/dist/tools/organizations.d.ts +17 -0
- package/dist/tools/organizations.js +221 -0
- package/dist/tools/progress.d.ts +9 -0
- package/dist/tools/progress.js +70 -0
- package/dist/tools/project.d.ts +13 -0
- package/dist/tools/project.js +199 -0
- package/dist/tools/requests.d.ts +10 -0
- package/dist/tools/requests.js +65 -0
- package/dist/tools/roles.d.ts +11 -0
- package/dist/tools/roles.js +109 -0
- package/dist/tools/session.d.ts +15 -0
- package/dist/tools/session.js +178 -0
- package/dist/tools/sprints.d.ts +18 -0
- package/dist/tools/sprints.js +295 -0
- package/dist/tools/tasks.d.ts +27 -0
- package/dist/tools/tasks.js +539 -0
- package/dist/tools/types.d.ts +7 -0
- package/dist/tools/types.js +6 -0
- package/dist/tools/validation.d.ts +10 -0
- package/dist/tools/validation.js +72 -0
- package/dist/tools/worktrees.d.ts +9 -0
- package/dist/tools/worktrees.js +63 -0
- package/dist/utils.d.ts +66 -0
- package/dist/utils.js +102 -0
- package/docs/TOOLS.md +55 -2
- package/package.json +5 -3
- package/scripts/generate-docs.ts +1 -1
- package/src/api-client/blockers.ts +86 -0
- package/src/api-client/cost.ts +185 -0
- package/src/api-client/decisions.ts +87 -0
- package/src/api-client/discovery.ts +81 -0
- package/src/api-client/ideas.ts +112 -0
- package/src/api-client/index.ts +378 -0
- package/src/api-client/project.ts +179 -0
- package/src/api-client/session.ts +220 -0
- package/src/api-client/tasks.ts +450 -0
- package/src/api-client/types.ts +32 -0
- package/src/api-client/worktrees.ts +53 -0
- package/src/api-client.test.ts +136 -9
- package/src/api-client.ts +125 -27
- package/src/cli-init.ts +504 -0
- package/src/handlers/__test-utils__.ts +2 -0
- package/src/handlers/cloud-agents.ts +138 -0
- package/src/handlers/discovery.ts +7 -0
- package/src/handlers/index.ts +3 -0
- package/src/handlers/session.ts +3 -1
- package/src/handlers/tasks.ts +10 -12
- package/src/handlers/tool-categories.test.ts +1 -1
- package/src/handlers/types.ts +2 -1
- package/src/handlers/validation.ts +6 -1
- package/src/index.test.ts +2 -2
- package/src/index.ts +8 -2
- package/src/token-tracking.ts +3 -2
- package/src/tools/blockers.ts +122 -0
- package/src/tools/bodies-of-work.ts +283 -0
- package/src/tools/cloud-agents.ts +70 -0
- package/src/tools/connectors.ts +191 -0
- package/src/tools/cost.ts +111 -0
- package/src/tools/decisions.ts +111 -0
- package/src/tools/deployment.ts +442 -0
- package/src/tools/discovery.ts +76 -0
- package/src/tools/fallback.ts +111 -0
- package/src/tools/file-checkouts.ts +145 -0
- package/src/tools/findings.ts +101 -0
- package/src/tools/git-issues.ts +130 -0
- package/src/tools/ideas.ts +162 -0
- package/src/tools/index.ts +131 -0
- package/src/tools/milestones.ts +118 -0
- package/src/tools/organizations.ts +224 -0
- package/src/tools/progress.ts +73 -0
- package/src/tools/project.ts +202 -0
- package/src/tools/requests.ts +68 -0
- package/src/tools/roles.ts +112 -0
- package/src/tools/session.ts +181 -0
- package/src/tools/sprints.ts +298 -0
- package/src/tools/tasks.ts +542 -0
- package/src/tools/tools.test.ts +222 -0
- package/src/tools/types.ts +9 -0
- package/src/tools/validation.ts +75 -0
- package/src/tools/worktrees.ts +66 -0
- package/src/tools.test.ts +1 -1
- package/src/utils.test.ts +229 -0
- package/src/utils.ts +117 -0
- package/dist/tools.d.ts +0 -2
- package/dist/tools.js +0 -3602
- package/src/tools.ts +0 -3607
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vibescope API Client
|
|
3
|
+
*
|
|
4
|
+
* HTTP client for communicating with the Vibescope API.
|
|
5
|
+
* All database operations are handled server-side through these endpoints.
|
|
6
|
+
*
|
|
7
|
+
* This module composes domain-specific API methods into a unified client.
|
|
8
|
+
*/
|
|
9
|
+
import { createSessionMethods } from './session.js';
|
|
10
|
+
import { createProjectMethods } from './project.js';
|
|
11
|
+
import { createBlockersMethods } from './blockers.js';
|
|
12
|
+
import { createCostMethods } from './cost.js';
|
|
13
|
+
import { createWorktreesMethods } from './worktrees.js';
|
|
14
|
+
import { createDiscoveryMethods } from './discovery.js';
|
|
15
|
+
import { createDecisionsMethods } from './decisions.js';
|
|
16
|
+
import { createIdeasMethods } from './ideas.js';
|
|
17
|
+
import { createTasksMethods } from './tasks.js';
|
|
18
|
+
const DEFAULT_API_URL = 'https://vibescope.dev';
|
|
19
|
+
// Retry configuration defaults
|
|
20
|
+
const DEFAULT_RETRY_STATUS_CODES = [429, 503, 504];
|
|
21
|
+
const DEFAULT_MAX_RETRIES = 3;
|
|
22
|
+
const DEFAULT_BASE_DELAY_MS = 1000;
|
|
23
|
+
const DEFAULT_MAX_DELAY_MS = 30000;
|
|
24
|
+
/**
|
|
25
|
+
* Calculate delay for exponential backoff with jitter
|
|
26
|
+
*/
|
|
27
|
+
function calculateBackoffDelay(attempt, baseDelayMs, maxDelayMs, retryAfter) {
|
|
28
|
+
if (retryAfter !== undefined && retryAfter > 0) {
|
|
29
|
+
return Math.min(retryAfter * 1000, maxDelayMs);
|
|
30
|
+
}
|
|
31
|
+
const exponentialDelay = baseDelayMs * Math.pow(2, attempt);
|
|
32
|
+
const jitter = Math.random() * 0.3 * exponentialDelay;
|
|
33
|
+
return Math.min(exponentialDelay + jitter, maxDelayMs);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Sleep for a specified duration
|
|
37
|
+
*/
|
|
38
|
+
function sleep(ms) {
|
|
39
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
40
|
+
}
|
|
41
|
+
export class VibescopeApiClient {
|
|
42
|
+
apiKey;
|
|
43
|
+
baseUrl;
|
|
44
|
+
retryConfig;
|
|
45
|
+
// Domain method implementations
|
|
46
|
+
sessionMethods;
|
|
47
|
+
projectMethods;
|
|
48
|
+
blockersMethods;
|
|
49
|
+
costMethods;
|
|
50
|
+
worktreesMethods;
|
|
51
|
+
discoveryMethods;
|
|
52
|
+
decisionsMethods;
|
|
53
|
+
ideasMethods;
|
|
54
|
+
tasksMethods;
|
|
55
|
+
constructor(config) {
|
|
56
|
+
this.apiKey = config.apiKey;
|
|
57
|
+
this.baseUrl = config.baseUrl || process.env.VIBESCOPE_API_URL || DEFAULT_API_URL;
|
|
58
|
+
this.retryConfig = {
|
|
59
|
+
maxRetries: config.retry?.maxRetries ?? DEFAULT_MAX_RETRIES,
|
|
60
|
+
baseDelayMs: config.retry?.baseDelayMs ?? DEFAULT_BASE_DELAY_MS,
|
|
61
|
+
maxDelayMs: config.retry?.maxDelayMs ?? DEFAULT_MAX_DELAY_MS,
|
|
62
|
+
retryStatusCodes: config.retry?.retryStatusCodes ?? DEFAULT_RETRY_STATUS_CODES,
|
|
63
|
+
};
|
|
64
|
+
// Create bound request and proxy functions for domain modules
|
|
65
|
+
const request = this.request.bind(this);
|
|
66
|
+
const proxy = this.proxy.bind(this);
|
|
67
|
+
const getApiKey = () => this.apiKey;
|
|
68
|
+
// Initialize domain methods
|
|
69
|
+
this.sessionMethods = createSessionMethods(request, getApiKey);
|
|
70
|
+
this.projectMethods = createProjectMethods(request);
|
|
71
|
+
this.blockersMethods = createBlockersMethods(request);
|
|
72
|
+
this.costMethods = createCostMethods(request);
|
|
73
|
+
this.worktreesMethods = createWorktreesMethods(request);
|
|
74
|
+
this.discoveryMethods = createDiscoveryMethods(request);
|
|
75
|
+
this.decisionsMethods = createDecisionsMethods(proxy);
|
|
76
|
+
this.ideasMethods = createIdeasMethods(proxy);
|
|
77
|
+
this.tasksMethods = createTasksMethods(request, proxy);
|
|
78
|
+
}
|
|
79
|
+
async request(method, path, body) {
|
|
80
|
+
const url = `${this.baseUrl}${path}`;
|
|
81
|
+
const { maxRetries, baseDelayMs, maxDelayMs, retryStatusCodes } = this.retryConfig;
|
|
82
|
+
let lastError = null;
|
|
83
|
+
let lastResponse = null;
|
|
84
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
85
|
+
try {
|
|
86
|
+
const response = await fetch(url, {
|
|
87
|
+
method,
|
|
88
|
+
headers: {
|
|
89
|
+
'Content-Type': 'application/json',
|
|
90
|
+
'X-API-Key': this.apiKey
|
|
91
|
+
},
|
|
92
|
+
body: body ? JSON.stringify(body) : undefined
|
|
93
|
+
});
|
|
94
|
+
if (retryStatusCodes.includes(response.status) && attempt < maxRetries) {
|
|
95
|
+
lastResponse = response;
|
|
96
|
+
const retryAfterHeader = response.headers.get('Retry-After');
|
|
97
|
+
let retryAfter;
|
|
98
|
+
if (retryAfterHeader) {
|
|
99
|
+
const parsed = parseInt(retryAfterHeader, 10);
|
|
100
|
+
if (!isNaN(parsed)) {
|
|
101
|
+
retryAfter = parsed;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const delay = calculateBackoffDelay(attempt, baseDelayMs, maxDelayMs, retryAfter);
|
|
105
|
+
await sleep(delay);
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
if (!response.ok) {
|
|
109
|
+
const errorData = await response.json().catch(() => ({}));
|
|
110
|
+
return {
|
|
111
|
+
ok: false,
|
|
112
|
+
status: response.status,
|
|
113
|
+
error: errorData.error || errorData.message || `HTTP ${response.status}`
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
const data = await response.json();
|
|
117
|
+
return {
|
|
118
|
+
ok: true,
|
|
119
|
+
status: response.status,
|
|
120
|
+
data
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
lastError = error;
|
|
125
|
+
if (attempt < maxRetries) {
|
|
126
|
+
const delay = calculateBackoffDelay(attempt, baseDelayMs, maxDelayMs);
|
|
127
|
+
await sleep(delay);
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (lastResponse && !lastResponse.ok) {
|
|
133
|
+
return {
|
|
134
|
+
ok: false,
|
|
135
|
+
status: lastResponse.status,
|
|
136
|
+
error: `Request failed after ${maxRetries + 1} attempts with status ${lastResponse.status}`
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
ok: false,
|
|
141
|
+
status: 0,
|
|
142
|
+
error: lastError?.message || 'Request failed after all retries'
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Generic proxy method for operations that go through the MCP proxy endpoint
|
|
147
|
+
*/
|
|
148
|
+
async proxy(operation, args, sessionContext) {
|
|
149
|
+
return this.request('POST', '/api/mcp/proxy', {
|
|
150
|
+
operation,
|
|
151
|
+
args,
|
|
152
|
+
...sessionContext
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
// ============================================================================
|
|
156
|
+
// Session methods (delegated)
|
|
157
|
+
// ============================================================================
|
|
158
|
+
validateAuth = () => this.sessionMethods.validateAuth();
|
|
159
|
+
startSession = (params) => this.sessionMethods.startSession(params);
|
|
160
|
+
heartbeat = (sessionId, options) => this.sessionMethods.heartbeat(sessionId, options);
|
|
161
|
+
endSession = (sessionId) => this.sessionMethods.endSession(sessionId);
|
|
162
|
+
signalIdle = (sessionId) => this.sessionMethods.signalIdle(sessionId);
|
|
163
|
+
syncSession = (sessionId, params) => this.sessionMethods.syncSession(sessionId, params);
|
|
164
|
+
confirmAgentSetup = (projectId, agentType) => this.sessionMethods.confirmAgentSetup(projectId, agentType);
|
|
165
|
+
// ============================================================================
|
|
166
|
+
// Project methods (delegated)
|
|
167
|
+
// ============================================================================
|
|
168
|
+
listProjects = () => this.projectMethods.listProjects();
|
|
169
|
+
createProject = (params) => this.projectMethods.createProject(params);
|
|
170
|
+
getProject = (projectId, gitUrl) => this.projectMethods.getProject(projectId, gitUrl);
|
|
171
|
+
updateProject = (projectId, updates) => this.projectMethods.updateProject(projectId, updates);
|
|
172
|
+
getGitWorkflow = (projectId, taskId) => this.projectMethods.getGitWorkflow(projectId, taskId);
|
|
173
|
+
updateProjectReadme = (projectId, readmeContent) => this.projectMethods.updateProjectReadme(projectId, readmeContent);
|
|
174
|
+
getProjectSummary = (projectId) => this.projectMethods.getProjectSummary(projectId);
|
|
175
|
+
// ============================================================================
|
|
176
|
+
// Blockers methods (delegated)
|
|
177
|
+
// ============================================================================
|
|
178
|
+
getBlockers = (projectId, params) => this.blockersMethods.getBlockers(projectId, params);
|
|
179
|
+
addBlocker = (projectId, description, sessionId) => this.blockersMethods.addBlocker(projectId, description, sessionId);
|
|
180
|
+
resolveBlocker = (blockerId, resolutionNote) => this.blockersMethods.resolveBlocker(blockerId, resolutionNote);
|
|
181
|
+
deleteBlocker = (blockerId) => this.blockersMethods.deleteBlocker(blockerId);
|
|
182
|
+
getBlockersStats = (projectId) => this.blockersMethods.getBlockersStats(projectId);
|
|
183
|
+
// ============================================================================
|
|
184
|
+
// Cost methods (delegated)
|
|
185
|
+
// ============================================================================
|
|
186
|
+
getCostSummary = (projectId, params) => this.costMethods.getCostSummary(projectId, params);
|
|
187
|
+
getCostAlerts = () => this.costMethods.getCostAlerts();
|
|
188
|
+
addCostAlert = (params) => this.costMethods.addCostAlert(params);
|
|
189
|
+
updateCostAlert = (alertId, updates) => this.costMethods.updateCostAlert(alertId, updates);
|
|
190
|
+
deleteCostAlert = (alertId) => this.costMethods.deleteCostAlert(alertId);
|
|
191
|
+
getTaskCosts = (projectId, limit) => this.costMethods.getTaskCosts(projectId, limit);
|
|
192
|
+
getBodyOfWorkCosts = (params) => this.costMethods.getBodyOfWorkCosts(params);
|
|
193
|
+
getSprintCosts = (params) => this.costMethods.getSprintCosts(params);
|
|
194
|
+
getTokenUsage = () => this.costMethods.getTokenUsage();
|
|
195
|
+
reportTokenUsage = (sessionId, params) => this.costMethods.reportTokenUsage(sessionId, params);
|
|
196
|
+
// ============================================================================
|
|
197
|
+
// Worktrees methods (delegated)
|
|
198
|
+
// ============================================================================
|
|
199
|
+
getStaleWorktrees = (projectId, params) => this.worktreesMethods.getStaleWorktrees(projectId, params);
|
|
200
|
+
clearWorktreePath = (taskId) => this.worktreesMethods.clearWorktreePath(taskId);
|
|
201
|
+
// ============================================================================
|
|
202
|
+
// Discovery methods (delegated)
|
|
203
|
+
// ============================================================================
|
|
204
|
+
queryKnowledgeBase = (projectId, params) => this.discoveryMethods.queryKnowledgeBase(projectId, params);
|
|
205
|
+
getHelpTopic = (slug) => this.discoveryMethods.getHelpTopic(slug);
|
|
206
|
+
getHelpTopics = () => this.discoveryMethods.getHelpTopics();
|
|
207
|
+
// ============================================================================
|
|
208
|
+
// Decisions methods (delegated)
|
|
209
|
+
// ============================================================================
|
|
210
|
+
getDecisions = (projectId, options) => this.decisionsMethods.getDecisions(projectId, options);
|
|
211
|
+
getDecision = (decisionId) => this.decisionsMethods.getDecision(decisionId);
|
|
212
|
+
logDecision = (projectId, params, sessionId) => this.decisionsMethods.logDecision(projectId, params, sessionId);
|
|
213
|
+
deleteDecision = (decisionId) => this.decisionsMethods.deleteDecision(decisionId);
|
|
214
|
+
getDecisionsStats = (projectId) => this.decisionsMethods.getDecisionsStats(projectId);
|
|
215
|
+
// ============================================================================
|
|
216
|
+
// Ideas methods (delegated)
|
|
217
|
+
// ============================================================================
|
|
218
|
+
getIdeas = (projectId, params) => this.ideasMethods.getIdeas(projectId, params);
|
|
219
|
+
getIdea = (ideaId) => this.ideasMethods.getIdea(ideaId);
|
|
220
|
+
addIdea = (projectId, params, sessionId) => this.ideasMethods.addIdea(projectId, params, sessionId);
|
|
221
|
+
updateIdea = (ideaId, updates) => this.ideasMethods.updateIdea(ideaId, updates);
|
|
222
|
+
deleteIdea = (ideaId) => this.ideasMethods.deleteIdea(ideaId);
|
|
223
|
+
convertIdeaToTask = (ideaId, params) => this.ideasMethods.convertIdeaToTask(ideaId, params);
|
|
224
|
+
// ============================================================================
|
|
225
|
+
// Tasks methods (delegated)
|
|
226
|
+
// ============================================================================
|
|
227
|
+
getTasks = (projectId, params) => this.tasksMethods.getTasks(projectId, params);
|
|
228
|
+
createTask = (projectId, params) => this.tasksMethods.createTask(projectId, params);
|
|
229
|
+
getNextTask = (projectId, sessionId) => this.tasksMethods.getNextTask(projectId, sessionId);
|
|
230
|
+
getTask = (taskId) => this.tasksMethods.getTask(taskId);
|
|
231
|
+
getTaskById = (taskId, params) => this.tasksMethods.getTaskById(taskId, params);
|
|
232
|
+
searchTasks = (projectId, params) => this.tasksMethods.searchTasks(projectId, params);
|
|
233
|
+
getTasksByPriority = (projectId, params) => this.tasksMethods.getTasksByPriority(projectId, params);
|
|
234
|
+
getRecentTasks = (projectId, params) => this.tasksMethods.getRecentTasks(projectId, params);
|
|
235
|
+
getTaskStats = (projectId) => this.tasksMethods.getTaskStats(projectId);
|
|
236
|
+
updateTask = (taskId, updates) => this.tasksMethods.updateTask(taskId, updates);
|
|
237
|
+
completeTask = (taskId, params) => this.tasksMethods.completeTask(taskId, params);
|
|
238
|
+
deleteTask = (taskId) => this.tasksMethods.deleteTask(taskId);
|
|
239
|
+
releaseTask = (taskId, params) => this.tasksMethods.releaseTask(taskId, params);
|
|
240
|
+
cancelTask = (taskId, params) => this.tasksMethods.cancelTask(taskId, params);
|
|
241
|
+
addTaskReference = (taskId, url, label) => this.tasksMethods.addTaskReference(taskId, url, label);
|
|
242
|
+
removeTaskReference = (taskId, url) => this.tasksMethods.removeTaskReference(taskId, url);
|
|
243
|
+
batchUpdateTasks = (updates) => this.tasksMethods.batchUpdateTasks(updates);
|
|
244
|
+
batchCompleteTasks = (completions) => this.tasksMethods.batchCompleteTasks(completions);
|
|
245
|
+
}
|
|
246
|
+
// Singleton instance
|
|
247
|
+
let apiClient = null;
|
|
248
|
+
export function getApiClient() {
|
|
249
|
+
if (!apiClient) {
|
|
250
|
+
const apiKey = resolveApiKeyFromSources();
|
|
251
|
+
apiClient = new VibescopeApiClient({ apiKey });
|
|
252
|
+
}
|
|
253
|
+
return apiClient;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Resolve API key from multiple sources in priority order:
|
|
257
|
+
* 1. VIBESCOPE_API_KEY env var (CI/cloud agents)
|
|
258
|
+
* 2. ~/.vibescope/credentials.json (local dev)
|
|
259
|
+
* 3. Error with helpful message
|
|
260
|
+
*/
|
|
261
|
+
function resolveApiKeyFromSources() {
|
|
262
|
+
// 1. Environment variable
|
|
263
|
+
if (process.env.VIBESCOPE_API_KEY) {
|
|
264
|
+
return process.env.VIBESCOPE_API_KEY;
|
|
265
|
+
}
|
|
266
|
+
// 2. Credentials file
|
|
267
|
+
try {
|
|
268
|
+
const { existsSync, readFileSync } = require('node:fs');
|
|
269
|
+
const { homedir } = require('node:os');
|
|
270
|
+
const { join } = require('node:path');
|
|
271
|
+
const credPath = join(homedir(), '.vibescope', 'credentials.json');
|
|
272
|
+
if (existsSync(credPath)) {
|
|
273
|
+
const data = JSON.parse(readFileSync(credPath, 'utf-8'));
|
|
274
|
+
if (data.apiKey) {
|
|
275
|
+
return data.apiKey;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
// ignore read errors
|
|
281
|
+
}
|
|
282
|
+
// 3. Not found
|
|
283
|
+
throw new Error('Vibescope API key not found.\n\n' +
|
|
284
|
+
'Set it up with:\n' +
|
|
285
|
+
' npx vibescope init\n\n' +
|
|
286
|
+
'Or set the VIBESCOPE_API_KEY environment variable.');
|
|
287
|
+
}
|
|
288
|
+
export function initApiClient(config) {
|
|
289
|
+
apiClient = new VibescopeApiClient(config);
|
|
290
|
+
return apiClient;
|
|
291
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project API Methods
|
|
3
|
+
*
|
|
4
|
+
* Methods for project management:
|
|
5
|
+
* - listProjects: List all projects
|
|
6
|
+
* - createProject: Create a new project
|
|
7
|
+
* - getProject: Get project details
|
|
8
|
+
* - updateProject: Update project settings
|
|
9
|
+
* - getGitWorkflow: Get git workflow configuration
|
|
10
|
+
* - updateProjectReadme: Update project README
|
|
11
|
+
* - getProjectSummary: Get project summary
|
|
12
|
+
*/
|
|
13
|
+
import type { ApiResponse, RequestFn } from './types.js';
|
|
14
|
+
export interface ProjectMethods {
|
|
15
|
+
listProjects(): Promise<ApiResponse<{
|
|
16
|
+
projects: Array<{
|
|
17
|
+
id: string;
|
|
18
|
+
name: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
status: string;
|
|
21
|
+
git_url?: string;
|
|
22
|
+
goal?: string;
|
|
23
|
+
tech_stack?: string[];
|
|
24
|
+
}>;
|
|
25
|
+
}>>;
|
|
26
|
+
createProject(params: {
|
|
27
|
+
name: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
goal?: string;
|
|
30
|
+
git_url?: string;
|
|
31
|
+
tech_stack?: string[];
|
|
32
|
+
}): Promise<ApiResponse<{
|
|
33
|
+
success: boolean;
|
|
34
|
+
project: {
|
|
35
|
+
id: string;
|
|
36
|
+
name: string;
|
|
37
|
+
};
|
|
38
|
+
}>>;
|
|
39
|
+
getProject(projectId: string, gitUrl?: string): Promise<ApiResponse<{
|
|
40
|
+
found: boolean;
|
|
41
|
+
project?: {
|
|
42
|
+
id: string;
|
|
43
|
+
name: string;
|
|
44
|
+
description?: string;
|
|
45
|
+
goal?: string;
|
|
46
|
+
status: string;
|
|
47
|
+
git_url?: string;
|
|
48
|
+
agent_instructions?: string;
|
|
49
|
+
tech_stack?: string[];
|
|
50
|
+
git_workflow?: string;
|
|
51
|
+
git_main_branch?: string;
|
|
52
|
+
git_develop_branch?: string;
|
|
53
|
+
git_auto_branch?: boolean;
|
|
54
|
+
git_auto_tag?: boolean;
|
|
55
|
+
deployment_instructions?: string;
|
|
56
|
+
};
|
|
57
|
+
active_tasks?: Array<{
|
|
58
|
+
id: string;
|
|
59
|
+
title: string;
|
|
60
|
+
description?: string;
|
|
61
|
+
priority: number;
|
|
62
|
+
status: string;
|
|
63
|
+
progress_percentage?: number;
|
|
64
|
+
estimated_minutes?: number;
|
|
65
|
+
}>;
|
|
66
|
+
open_blockers?: Array<{
|
|
67
|
+
id: string;
|
|
68
|
+
description: string;
|
|
69
|
+
}>;
|
|
70
|
+
recent_decisions?: Array<{
|
|
71
|
+
id: string;
|
|
72
|
+
title: string;
|
|
73
|
+
description?: string;
|
|
74
|
+
}>;
|
|
75
|
+
message?: string;
|
|
76
|
+
}>>;
|
|
77
|
+
updateProject(projectId: string, updates: {
|
|
78
|
+
name?: string;
|
|
79
|
+
description?: string;
|
|
80
|
+
goal?: string;
|
|
81
|
+
git_url?: string;
|
|
82
|
+
tech_stack?: string[];
|
|
83
|
+
status?: string;
|
|
84
|
+
git_workflow?: string;
|
|
85
|
+
git_main_branch?: string;
|
|
86
|
+
git_develop_branch?: string;
|
|
87
|
+
git_auto_branch?: boolean;
|
|
88
|
+
git_auto_tag?: boolean;
|
|
89
|
+
deployment_instructions?: string;
|
|
90
|
+
agent_instructions?: string;
|
|
91
|
+
git_delete_branch_on_merge?: boolean;
|
|
92
|
+
require_pr_for_validation?: boolean;
|
|
93
|
+
auto_merge_on_approval?: boolean;
|
|
94
|
+
validation_required?: boolean;
|
|
95
|
+
default_task_priority?: number;
|
|
96
|
+
require_time_estimates?: boolean;
|
|
97
|
+
fallback_activities_enabled?: boolean;
|
|
98
|
+
preferred_fallback_activities?: string[];
|
|
99
|
+
}): Promise<ApiResponse<{
|
|
100
|
+
success: boolean;
|
|
101
|
+
project_id: string;
|
|
102
|
+
}>>;
|
|
103
|
+
getGitWorkflow(projectId: string, taskId?: string): Promise<ApiResponse<{
|
|
104
|
+
workflow: string;
|
|
105
|
+
main_branch: string;
|
|
106
|
+
develop_branch?: string;
|
|
107
|
+
suggested_branch?: string;
|
|
108
|
+
base_branch?: string;
|
|
109
|
+
}>>;
|
|
110
|
+
updateProjectReadme(projectId: string, readmeContent: string): Promise<ApiResponse<{
|
|
111
|
+
success: boolean;
|
|
112
|
+
project_id: string;
|
|
113
|
+
}>>;
|
|
114
|
+
getProjectSummary(projectId: string): Promise<ApiResponse<{
|
|
115
|
+
project: {
|
|
116
|
+
id: string;
|
|
117
|
+
name: string;
|
|
118
|
+
description?: string;
|
|
119
|
+
goal?: string;
|
|
120
|
+
status: string;
|
|
121
|
+
};
|
|
122
|
+
stats: {
|
|
123
|
+
total_tasks: number;
|
|
124
|
+
completed_tasks: number;
|
|
125
|
+
in_progress_tasks: number;
|
|
126
|
+
pending_tasks: number;
|
|
127
|
+
open_blockers: number;
|
|
128
|
+
total_decisions: number;
|
|
129
|
+
};
|
|
130
|
+
}>>;
|
|
131
|
+
}
|
|
132
|
+
export declare function createProjectMethods(request: RequestFn): ProjectMethods;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project API Methods
|
|
3
|
+
*
|
|
4
|
+
* Methods for project management:
|
|
5
|
+
* - listProjects: List all projects
|
|
6
|
+
* - createProject: Create a new project
|
|
7
|
+
* - getProject: Get project details
|
|
8
|
+
* - updateProject: Update project settings
|
|
9
|
+
* - getGitWorkflow: Get git workflow configuration
|
|
10
|
+
* - updateProjectReadme: Update project README
|
|
11
|
+
* - getProjectSummary: Get project summary
|
|
12
|
+
*/
|
|
13
|
+
export function createProjectMethods(request) {
|
|
14
|
+
return {
|
|
15
|
+
async listProjects() {
|
|
16
|
+
return request('GET', '/api/mcp/projects');
|
|
17
|
+
},
|
|
18
|
+
async createProject(params) {
|
|
19
|
+
return request('POST', '/api/mcp/projects', params);
|
|
20
|
+
},
|
|
21
|
+
async getProject(projectId, gitUrl) {
|
|
22
|
+
const url = gitUrl
|
|
23
|
+
? `/api/mcp/projects/${projectId}?git_url=${encodeURIComponent(gitUrl)}`
|
|
24
|
+
: `/api/mcp/projects/${projectId}`;
|
|
25
|
+
return request('GET', url);
|
|
26
|
+
},
|
|
27
|
+
async updateProject(projectId, updates) {
|
|
28
|
+
return request('PATCH', `/api/mcp/projects/${projectId}`, updates);
|
|
29
|
+
},
|
|
30
|
+
async getGitWorkflow(projectId, taskId) {
|
|
31
|
+
const url = taskId
|
|
32
|
+
? `/api/mcp/projects/${projectId}/git-workflow?task_id=${taskId}`
|
|
33
|
+
: `/api/mcp/projects/${projectId}/git-workflow`;
|
|
34
|
+
return request('GET', url);
|
|
35
|
+
},
|
|
36
|
+
async updateProjectReadme(projectId, readmeContent) {
|
|
37
|
+
return request('PATCH', `/api/mcp/projects/${projectId}/readme`, {
|
|
38
|
+
readme_content: readmeContent
|
|
39
|
+
});
|
|
40
|
+
},
|
|
41
|
+
async getProjectSummary(projectId) {
|
|
42
|
+
return request('GET', `/api/mcp/projects/${projectId}/summary`);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session API Methods
|
|
3
|
+
*
|
|
4
|
+
* Methods for session lifecycle management:
|
|
5
|
+
* - validateAuth: Validate API key
|
|
6
|
+
* - startSession: Start a new work session
|
|
7
|
+
* - heartbeat: Maintain active status
|
|
8
|
+
* - endSession: End session and release tasks
|
|
9
|
+
* - signalIdle: Signal agent is idle
|
|
10
|
+
* - syncSession: Sync session state
|
|
11
|
+
* - confirmAgentSetup: Confirm agent setup completion
|
|
12
|
+
*/
|
|
13
|
+
import type { ApiResponse, RequestFn } from './types.js';
|
|
14
|
+
export interface SessionMethods {
|
|
15
|
+
validateAuth(): Promise<ApiResponse<{
|
|
16
|
+
valid: boolean;
|
|
17
|
+
user_id: string;
|
|
18
|
+
api_key_id: string;
|
|
19
|
+
key_name: string;
|
|
20
|
+
}>>;
|
|
21
|
+
startSession(params: {
|
|
22
|
+
project_id?: string;
|
|
23
|
+
git_url?: string;
|
|
24
|
+
mode?: 'lite' | 'full';
|
|
25
|
+
model?: string;
|
|
26
|
+
role?: string;
|
|
27
|
+
hostname?: string;
|
|
28
|
+
agent_type?: string;
|
|
29
|
+
agent_name?: string;
|
|
30
|
+
}): Promise<ApiResponse<{
|
|
31
|
+
session_started: boolean;
|
|
32
|
+
session_id?: string;
|
|
33
|
+
persona?: string;
|
|
34
|
+
role?: string;
|
|
35
|
+
project?: {
|
|
36
|
+
id: string;
|
|
37
|
+
name: string;
|
|
38
|
+
description?: string;
|
|
39
|
+
goal?: string;
|
|
40
|
+
status?: string;
|
|
41
|
+
git_url?: string;
|
|
42
|
+
agent_instructions?: string;
|
|
43
|
+
tech_stack?: string[];
|
|
44
|
+
git_workflow?: string;
|
|
45
|
+
git_main_branch?: string;
|
|
46
|
+
git_develop_branch?: string;
|
|
47
|
+
git_auto_branch?: boolean;
|
|
48
|
+
};
|
|
49
|
+
active_tasks?: Array<{
|
|
50
|
+
id: string;
|
|
51
|
+
title: string;
|
|
52
|
+
status: string;
|
|
53
|
+
priority: number;
|
|
54
|
+
progress_percentage?: number;
|
|
55
|
+
estimated_minutes?: number;
|
|
56
|
+
}>;
|
|
57
|
+
blockers?: Array<{
|
|
58
|
+
id: string;
|
|
59
|
+
description: string;
|
|
60
|
+
status: string;
|
|
61
|
+
}>;
|
|
62
|
+
next_task?: {
|
|
63
|
+
id: string;
|
|
64
|
+
title: string;
|
|
65
|
+
priority: number;
|
|
66
|
+
estimated_minutes?: number;
|
|
67
|
+
} | null;
|
|
68
|
+
pending_requests?: Array<{
|
|
69
|
+
id: string;
|
|
70
|
+
request_type: string;
|
|
71
|
+
message: string;
|
|
72
|
+
created_at: string;
|
|
73
|
+
}>;
|
|
74
|
+
pending_requests_count?: number;
|
|
75
|
+
URGENT_QUESTIONS?: {
|
|
76
|
+
count: number;
|
|
77
|
+
oldest_waiting_minutes: number;
|
|
78
|
+
action_required: string;
|
|
79
|
+
requests: Array<{
|
|
80
|
+
id: string;
|
|
81
|
+
message: string;
|
|
82
|
+
waiting_minutes: number;
|
|
83
|
+
}>;
|
|
84
|
+
};
|
|
85
|
+
directive?: string;
|
|
86
|
+
blockers_count?: number;
|
|
87
|
+
validation_count?: number;
|
|
88
|
+
project_not_found?: boolean;
|
|
89
|
+
message?: string;
|
|
90
|
+
suggestion?: {
|
|
91
|
+
action: string;
|
|
92
|
+
example: string;
|
|
93
|
+
note: string;
|
|
94
|
+
};
|
|
95
|
+
agent_setup?: {
|
|
96
|
+
agent_type: string;
|
|
97
|
+
is_new_agent_type: boolean;
|
|
98
|
+
setup_required: boolean;
|
|
99
|
+
instructions: string;
|
|
100
|
+
config_file: string;
|
|
101
|
+
template_url?: string;
|
|
102
|
+
steps: string[];
|
|
103
|
+
};
|
|
104
|
+
stale_worktrees?: Array<{
|
|
105
|
+
task_id: string;
|
|
106
|
+
task_title: string;
|
|
107
|
+
worktree_path: string;
|
|
108
|
+
worktree_hostname?: string | null;
|
|
109
|
+
}>;
|
|
110
|
+
stale_worktrees_count?: number;
|
|
111
|
+
cleanup_action?: string;
|
|
112
|
+
awaiting_validation?: Array<{
|
|
113
|
+
id: string;
|
|
114
|
+
title?: string;
|
|
115
|
+
}>;
|
|
116
|
+
validation_priority?: boolean;
|
|
117
|
+
next_action?: string;
|
|
118
|
+
error?: string;
|
|
119
|
+
}>>;
|
|
120
|
+
heartbeat(sessionId: string, options?: {
|
|
121
|
+
current_worktree_path?: string | null;
|
|
122
|
+
hostname?: string;
|
|
123
|
+
}): Promise<ApiResponse<{
|
|
124
|
+
success: boolean;
|
|
125
|
+
session_id: string;
|
|
126
|
+
timestamp: string;
|
|
127
|
+
}>>;
|
|
128
|
+
endSession(sessionId: string): Promise<ApiResponse<{
|
|
129
|
+
success: boolean;
|
|
130
|
+
ended_session_id?: string;
|
|
131
|
+
session_summary?: {
|
|
132
|
+
agent_name: string;
|
|
133
|
+
tasks_completed_this_session: number;
|
|
134
|
+
tasks_awaiting_validation: number;
|
|
135
|
+
tasks_released: number;
|
|
136
|
+
};
|
|
137
|
+
reminders?: string[];
|
|
138
|
+
}>>;
|
|
139
|
+
signalIdle(sessionId: string): Promise<ApiResponse<{
|
|
140
|
+
success: boolean;
|
|
141
|
+
session_id: string;
|
|
142
|
+
status: string;
|
|
143
|
+
message: string;
|
|
144
|
+
}>>;
|
|
145
|
+
syncSession(sessionId: string, params?: {
|
|
146
|
+
include_project?: boolean;
|
|
147
|
+
include_tasks?: boolean;
|
|
148
|
+
}): Promise<ApiResponse<{
|
|
149
|
+
session: {
|
|
150
|
+
id: string;
|
|
151
|
+
status: string;
|
|
152
|
+
agent_name: string;
|
|
153
|
+
};
|
|
154
|
+
project?: unknown;
|
|
155
|
+
tasks?: unknown[];
|
|
156
|
+
}>>;
|
|
157
|
+
confirmAgentSetup(projectId: string, agentType: string): Promise<ApiResponse<{
|
|
158
|
+
success: boolean;
|
|
159
|
+
project_id: string;
|
|
160
|
+
agent_type: string;
|
|
161
|
+
}>>;
|
|
162
|
+
}
|
|
163
|
+
export declare function createSessionMethods(request: RequestFn, getApiKey: () => string): SessionMethods;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session API Methods
|
|
3
|
+
*
|
|
4
|
+
* Methods for session lifecycle management:
|
|
5
|
+
* - validateAuth: Validate API key
|
|
6
|
+
* - startSession: Start a new work session
|
|
7
|
+
* - heartbeat: Maintain active status
|
|
8
|
+
* - endSession: End session and release tasks
|
|
9
|
+
* - signalIdle: Signal agent is idle
|
|
10
|
+
* - syncSession: Sync session state
|
|
11
|
+
* - confirmAgentSetup: Confirm agent setup completion
|
|
12
|
+
*/
|
|
13
|
+
export function createSessionMethods(request, getApiKey) {
|
|
14
|
+
return {
|
|
15
|
+
async validateAuth() {
|
|
16
|
+
return request('POST', '/api/mcp/auth/validate', {
|
|
17
|
+
api_key: getApiKey()
|
|
18
|
+
});
|
|
19
|
+
},
|
|
20
|
+
async startSession(params) {
|
|
21
|
+
return request('POST', '/api/mcp/sessions/start', params);
|
|
22
|
+
},
|
|
23
|
+
async heartbeat(sessionId, options) {
|
|
24
|
+
return request('POST', '/api/mcp/sessions/heartbeat', {
|
|
25
|
+
session_id: sessionId,
|
|
26
|
+
...options
|
|
27
|
+
});
|
|
28
|
+
},
|
|
29
|
+
async endSession(sessionId) {
|
|
30
|
+
return request('POST', '/api/mcp/sessions/end', {
|
|
31
|
+
session_id: sessionId
|
|
32
|
+
});
|
|
33
|
+
},
|
|
34
|
+
async signalIdle(sessionId) {
|
|
35
|
+
return request('POST', '/api/mcp/sessions/idle', {
|
|
36
|
+
session_id: sessionId
|
|
37
|
+
});
|
|
38
|
+
},
|
|
39
|
+
async syncSession(sessionId, params) {
|
|
40
|
+
return request('POST', '/api/mcp/sessions/sync', {
|
|
41
|
+
session_id: sessionId,
|
|
42
|
+
...params
|
|
43
|
+
});
|
|
44
|
+
},
|
|
45
|
+
async confirmAgentSetup(projectId, agentType) {
|
|
46
|
+
return request('POST', '/api/mcp/agent-setup/confirm', {
|
|
47
|
+
project_id: projectId,
|
|
48
|
+
agent_type: agentType
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|