@rallycry/conveyor-mcp 3.4.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.
@@ -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.config.projectId;
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;
@@ -118,70 +133,86 @@ var ConveyorConnection = class {
118
133
  }
119
134
  // ── Task Queries ────────────────────────────────────────────────────
120
135
  listTasks(params) {
136
+ const { projectId, ...rest } = params;
121
137
  return this.call("listProjectTasks", {
122
- projectId: this.config.projectId,
123
- ...params
138
+ projectId: this.resolveProjectId(projectId),
139
+ ...rest
124
140
  });
125
141
  }
126
- getTask(taskId) {
142
+ getTask(taskId, projectId) {
127
143
  return this.call("getProjectTask", {
128
- projectId: this.config.projectId,
144
+ projectId: this.resolveProjectId(projectId),
129
145
  taskId
130
146
  });
131
147
  }
148
+ getCardBySlug(slug, projectId) {
149
+ return this.call("getProjectTask", {
150
+ projectId: this.resolveProjectId(projectId),
151
+ taskId: slug
152
+ });
153
+ }
132
154
  searchTasks(params) {
155
+ const { projectId, ...rest } = params;
133
156
  return this.call("searchProjectTasks", {
134
- projectId: this.config.projectId,
135
- ...params
157
+ projectId: this.resolveProjectId(projectId),
158
+ ...rest
136
159
  });
137
160
  }
138
161
  // ── Task Mutations ──────────────────────────────────────────────────
139
162
  createTask(params) {
163
+ const { projectId, ...rest } = params;
140
164
  return this.call("createProjectTask", {
141
- projectId: this.config.projectId,
142
- ...params
165
+ projectId: this.resolveProjectId(projectId),
166
+ ...rest
143
167
  });
144
168
  }
145
169
  updateTask(params) {
170
+ const { projectId, ...rest } = params;
146
171
  return this.call("updateProjectTask", {
147
- projectId: this.config.projectId,
148
- ...params
172
+ projectId: this.resolveProjectId(projectId),
173
+ ...rest
149
174
  });
150
175
  }
151
176
  // ── Reviewers & Members ─────────────────────────────────────────────
152
177
  addReviewer(params) {
178
+ const { projectId, ...rest } = params;
153
179
  return this.call("addProjectTaskReviewer", {
154
- projectId: this.config.projectId,
155
- ...params
180
+ projectId: this.resolveProjectId(projectId),
181
+ ...rest
156
182
  });
157
183
  }
158
184
  removeReviewer(params) {
185
+ const { projectId, ...rest } = params;
159
186
  return this.call("removeProjectTaskReviewer", {
160
- projectId: this.config.projectId,
161
- ...params
187
+ projectId: this.resolveProjectId(projectId),
188
+ ...rest
162
189
  });
163
190
  }
164
- listProjectMembers() {
191
+ listProjectMembers(projectId) {
165
192
  return this.call("listProjectMembers", {
166
- projectId: this.config.projectId
193
+ projectId: this.resolveProjectId(projectId)
167
194
  });
168
195
  }
196
+ async listProjects() {
197
+ const response = await this.call("listAccessibleProjects", { pageSize: 100 });
198
+ return this.normalizeProjectList(response);
199
+ }
169
200
  // ── Build Management ────────────────────────────────────────────────
170
- startBuild(taskId) {
201
+ startBuild(taskId, projectId) {
171
202
  return this.call("startProjectBuild", {
172
- projectId: this.config.projectId,
203
+ projectId: this.resolveProjectId(projectId),
173
204
  taskId
174
205
  });
175
206
  }
176
- stopBuild(taskId) {
207
+ stopBuild(taskId, projectId) {
177
208
  return this.call("stopProjectBuild", {
178
- projectId: this.config.projectId,
209
+ projectId: this.resolveProjectId(projectId),
179
210
  taskId
180
211
  });
181
212
  }
182
- getBuildStatus(taskId) {
213
+ getBuildStatus(taskId, projectId) {
183
214
  return this.call("getProjectTask", {
184
- projectId: this.config.projectId,
215
+ projectId: this.resolveProjectId(projectId),
185
216
  taskId
186
217
  }).then((task) => ({
187
218
  session: task?.session ?? null
@@ -194,73 +225,79 @@ var ConveyorConnection = class {
194
225
  });
195
226
  }
196
227
  // ── Chat ────────────────────────────────────────────────────────────
197
- getTaskChat(taskId, limit) {
228
+ getTaskChat(taskId, limit, projectId) {
198
229
  return this.call("getProjectTask", {
199
- projectId: this.config.projectId,
230
+ projectId: this.resolveProjectId(projectId),
200
231
  taskId
201
232
  }).then((task) => {
202
233
  const messages = task?.chatMessages ?? [];
203
234
  return limit ? messages.slice(-limit) : messages;
204
235
  });
205
236
  }
206
- postToTaskChat(taskId, content) {
237
+ postToTaskChat(taskId, content, projectId) {
207
238
  return this.call("postToProjectTaskChat", {
208
- projectId: this.config.projectId,
239
+ projectId: this.resolveProjectId(projectId),
209
240
  taskId,
210
241
  content
211
242
  });
212
243
  }
213
244
  // ── CLI History ─────────────────────────────────────────────────────
214
- getTaskCli(taskId, limit, source) {
245
+ getTaskCli(taskId, limit, source, projectId) {
215
246
  return this.call("getProjectTaskCli", {
216
- projectId: this.config.projectId,
247
+ projectId: this.resolveProjectId(projectId),
217
248
  taskId,
218
249
  limit,
219
250
  source
220
251
  });
221
252
  }
222
253
  // ── Project Info ────────────────────────────────────────────────────
223
- listTags() {
254
+ listTags(projectId) {
224
255
  return this.call("listProjectTags", {
225
- projectId: this.config.projectId
256
+ projectId: this.resolveProjectId(projectId)
226
257
  });
227
258
  }
228
- getProjectSummary() {
259
+ getProjectSummary(projectId) {
229
260
  return this.call("getProjectSummary", {
230
- projectId: this.config.projectId
261
+ projectId: this.resolveProjectId(projectId)
231
262
  });
232
263
  }
233
264
  // ── Review Flow ─────────────────────────────────────────────────────
234
- async approveTask(taskId) {
265
+ async approveTask(taskId, projectId) {
266
+ const targetProjectId = this.resolveProjectId(projectId);
235
267
  const task = await this.call("getProjectTask", {
236
- projectId: this.config.projectId,
268
+ projectId: targetProjectId,
237
269
  taskId
238
270
  });
239
271
  if (!task) throw new Error("Task not found");
240
272
  const nextStatus = task.status === "ReviewPR" ? "ReviewDev" : "Complete";
241
- const result = await this.updateTask({ taskId, status: nextStatus });
273
+ const result = await this.updateTask({
274
+ projectId: targetProjectId,
275
+ taskId,
276
+ status: nextStatus
277
+ });
242
278
  return { status: result.status };
243
279
  }
244
- async requestChanges(taskId, feedback) {
245
- await this.postToTaskChat(taskId, feedback);
246
- await this.updateTask({ taskId, status: "InProgress" });
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" });
247
284
  }
248
- approveAndMergePR(childTaskId) {
285
+ approveAndMergePR(childTaskId, projectId) {
249
286
  return this.call("approveProjectMergePR", {
250
- projectId: this.config.projectId,
287
+ projectId: this.resolveProjectId(projectId),
251
288
  childTaskId
252
289
  });
253
290
  }
254
291
  // ── File Attachments ────────────────────────────────────────────────
255
- listTaskFiles(taskId) {
292
+ listTaskFiles(taskId, projectId) {
256
293
  return this.call("listProjectTaskFiles", {
257
- projectId: this.config.projectId,
294
+ projectId: this.resolveProjectId(projectId),
258
295
  taskId
259
296
  });
260
297
  }
261
298
  getAttachment(taskId, fileId, opts) {
262
299
  const payload = {
263
- projectId: this.config.projectId,
300
+ projectId: this.resolveProjectId(opts?.projectId),
264
301
  taskId,
265
302
  fileId
266
303
  };
@@ -269,15 +306,16 @@ var ConveyorConnection = class {
269
306
  return this.call("getProjectAttachment", payload);
270
307
  }
271
308
  requestFileUpload(taskId, params) {
309
+ const { projectId, ...rest } = params;
272
310
  return this.call("requestProjectFileUpload", {
273
- projectId: this.config.projectId,
311
+ projectId: this.resolveProjectId(projectId),
274
312
  taskId,
275
- ...params
313
+ ...rest
276
314
  });
277
315
  }
278
- confirmFileUpload(taskId, fileId, comment) {
316
+ confirmFileUpload(taskId, fileId, comment, projectId) {
279
317
  const payload = {
280
- projectId: this.config.projectId,
318
+ projectId: this.resolveProjectId(projectId),
281
319
  taskId,
282
320
  fileId
283
321
  };
@@ -285,80 +323,90 @@ var ConveyorConnection = class {
285
323
  return this.call("confirmProjectFileUpload", payload, 3e4);
286
324
  }
287
325
  // ── Releases ────────────────────────────────────────────────────────
288
- createRelease(taskIds) {
289
- return this.call("createProjectRelease", { projectId: this.config.projectId, taskIds }, 45e3);
326
+ createRelease(taskIds, projectId) {
327
+ return this.call(
328
+ "createProjectRelease",
329
+ { projectId: this.resolveProjectId(projectId), taskIds },
330
+ 45e3
331
+ );
290
332
  }
291
333
  // ── Pull Requests ───────────────────────────────────────────────────
292
334
  createPullRequest(params) {
335
+ const { projectId, ...rest } = params;
293
336
  return this.call(
294
337
  "createProjectPullRequest",
295
- { projectId: this.config.projectId, ...params },
338
+ { projectId: this.resolveProjectId(projectId), ...rest },
296
339
  45e3
297
340
  );
298
341
  }
299
342
  // ── Subtasks ────────────────────────────────────────────────────────
300
343
  createSubtask(params) {
344
+ const { projectId, ...rest } = params;
301
345
  return this.call("createProjectSubtask", {
302
- projectId: this.config.projectId,
303
- ...params
346
+ projectId: this.resolveProjectId(projectId),
347
+ ...rest
304
348
  });
305
349
  }
306
350
  updateSubtask(params) {
351
+ const { projectId, ...rest } = params;
307
352
  return this.call("updateProjectSubtask", {
308
- projectId: this.config.projectId,
309
- ...params
353
+ projectId: this.resolveProjectId(projectId),
354
+ ...rest
310
355
  });
311
356
  }
312
- listSubtasks(taskId) {
357
+ listSubtasks(taskId, projectId) {
313
358
  return this.call("listProjectSubtasks", {
314
- projectId: this.config.projectId,
359
+ projectId: this.resolveProjectId(projectId),
315
360
  taskId
316
361
  });
317
362
  }
318
- deleteSubtask(subtaskId) {
363
+ deleteSubtask(subtaskId, projectId) {
319
364
  return this.call("deleteProjectSubtask", {
320
- projectId: this.config.projectId,
365
+ projectId: this.resolveProjectId(projectId),
321
366
  subtaskId
322
367
  });
323
368
  }
324
369
  // ── Dependencies ────────────────────────────────────────────────────
325
- getDependencies(taskId) {
370
+ getDependencies(taskId, projectId) {
326
371
  return this.call("getProjectTaskDependencies", {
327
- projectId: this.config.projectId,
372
+ projectId: this.resolveProjectId(projectId),
328
373
  taskId
329
374
  });
330
375
  }
331
376
  addDependency(params) {
377
+ const { projectId, ...rest } = params;
332
378
  return this.call("addProjectTaskDependency", {
333
- projectId: this.config.projectId,
334
- ...params
379
+ projectId: this.resolveProjectId(projectId),
380
+ ...rest
335
381
  });
336
382
  }
337
383
  removeDependency(params) {
384
+ const { projectId, ...rest } = params;
338
385
  return this.call("removeProjectTaskDependency", {
339
- projectId: this.config.projectId,
340
- ...params
386
+ projectId: this.resolveProjectId(projectId),
387
+ ...rest
341
388
  });
342
389
  }
343
390
  // ── Manual Test Checklist ───────────────────────────────────────────
344
- listManualTests(taskId) {
391
+ listManualTests(taskId, projectId) {
345
392
  return this.call("listProjectManualTests", {
346
- projectId: this.config.projectId,
393
+ projectId: this.resolveProjectId(projectId),
347
394
  taskId
348
395
  });
349
396
  }
350
- setManualTests(taskId, items) {
397
+ setManualTests(taskId, items, projectId) {
351
398
  return this.call("setProjectManualTests", {
352
- projectId: this.config.projectId,
399
+ projectId: this.resolveProjectId(projectId),
353
400
  taskId,
354
401
  items
355
402
  });
356
403
  }
357
404
  // ── Suggestions ─────────────────────────────────────────────────────
358
405
  createSuggestion(params) {
406
+ const { projectId, ...rest } = params;
359
407
  return this.call("createProjectSuggestion", {
360
- projectId: this.config.projectId,
361
- ...params
408
+ projectId: this.resolveProjectId(projectId),
409
+ ...rest
362
410
  });
363
411
  }
364
412
  // ── PTY Tunnel Relay (reuses the S2 pty:* envelope) ─────────────────
@@ -413,4 +461,4 @@ var ConveyorConnection = class {
413
461
  export {
414
462
  ConveyorConnection
415
463
  };
416
- //# sourceMappingURL=chunk-2DPMMT6S.js.map
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":[]}