@rallycry/conveyor-mcp 3.3.0 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-OAHSTMYM.js → chunk-Z566YAS7.js} +147 -73
- package/dist/chunk-Z566YAS7.js.map +1 -0
- package/dist/cli.js +443 -155
- package/dist/cli.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/tunnel-cli.js +1 -1
- package/dist/tunnel.d.ts +60 -22
- package/package.json +3 -1
- package/dist/chunk-OAHSTMYM.js.map +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// src/connection.ts
|
|
2
2
|
import { io } from "socket.io-client";
|
|
3
|
+
var NO_PROJECT_SELECTED_MESSAGE = "No Conveyor project selected. Pass projectId to this tool or configure CONVEYOR_PROJECT_ID.";
|
|
3
4
|
var AUTH_ERROR_RE = /token|unauthor|forbidden|not authenticated|invalid auth/i;
|
|
4
5
|
function enrichToolError(error, fallback) {
|
|
5
6
|
const base = error ?? fallback ?? "Request failed";
|
|
@@ -15,7 +16,21 @@ var ConveyorConnection = class {
|
|
|
15
16
|
this.config = config;
|
|
16
17
|
}
|
|
17
18
|
get projectId() {
|
|
18
|
-
return this.
|
|
19
|
+
return this.resolveProjectId();
|
|
20
|
+
}
|
|
21
|
+
resolveProjectId(projectId) {
|
|
22
|
+
const resolved = projectId ?? this.config.projectId;
|
|
23
|
+
if (!resolved) throw new Error(NO_PROJECT_SELECTED_MESSAGE);
|
|
24
|
+
return resolved;
|
|
25
|
+
}
|
|
26
|
+
normalizeProjectList(response) {
|
|
27
|
+
if (Array.isArray(response)) return response;
|
|
28
|
+
if (typeof response !== "object" || response === null) return [];
|
|
29
|
+
const record = response;
|
|
30
|
+
if (Array.isArray(record.items)) return record.items;
|
|
31
|
+
if (Array.isArray(record.projects)) return record.projects;
|
|
32
|
+
if (Array.isArray(record.data)) return record.data;
|
|
33
|
+
return [];
|
|
19
34
|
}
|
|
20
35
|
connect() {
|
|
21
36
|
return new Promise((resolve, reject) => {
|
|
@@ -49,7 +64,7 @@ var ConveyorConnection = class {
|
|
|
49
64
|
this.socket?.close();
|
|
50
65
|
reject(
|
|
51
66
|
new Error(
|
|
52
|
-
`Conveyor rejected the connection: ${message}. The project token is likely invalid or expired \u2014 regenerate it in the web app (User Settings \u2192 Connect Claude Code) and update CONVEYOR_PROJECT_TOKEN.`
|
|
67
|
+
`Conveyor rejected the connection: ${message}. The project token is likely invalid or expired \u2014 regenerate it in the web app (User Settings \u2192 Connect Claude Code) and update CONVEYOR_USER_TOKEN (or legacy CONVEYOR_PROJECT_TOKEN).`
|
|
53
68
|
)
|
|
54
69
|
);
|
|
55
70
|
return;
|
|
@@ -96,145 +111,193 @@ var ConveyorConnection = class {
|
|
|
96
111
|
if (!socket) throw new Error("Not connected");
|
|
97
112
|
socket.emit(`agentSessionService:${method}`, data);
|
|
98
113
|
}
|
|
114
|
+
callService(serviceName, method, data, timeoutMs = 15e3) {
|
|
115
|
+
const socket = this.socket;
|
|
116
|
+
if (!socket) throw new Error("Not connected");
|
|
117
|
+
return Promise.race([
|
|
118
|
+
new Promise((resolve, reject) => {
|
|
119
|
+
socket.emit(`${serviceName}:${method}`, data, ((response) => {
|
|
120
|
+
if (response.success) {
|
|
121
|
+
resolve(response.data);
|
|
122
|
+
} else {
|
|
123
|
+
reject(new Error(enrichToolError(response.error, `${method} failed`)));
|
|
124
|
+
}
|
|
125
|
+
}));
|
|
126
|
+
}),
|
|
127
|
+
new Promise((_, reject) => {
|
|
128
|
+
setTimeout(() => {
|
|
129
|
+
reject(new Error(`Request timed out: ${serviceName}:${method}`));
|
|
130
|
+
}, timeoutMs);
|
|
131
|
+
})
|
|
132
|
+
]);
|
|
133
|
+
}
|
|
99
134
|
// ── Task Queries ────────────────────────────────────────────────────
|
|
100
135
|
listTasks(params) {
|
|
136
|
+
const { projectId, ...rest } = params;
|
|
101
137
|
return this.call("listProjectTasks", {
|
|
102
|
-
projectId: this.
|
|
103
|
-
...
|
|
138
|
+
projectId: this.resolveProjectId(projectId),
|
|
139
|
+
...rest
|
|
104
140
|
});
|
|
105
141
|
}
|
|
106
|
-
getTask(taskId) {
|
|
142
|
+
getTask(taskId, projectId) {
|
|
107
143
|
return this.call("getProjectTask", {
|
|
108
|
-
projectId: this.
|
|
144
|
+
projectId: this.resolveProjectId(projectId),
|
|
109
145
|
taskId
|
|
110
146
|
});
|
|
111
147
|
}
|
|
148
|
+
getCardBySlug(slug, projectId) {
|
|
149
|
+
return this.call("getProjectTask", {
|
|
150
|
+
projectId: this.resolveProjectId(projectId),
|
|
151
|
+
taskId: slug
|
|
152
|
+
});
|
|
153
|
+
}
|
|
112
154
|
searchTasks(params) {
|
|
155
|
+
const { projectId, ...rest } = params;
|
|
113
156
|
return this.call("searchProjectTasks", {
|
|
114
|
-
projectId: this.
|
|
115
|
-
...
|
|
157
|
+
projectId: this.resolveProjectId(projectId),
|
|
158
|
+
...rest
|
|
116
159
|
});
|
|
117
160
|
}
|
|
118
161
|
// ── Task Mutations ──────────────────────────────────────────────────
|
|
119
162
|
createTask(params) {
|
|
163
|
+
const { projectId, ...rest } = params;
|
|
120
164
|
return this.call("createProjectTask", {
|
|
121
|
-
projectId: this.
|
|
122
|
-
...
|
|
165
|
+
projectId: this.resolveProjectId(projectId),
|
|
166
|
+
...rest
|
|
123
167
|
});
|
|
124
168
|
}
|
|
125
169
|
updateTask(params) {
|
|
170
|
+
const { projectId, ...rest } = params;
|
|
126
171
|
return this.call("updateProjectTask", {
|
|
127
|
-
projectId: this.
|
|
128
|
-
...
|
|
172
|
+
projectId: this.resolveProjectId(projectId),
|
|
173
|
+
...rest
|
|
129
174
|
});
|
|
130
175
|
}
|
|
131
176
|
// ── Reviewers & Members ─────────────────────────────────────────────
|
|
132
177
|
addReviewer(params) {
|
|
178
|
+
const { projectId, ...rest } = params;
|
|
133
179
|
return this.call("addProjectTaskReviewer", {
|
|
134
|
-
projectId: this.
|
|
135
|
-
...
|
|
180
|
+
projectId: this.resolveProjectId(projectId),
|
|
181
|
+
...rest
|
|
136
182
|
});
|
|
137
183
|
}
|
|
138
184
|
removeReviewer(params) {
|
|
185
|
+
const { projectId, ...rest } = params;
|
|
139
186
|
return this.call("removeProjectTaskReviewer", {
|
|
140
|
-
projectId: this.
|
|
141
|
-
...
|
|
187
|
+
projectId: this.resolveProjectId(projectId),
|
|
188
|
+
...rest
|
|
142
189
|
});
|
|
143
190
|
}
|
|
144
|
-
listProjectMembers() {
|
|
191
|
+
listProjectMembers(projectId) {
|
|
145
192
|
return this.call("listProjectMembers", {
|
|
146
|
-
projectId: this.
|
|
193
|
+
projectId: this.resolveProjectId(projectId)
|
|
147
194
|
});
|
|
148
195
|
}
|
|
196
|
+
async listProjects() {
|
|
197
|
+
const response = await this.call("listAccessibleProjects", { pageSize: 100 });
|
|
198
|
+
return this.normalizeProjectList(response);
|
|
199
|
+
}
|
|
149
200
|
// ── Build Management ────────────────────────────────────────────────
|
|
150
|
-
startBuild(taskId) {
|
|
201
|
+
startBuild(taskId, projectId) {
|
|
151
202
|
return this.call("startProjectBuild", {
|
|
152
|
-
projectId: this.
|
|
203
|
+
projectId: this.resolveProjectId(projectId),
|
|
153
204
|
taskId
|
|
154
205
|
});
|
|
155
206
|
}
|
|
156
|
-
stopBuild(taskId) {
|
|
207
|
+
stopBuild(taskId, projectId) {
|
|
157
208
|
return this.call("stopProjectBuild", {
|
|
158
|
-
projectId: this.
|
|
209
|
+
projectId: this.resolveProjectId(projectId),
|
|
159
210
|
taskId
|
|
160
211
|
});
|
|
161
212
|
}
|
|
162
|
-
getBuildStatus(taskId) {
|
|
213
|
+
getBuildStatus(taskId, projectId) {
|
|
163
214
|
return this.call("getProjectTask", {
|
|
164
|
-
projectId: this.
|
|
215
|
+
projectId: this.resolveProjectId(projectId),
|
|
165
216
|
taskId
|
|
166
217
|
}).then((task) => ({
|
|
167
218
|
session: task?.session ?? null
|
|
168
219
|
}));
|
|
169
220
|
}
|
|
221
|
+
getWorkspaceAttachInfo(taskId, sshPublicKey) {
|
|
222
|
+
return this.callService("cloudBuildService", "getWorkspaceAttachInfo", {
|
|
223
|
+
taskId,
|
|
224
|
+
sshPublicKey
|
|
225
|
+
});
|
|
226
|
+
}
|
|
170
227
|
// ── Chat ────────────────────────────────────────────────────────────
|
|
171
|
-
getTaskChat(taskId, limit) {
|
|
228
|
+
getTaskChat(taskId, limit, projectId) {
|
|
172
229
|
return this.call("getProjectTask", {
|
|
173
|
-
projectId: this.
|
|
230
|
+
projectId: this.resolveProjectId(projectId),
|
|
174
231
|
taskId
|
|
175
232
|
}).then((task) => {
|
|
176
233
|
const messages = task?.chatMessages ?? [];
|
|
177
234
|
return limit ? messages.slice(-limit) : messages;
|
|
178
235
|
});
|
|
179
236
|
}
|
|
180
|
-
postToTaskChat(taskId, content) {
|
|
237
|
+
postToTaskChat(taskId, content, projectId) {
|
|
181
238
|
return this.call("postToProjectTaskChat", {
|
|
182
|
-
projectId: this.
|
|
239
|
+
projectId: this.resolveProjectId(projectId),
|
|
183
240
|
taskId,
|
|
184
241
|
content
|
|
185
242
|
});
|
|
186
243
|
}
|
|
187
244
|
// ── CLI History ─────────────────────────────────────────────────────
|
|
188
|
-
getTaskCli(taskId, limit, source) {
|
|
245
|
+
getTaskCli(taskId, limit, source, projectId) {
|
|
189
246
|
return this.call("getProjectTaskCli", {
|
|
190
|
-
projectId: this.
|
|
247
|
+
projectId: this.resolveProjectId(projectId),
|
|
191
248
|
taskId,
|
|
192
249
|
limit,
|
|
193
250
|
source
|
|
194
251
|
});
|
|
195
252
|
}
|
|
196
253
|
// ── Project Info ────────────────────────────────────────────────────
|
|
197
|
-
listTags() {
|
|
254
|
+
listTags(projectId) {
|
|
198
255
|
return this.call("listProjectTags", {
|
|
199
|
-
projectId: this.
|
|
256
|
+
projectId: this.resolveProjectId(projectId)
|
|
200
257
|
});
|
|
201
258
|
}
|
|
202
|
-
getProjectSummary() {
|
|
259
|
+
getProjectSummary(projectId) {
|
|
203
260
|
return this.call("getProjectSummary", {
|
|
204
|
-
projectId: this.
|
|
261
|
+
projectId: this.resolveProjectId(projectId)
|
|
205
262
|
});
|
|
206
263
|
}
|
|
207
264
|
// ── Review Flow ─────────────────────────────────────────────────────
|
|
208
|
-
async approveTask(taskId) {
|
|
265
|
+
async approveTask(taskId, projectId) {
|
|
266
|
+
const targetProjectId = this.resolveProjectId(projectId);
|
|
209
267
|
const task = await this.call("getProjectTask", {
|
|
210
|
-
projectId:
|
|
268
|
+
projectId: targetProjectId,
|
|
211
269
|
taskId
|
|
212
270
|
});
|
|
213
271
|
if (!task) throw new Error("Task not found");
|
|
214
272
|
const nextStatus = task.status === "ReviewPR" ? "ReviewDev" : "Complete";
|
|
215
|
-
const result = await this.updateTask({
|
|
273
|
+
const result = await this.updateTask({
|
|
274
|
+
projectId: targetProjectId,
|
|
275
|
+
taskId,
|
|
276
|
+
status: nextStatus
|
|
277
|
+
});
|
|
216
278
|
return { status: result.status };
|
|
217
279
|
}
|
|
218
|
-
async requestChanges(taskId, feedback) {
|
|
219
|
-
|
|
220
|
-
await this.
|
|
280
|
+
async requestChanges(taskId, feedback, projectId) {
|
|
281
|
+
const targetProjectId = this.resolveProjectId(projectId);
|
|
282
|
+
await this.postToTaskChat(taskId, feedback, targetProjectId);
|
|
283
|
+
await this.updateTask({ projectId: targetProjectId, taskId, status: "InProgress" });
|
|
221
284
|
}
|
|
222
|
-
approveAndMergePR(childTaskId) {
|
|
285
|
+
approveAndMergePR(childTaskId, projectId) {
|
|
223
286
|
return this.call("approveProjectMergePR", {
|
|
224
|
-
projectId: this.
|
|
287
|
+
projectId: this.resolveProjectId(projectId),
|
|
225
288
|
childTaskId
|
|
226
289
|
});
|
|
227
290
|
}
|
|
228
291
|
// ── File Attachments ────────────────────────────────────────────────
|
|
229
|
-
listTaskFiles(taskId) {
|
|
292
|
+
listTaskFiles(taskId, projectId) {
|
|
230
293
|
return this.call("listProjectTaskFiles", {
|
|
231
|
-
projectId: this.
|
|
294
|
+
projectId: this.resolveProjectId(projectId),
|
|
232
295
|
taskId
|
|
233
296
|
});
|
|
234
297
|
}
|
|
235
298
|
getAttachment(taskId, fileId, opts) {
|
|
236
299
|
const payload = {
|
|
237
|
-
projectId: this.
|
|
300
|
+
projectId: this.resolveProjectId(opts?.projectId),
|
|
238
301
|
taskId,
|
|
239
302
|
fileId
|
|
240
303
|
};
|
|
@@ -243,15 +306,16 @@ var ConveyorConnection = class {
|
|
|
243
306
|
return this.call("getProjectAttachment", payload);
|
|
244
307
|
}
|
|
245
308
|
requestFileUpload(taskId, params) {
|
|
309
|
+
const { projectId, ...rest } = params;
|
|
246
310
|
return this.call("requestProjectFileUpload", {
|
|
247
|
-
projectId: this.
|
|
311
|
+
projectId: this.resolveProjectId(projectId),
|
|
248
312
|
taskId,
|
|
249
|
-
...
|
|
313
|
+
...rest
|
|
250
314
|
});
|
|
251
315
|
}
|
|
252
|
-
confirmFileUpload(taskId, fileId, comment) {
|
|
316
|
+
confirmFileUpload(taskId, fileId, comment, projectId) {
|
|
253
317
|
const payload = {
|
|
254
|
-
projectId: this.
|
|
318
|
+
projectId: this.resolveProjectId(projectId),
|
|
255
319
|
taskId,
|
|
256
320
|
fileId
|
|
257
321
|
};
|
|
@@ -259,80 +323,90 @@ var ConveyorConnection = class {
|
|
|
259
323
|
return this.call("confirmProjectFileUpload", payload, 3e4);
|
|
260
324
|
}
|
|
261
325
|
// ── Releases ────────────────────────────────────────────────────────
|
|
262
|
-
createRelease(taskIds) {
|
|
263
|
-
return this.call(
|
|
326
|
+
createRelease(taskIds, projectId) {
|
|
327
|
+
return this.call(
|
|
328
|
+
"createProjectRelease",
|
|
329
|
+
{ projectId: this.resolveProjectId(projectId), taskIds },
|
|
330
|
+
45e3
|
|
331
|
+
);
|
|
264
332
|
}
|
|
265
333
|
// ── Pull Requests ───────────────────────────────────────────────────
|
|
266
334
|
createPullRequest(params) {
|
|
335
|
+
const { projectId, ...rest } = params;
|
|
267
336
|
return this.call(
|
|
268
337
|
"createProjectPullRequest",
|
|
269
|
-
{ projectId: this.
|
|
338
|
+
{ projectId: this.resolveProjectId(projectId), ...rest },
|
|
270
339
|
45e3
|
|
271
340
|
);
|
|
272
341
|
}
|
|
273
342
|
// ── Subtasks ────────────────────────────────────────────────────────
|
|
274
343
|
createSubtask(params) {
|
|
344
|
+
const { projectId, ...rest } = params;
|
|
275
345
|
return this.call("createProjectSubtask", {
|
|
276
|
-
projectId: this.
|
|
277
|
-
...
|
|
346
|
+
projectId: this.resolveProjectId(projectId),
|
|
347
|
+
...rest
|
|
278
348
|
});
|
|
279
349
|
}
|
|
280
350
|
updateSubtask(params) {
|
|
351
|
+
const { projectId, ...rest } = params;
|
|
281
352
|
return this.call("updateProjectSubtask", {
|
|
282
|
-
projectId: this.
|
|
283
|
-
...
|
|
353
|
+
projectId: this.resolveProjectId(projectId),
|
|
354
|
+
...rest
|
|
284
355
|
});
|
|
285
356
|
}
|
|
286
|
-
listSubtasks(taskId) {
|
|
357
|
+
listSubtasks(taskId, projectId) {
|
|
287
358
|
return this.call("listProjectSubtasks", {
|
|
288
|
-
projectId: this.
|
|
359
|
+
projectId: this.resolveProjectId(projectId),
|
|
289
360
|
taskId
|
|
290
361
|
});
|
|
291
362
|
}
|
|
292
|
-
deleteSubtask(subtaskId) {
|
|
363
|
+
deleteSubtask(subtaskId, projectId) {
|
|
293
364
|
return this.call("deleteProjectSubtask", {
|
|
294
|
-
projectId: this.
|
|
365
|
+
projectId: this.resolveProjectId(projectId),
|
|
295
366
|
subtaskId
|
|
296
367
|
});
|
|
297
368
|
}
|
|
298
369
|
// ── Dependencies ────────────────────────────────────────────────────
|
|
299
|
-
getDependencies(taskId) {
|
|
370
|
+
getDependencies(taskId, projectId) {
|
|
300
371
|
return this.call("getProjectTaskDependencies", {
|
|
301
|
-
projectId: this.
|
|
372
|
+
projectId: this.resolveProjectId(projectId),
|
|
302
373
|
taskId
|
|
303
374
|
});
|
|
304
375
|
}
|
|
305
376
|
addDependency(params) {
|
|
377
|
+
const { projectId, ...rest } = params;
|
|
306
378
|
return this.call("addProjectTaskDependency", {
|
|
307
|
-
projectId: this.
|
|
308
|
-
...
|
|
379
|
+
projectId: this.resolveProjectId(projectId),
|
|
380
|
+
...rest
|
|
309
381
|
});
|
|
310
382
|
}
|
|
311
383
|
removeDependency(params) {
|
|
384
|
+
const { projectId, ...rest } = params;
|
|
312
385
|
return this.call("removeProjectTaskDependency", {
|
|
313
|
-
projectId: this.
|
|
314
|
-
...
|
|
386
|
+
projectId: this.resolveProjectId(projectId),
|
|
387
|
+
...rest
|
|
315
388
|
});
|
|
316
389
|
}
|
|
317
390
|
// ── Manual Test Checklist ───────────────────────────────────────────
|
|
318
|
-
listManualTests(taskId) {
|
|
391
|
+
listManualTests(taskId, projectId) {
|
|
319
392
|
return this.call("listProjectManualTests", {
|
|
320
|
-
projectId: this.
|
|
393
|
+
projectId: this.resolveProjectId(projectId),
|
|
321
394
|
taskId
|
|
322
395
|
});
|
|
323
396
|
}
|
|
324
|
-
setManualTests(taskId, items) {
|
|
397
|
+
setManualTests(taskId, items, projectId) {
|
|
325
398
|
return this.call("setProjectManualTests", {
|
|
326
|
-
projectId: this.
|
|
399
|
+
projectId: this.resolveProjectId(projectId),
|
|
327
400
|
taskId,
|
|
328
401
|
items
|
|
329
402
|
});
|
|
330
403
|
}
|
|
331
404
|
// ── Suggestions ─────────────────────────────────────────────────────
|
|
332
405
|
createSuggestion(params) {
|
|
406
|
+
const { projectId, ...rest } = params;
|
|
333
407
|
return this.call("createProjectSuggestion", {
|
|
334
|
-
projectId: this.
|
|
335
|
-
...
|
|
408
|
+
projectId: this.resolveProjectId(projectId),
|
|
409
|
+
...rest
|
|
336
410
|
});
|
|
337
411
|
}
|
|
338
412
|
// ── PTY Tunnel Relay (reuses the S2 pty:* envelope) ─────────────────
|
|
@@ -387,4 +461,4 @@ var ConveyorConnection = class {
|
|
|
387
461
|
export {
|
|
388
462
|
ConveyorConnection
|
|
389
463
|
};
|
|
390
|
-
//# sourceMappingURL=chunk-
|
|
464
|
+
//# sourceMappingURL=chunk-Z566YAS7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/connection.ts"],"sourcesContent":["/* oxlint-disable max-lines -- central MCP socket client; split after service-call helpers are extracted */\nimport { io, type Socket } from \"socket.io-client\";\n\nexport interface ConveyorMcpConfig {\n apiUrl: string;\n projectToken: string;\n projectId?: string;\n}\n\n/** A single PTY output frame broadcast on the `pty:data` room event. */\nexport interface PtyDataChunk {\n sessionId: string;\n seq: number;\n data: string;\n cols?: number;\n rows?: number;\n}\n\n/** Ring-buffer snapshot returned by `ptyAttach` for catch-up replay. */\nexport interface PtyAttachSnapshot {\n sessionId: string;\n chunks: { seq: number; data: string }[];\n cols: number;\n rows: number;\n totalBytes: number;\n}\n\n/**\n * Result of `getActivePtySession`. `sessionId` is null until the cloud agent\n * has booted a PTY and produced at least one ring frame (readiness signal).\n */\nexport interface ActivePtySession {\n sessionId: string | null;\n cols?: number;\n rows?: number;\n}\n\nexport interface WorkspaceAttachInfo {\n taskId: string;\n sessionId: string;\n workspaceRoot: string;\n tunnelUrl: string;\n attachToken: string;\n expiresAt: string;\n previewPorts: Array<{ port: number; label: string }>;\n previewUrls: Record<string, string>;\n ssh?: {\n remotePort: number;\n preferredLocalPort: number;\n username: string;\n };\n}\n\ntype SocketCallback = (response: { success: boolean; data?: unknown; error?: string }) => void;\n\nconst NO_PROJECT_SELECTED_MESSAGE =\n \"No Conveyor project selected. Pass projectId to this tool or configure CONVEYOR_PROJECT_ID.\";\n\n/** Auth failures never recover on retry — match them to fail fast with guidance. */\nconst AUTH_ERROR_RE = /token|unauthor|forbidden|not authenticated|invalid auth/i;\n\n/**\n * Turn a raw server error into an actionable message. Most errors pass through\n * unchanged; the common-but-opaque \"Insufficient permissions\" gets the missing\n * context about why (project role too low) and how to fix it.\n */\nfunction enrichToolError(error?: string, fallback?: string): string {\n const base = error ?? fallback ?? \"Request failed\";\n if (/insufficient permissions/i.test(base)) {\n return (\n `${base}: your Conveyor project role can't perform this action. ` +\n `Creating/updating tasks, builds, and PRs requires Moderate access or higher — ` +\n `ask a project admin to raise your role.`\n );\n }\n return base;\n}\n\nexport class ConveyorConnection {\n private socket: Socket | null = null;\n private config: ConveyorMcpConfig;\n\n constructor(config: ConveyorMcpConfig) {\n this.config = config;\n }\n\n get projectId(): string {\n return this.resolveProjectId();\n }\n\n private resolveProjectId(projectId?: string): string {\n const resolved = projectId ?? this.config.projectId;\n if (!resolved) throw new Error(NO_PROJECT_SELECTED_MESSAGE);\n return resolved;\n }\n\n private normalizeProjectList(response: unknown): unknown[] {\n if (Array.isArray(response)) return response;\n if (typeof response !== \"object\" || response === null) return [];\n const record = response as Record<string, unknown>;\n if (Array.isArray(record.items)) return record.items;\n if (Array.isArray(record.projects)) return record.projects;\n if (Array.isArray(record.data)) return record.data;\n return [];\n }\n\n connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n let settled = false;\n let attempts = 0;\n const maxAttempts = 15;\n\n this.socket = io(this.config.apiUrl, {\n auth: {\n projectToken: this.config.projectToken,\n runnerMode: \"project\",\n },\n transports: [\"websocket\"],\n reconnection: true,\n reconnectionAttempts: Infinity,\n reconnectionDelay: 2000,\n reconnectionDelayMax: 30000,\n randomizationFactor: 0.3,\n extraHeaders: { \"ngrok-skip-browser-warning\": \"true\" },\n });\n\n this.socket.on(\"connect\", () => {\n if (!settled) {\n settled = true;\n // Subscribe to project room for events\n this.socket?.emit(\"projectService:subscribe\", { id: this.config.projectId });\n resolve();\n }\n });\n\n this.socket.on(\"connect_error\", (err) => {\n const message = err?.message ?? \"unknown error\";\n // An auth rejection (e.g. \"Invalid project token\") will never succeed on\n // retry, so fail fast with an actionable message instead of silently\n // retrying for ~30s and then dying with a generic error.\n if (!settled && AUTH_ERROR_RE.test(message)) {\n settled = true;\n this.socket?.close();\n reject(\n new Error(\n `Conveyor rejected the connection: ${message}. The project token is ` +\n `likely invalid or expired — regenerate it in the web app ` +\n `(User Settings → Connect Claude Code) and update CONVEYOR_USER_TOKEN ` +\n `(or legacy CONVEYOR_PROJECT_TOKEN).`,\n ),\n );\n return;\n }\n attempts++;\n if (!settled && attempts >= maxAttempts) {\n settled = true;\n reject(new Error(`Failed to connect to ${this.config.apiUrl}: ${message}`));\n }\n });\n });\n }\n\n // ── Service method call (agentSessionService:*) ─────────────────────\n\n private call<T>(method: string, data: unknown, timeoutMs = 15_000): Promise<T> {\n const socket = this.socket;\n if (!socket) throw new Error(\"Not connected\");\n\n const TIMEOUT_MS = timeoutMs;\n\n return Promise.race([\n new Promise<T>((resolve, reject) => {\n socket.emit(`agentSessionService:${method}`, data, ((response: {\n success: boolean;\n data?: T;\n error?: string;\n }) => {\n if (response.success) {\n resolve(response.data as T);\n } else {\n reject(new Error(enrichToolError(response.error, `${method} failed`)));\n }\n }) as SocketCallback);\n }),\n new Promise<never>((_, reject) => {\n setTimeout(() => {\n reject(new Error(`Request timed out: ${method}`));\n }, TIMEOUT_MS);\n }),\n ]);\n }\n\n /**\n * Fire-and-forget emit (no ack). The quickdraw-core server method handler\n * invokes the ack callback via optional chaining, so omitting it still runs\n * the full auth/schema/ACL pipeline — it just skips the response round-trip.\n * Used for high-frequency PTY input/resize so each keystroke does not arm a\n * 15s timeout timer.\n */\n private emit(method: string, data: unknown): void {\n const socket = this.socket;\n if (!socket) throw new Error(\"Not connected\");\n socket.emit(`agentSessionService:${method}`, data);\n }\n\n private callService<T>(\n serviceName: string,\n method: string,\n data: unknown,\n timeoutMs = 15_000,\n ): Promise<T> {\n const socket = this.socket;\n if (!socket) throw new Error(\"Not connected\");\n return Promise.race([\n new Promise<T>((resolve, reject) => {\n socket.emit(`${serviceName}:${method}`, data, ((response: {\n success: boolean;\n data?: T;\n error?: string;\n }) => {\n if (response.success) {\n resolve(response.data as T);\n } else {\n reject(new Error(enrichToolError(response.error, `${method} failed`)));\n }\n }) as SocketCallback);\n }),\n new Promise<never>((_, reject) => {\n setTimeout(() => {\n reject(new Error(`Request timed out: ${serviceName}:${method}`));\n }, timeoutMs);\n }),\n ]);\n }\n\n // ── Task Queries ────────────────────────────────────────────────────\n\n listTasks(params: {\n projectId?: string;\n status?: string;\n assigneeId?: string;\n unassigned?: boolean;\n limit?: number;\n }): Promise<unknown[]> {\n const { projectId, ...rest } = params;\n return this.call(\"listProjectTasks\", {\n projectId: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n getTask(taskId: string, projectId?: string): Promise<unknown> {\n return this.call(\"getProjectTask\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n });\n }\n\n getCardBySlug(slug: string, projectId?: string): Promise<unknown> {\n return this.call(\"getProjectTask\", {\n projectId: this.resolveProjectId(projectId),\n taskId: slug,\n });\n }\n\n searchTasks(params: {\n projectId?: string;\n tagNames?: string[];\n searchQuery?: string;\n statusFilters?: string[];\n assigneeId?: string;\n unassigned?: boolean;\n limit?: number;\n }): Promise<unknown[]> {\n const { projectId, ...rest } = params;\n return this.call(\"searchProjectTasks\", {\n projectId: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n // ── Task Mutations ──────────────────────────────────────────────────\n\n createTask(params: {\n projectId?: string;\n title: string;\n description?: string;\n plan?: string;\n status?: string;\n }): Promise<{ id: string; slug: string }> {\n const { projectId, ...rest } = params;\n return this.call(\"createProjectTask\", {\n projectId: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n updateTask(params: {\n projectId?: string;\n taskId: string;\n title?: string;\n description?: string;\n plan?: string;\n status?: string;\n assignedUserId?: string | null;\n }): Promise<{ id: string; status: string }> {\n const { projectId, ...rest } = params;\n return this.call(\"updateProjectTask\", {\n projectId: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n // ── Reviewers & Members ─────────────────────────────────────────────\n\n addReviewer(params: {\n projectId?: string;\n taskId: string;\n userId: string;\n }): Promise<{ taskId: string; reviewers: Array<{ userId: string; name: string | null }> }> {\n const { projectId, ...rest } = params;\n return this.call(\"addProjectTaskReviewer\", {\n projectId: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n removeReviewer(params: {\n projectId?: string;\n taskId: string;\n userId: string;\n }): Promise<{ taskId: string; reviewers: Array<{ userId: string; name: string | null }> }> {\n const { projectId, ...rest } = params;\n return this.call(\"removeProjectTaskReviewer\", {\n projectId: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n listProjectMembers(\n projectId?: string,\n ): Promise<Array<{ userId: string; name: string | null; email: string; level: string }>> {\n return this.call(\"listProjectMembers\", {\n projectId: this.resolveProjectId(projectId),\n });\n }\n\n async listProjects(): Promise<unknown[]> {\n const response = await this.call(\"listAccessibleProjects\", { pageSize: 100 });\n return this.normalizeProjectList(response);\n }\n\n // ── Build Management ────────────────────────────────────────────────\n\n startBuild(taskId: string, projectId?: string): Promise<{ taskId: string; status: string }> {\n return this.call(\"startProjectBuild\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n });\n }\n\n stopBuild(taskId: string, projectId?: string): Promise<{ taskId: string; stopped: boolean }> {\n return this.call(\"stopProjectBuild\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n });\n }\n\n getBuildStatus(\n taskId: string,\n projectId?: string,\n ): Promise<{\n session: { status: string | null; agentRunnerStatus: string | null } | null;\n }> {\n // Uses getProjectTask and extracts the session field\n return this.call<Record<string, unknown>>(\"getProjectTask\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n }).then((task) => ({\n session:\n (task?.session as {\n status: string | null;\n agentRunnerStatus: string | null;\n }) ?? null,\n }));\n }\n\n getWorkspaceAttachInfo(taskId: string, sshPublicKey?: string): Promise<WorkspaceAttachInfo> {\n return this.callService(\"cloudBuildService\", \"getWorkspaceAttachInfo\", {\n taskId,\n sshPublicKey,\n });\n }\n\n // ── Chat ────────────────────────────────────────────────────────────\n\n getTaskChat(taskId: string, limit?: number, projectId?: string): Promise<unknown[]> {\n // Uses getProjectTask and extracts chatMessages\n return this.call<Record<string, unknown>>(\"getProjectTask\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n }).then((task) => {\n const messages = (task?.chatMessages ?? []) as unknown[];\n return limit ? messages.slice(-limit) : messages;\n });\n }\n\n postToTaskChat(\n taskId: string,\n content: string,\n projectId?: string,\n ): Promise<{ messageId: string }> {\n return this.call(\"postToProjectTaskChat\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n content,\n });\n }\n\n // ── CLI History ─────────────────────────────────────────────────────\n\n getTaskCli(\n taskId: string,\n limit?: number,\n source?: string,\n projectId?: string,\n ): Promise<{ type: string; data: Record<string, unknown>; timestamp: string }[]> {\n return this.call(\"getProjectTaskCli\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n limit,\n source,\n });\n }\n\n // ── Project Info ────────────────────────────────────────────────────\n\n listTags(projectId?: string): Promise<{ id: string; name: string; color: string }[]> {\n return this.call(\"listProjectTags\", {\n projectId: this.resolveProjectId(projectId),\n });\n }\n\n getProjectSummary(projectId?: string): Promise<unknown> {\n return this.call(\"getProjectSummary\", {\n projectId: this.resolveProjectId(projectId),\n });\n }\n\n // ── Review Flow ─────────────────────────────────────────────────────\n\n async approveTask(taskId: string, projectId?: string): Promise<{ status: string }> {\n const targetProjectId = this.resolveProjectId(projectId);\n // Determine next status based on current status\n const task = (await this.call(\"getProjectTask\", {\n projectId: targetProjectId,\n taskId,\n })) as { status: string } | null;\n\n if (!task) throw new Error(\"Task not found\");\n\n const nextStatus = task.status === \"ReviewPR\" ? \"ReviewDev\" : \"Complete\";\n\n const result = await this.updateTask({\n projectId: targetProjectId,\n taskId,\n status: nextStatus,\n });\n return { status: result.status };\n }\n\n async requestChanges(taskId: string, feedback: string, projectId?: string): Promise<void> {\n const targetProjectId = this.resolveProjectId(projectId);\n // Post feedback to task chat then move to InProgress\n await this.postToTaskChat(taskId, feedback, targetProjectId);\n await this.updateTask({ projectId: targetProjectId, taskId, status: \"InProgress\" });\n }\n\n approveAndMergePR(\n childTaskId: string,\n projectId?: string,\n ): Promise<{ merged: boolean; childTaskId: string; prNumber: number }> {\n return this.call(\"approveProjectMergePR\", {\n projectId: this.resolveProjectId(projectId),\n childTaskId,\n });\n }\n\n // ── File Attachments ────────────────────────────────────────────────\n\n listTaskFiles(taskId: string, projectId?: string): Promise<unknown[]> {\n return this.call(\"listProjectTaskFiles\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n });\n }\n\n getAttachment(\n taskId: string,\n fileId: string,\n opts?: { offset?: number; maxBytes?: number; projectId?: string },\n ): Promise<unknown> {\n const payload: Record<string, unknown> = {\n projectId: this.resolveProjectId(opts?.projectId),\n taskId,\n fileId,\n };\n if (opts?.offset !== undefined) payload.offset = opts.offset;\n if (opts?.maxBytes !== undefined) payload.maxBytes = opts.maxBytes;\n return this.call(\"getProjectAttachment\", payload);\n }\n\n requestFileUpload(\n taskId: string,\n params: { fileName: string; mimeType: string; fileSize: number; projectId?: string },\n ): Promise<{ fileId: string; uploadUrl: string }> {\n const { projectId, ...rest } = params;\n return this.call(\"requestProjectFileUpload\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n ...rest,\n });\n }\n\n confirmFileUpload(\n taskId: string,\n fileId: string,\n comment?: string,\n projectId?: string,\n ): Promise<{ fileId: string; fileName: string; downloadUrl?: string; messageId?: string }> {\n const payload: Record<string, unknown> = {\n projectId: this.resolveProjectId(projectId),\n taskId,\n fileId,\n };\n if (comment !== undefined) payload.comment = comment;\n // Confirm verifies the object in GCS before marking it uploaded — allow\n // extra headroom for the storage round-trips.\n return this.call(\"confirmProjectFileUpload\", payload, 30_000);\n }\n\n // ── Releases ────────────────────────────────────────────────────────\n\n createRelease(\n taskIds?: string[],\n projectId?: string,\n ): Promise<{ taskId: string; version: string }> {\n // Full releases create the release branch + PR against GitHub synchronously;\n // allow the same headroom as createPullRequest.\n return this.call(\n \"createProjectRelease\",\n { projectId: this.resolveProjectId(projectId), taskIds },\n 45_000,\n );\n }\n\n // ── Pull Requests ───────────────────────────────────────────────────\n\n createPullRequest(params: {\n projectId?: string;\n taskId: string;\n title: string;\n body: string;\n head?: string;\n base?: string;\n }): Promise<{ prNumber: number; prUrl: string }> {\n const { projectId, ...rest } = params;\n // PR creation makes several sequential GitHub API calls (token, create,\n // existing-PR lookup); allow more headroom than the default request timeout.\n return this.call(\n \"createProjectPullRequest\",\n { projectId: this.resolveProjectId(projectId), ...rest },\n 45_000,\n );\n }\n\n // ── Subtasks ────────────────────────────────────────────────────────\n\n createSubtask(params: {\n projectId?: string;\n parentTaskId: string;\n title: string;\n description?: string;\n plan?: string;\n ordinal?: number;\n storyPointValue?: number;\n }): Promise<{ id: string; slug: string }> {\n const { projectId, ...rest } = params;\n return this.call(\"createProjectSubtask\", {\n projectId: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n updateSubtask(params: {\n projectId?: string;\n subtaskId: string;\n title?: string;\n description?: string;\n plan?: string;\n status?: string;\n ordinal?: number;\n storyPointValue?: number;\n }): Promise<{ id: string; status: string }> {\n const { projectId, ...rest } = params;\n return this.call(\"updateProjectSubtask\", {\n projectId: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n listSubtasks(taskId: string, projectId?: string): Promise<unknown[]> {\n return this.call(\"listProjectSubtasks\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n });\n }\n\n deleteSubtask(subtaskId: string, projectId?: string): Promise<{ deleted: boolean }> {\n return this.call(\"deleteProjectSubtask\", {\n projectId: this.resolveProjectId(projectId),\n subtaskId,\n });\n }\n\n // ── Dependencies ────────────────────────────────────────────────────\n\n getDependencies(taskId: string, projectId?: string): Promise<unknown[]> {\n return this.call(\"getProjectTaskDependencies\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n });\n }\n\n addDependency(params: {\n projectId?: string;\n taskId: string;\n dependsOnSlugOrId: string;\n }): Promise<{ success: boolean }> {\n const { projectId, ...rest } = params;\n return this.call(\"addProjectTaskDependency\", {\n projectId: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n removeDependency(params: {\n projectId?: string;\n taskId: string;\n dependsOnSlugOrId: string;\n }): Promise<{ success: boolean }> {\n const { projectId, ...rest } = params;\n return this.call(\"removeProjectTaskDependency\", {\n projectId: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n // ── Manual Test Checklist ───────────────────────────────────────────\n\n listManualTests(\n taskId: string,\n projectId?: string,\n ): Promise<\n Array<{\n id: string;\n type: string;\n title: string;\n ordinal: number;\n createdAt: string;\n checked: boolean;\n }>\n > {\n return this.call(\"listProjectManualTests\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n });\n }\n\n setManualTests(\n taskId: string,\n items: Array<{ title: string }>,\n projectId?: string,\n ): Promise<{ created: number; skipped: number }> {\n return this.call(\"setProjectManualTests\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n items,\n });\n }\n\n // ── Suggestions ─────────────────────────────────────────────────────\n\n createSuggestion(params: {\n projectId?: string;\n title: string;\n description?: string;\n tagNames?: string[];\n }): Promise<{ id: string; merged: boolean; mergedIntoId?: string }> {\n const { projectId, ...rest } = params;\n return this.call(\"createProjectSuggestion\", {\n projectId: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n // ── PTY Tunnel Relay (reuses the S2 pty:* envelope) ─────────────────\n\n /**\n * Poll target: returns the active cloud PTY session for a task once its ring\n * buffer has frames. `sessionId` is resolved server-side from `taskId` (never\n * accepted from the wire), preserving the one-active-session-per-task invariant.\n */\n getActivePtySession(taskId: string): Promise<ActivePtySession> {\n return this.call(\"getActivePtySession\", { taskId });\n }\n\n /** Fetch the ring-buffer snapshot for catch-up replay on (re)attach. */\n ptyAttach(sessionId: string): Promise<PtyAttachSnapshot> {\n return this.call(\"ptyAttach\", { sessionId });\n }\n\n /**\n * Join the session room so `pty:data` frames are delivered. Uses the standard\n * quickdraw-core subscribe envelope; \"Read\" is sufficient for output streaming.\n */\n subscribeToSession(sessionId: string): void {\n const socket = this.socket;\n if (!socket) throw new Error(\"Not connected\");\n socket.emit(\"agentSessionService:subscribe\", {\n entryId: sessionId,\n requiredLevel: \"Read\",\n });\n }\n\n /** Relay a stdin chunk to the cloud PTY (raw utf8, fire-and-forget). */\n ptyInput(sessionId: string, data: string): void {\n this.emit(\"ptyInput\", { sessionId, data });\n }\n\n /** Relay a terminal resize to the cloud PTY (fire-and-forget). */\n ptyResize(sessionId: string, cols: number, rows: number): void {\n this.emit(\"ptyResize\", { sessionId, cols, rows });\n }\n\n /** Subscribe to raw PTY output frames. Returns an unsubscribe function. */\n onPtyData(handler: (chunk: PtyDataChunk) => void): () => void {\n const socket = this.socket;\n if (!socket) throw new Error(\"Not connected\");\n socket.on(\"pty:data\", handler as (...args: unknown[]) => void);\n return () => {\n socket.off(\"pty:data\", handler as (...args: unknown[]) => void);\n };\n }\n\n // ── Connection lifecycle ────────────────────────────────────────────\n\n disconnect(): void {\n this.socket?.disconnect();\n this.socket = null;\n }\n}\n"],"mappings":"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","names":[]}
|