@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.
@@ -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;
@@ -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.config.projectId,
103
- ...params
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.config.projectId,
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.config.projectId,
115
- ...params
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.config.projectId,
122
- ...params
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.config.projectId,
128
- ...params
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.config.projectId,
135
- ...params
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.config.projectId,
141
- ...params
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.config.projectId
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.config.projectId,
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.config.projectId,
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.config.projectId,
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.config.projectId,
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.config.projectId,
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.config.projectId,
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.config.projectId
256
+ projectId: this.resolveProjectId(projectId)
200
257
  });
201
258
  }
202
- getProjectSummary() {
259
+ getProjectSummary(projectId) {
203
260
  return this.call("getProjectSummary", {
204
- projectId: this.config.projectId
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: this.config.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({ taskId, status: nextStatus });
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
- await this.postToTaskChat(taskId, feedback);
220
- 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" });
221
284
  }
222
- approveAndMergePR(childTaskId) {
285
+ approveAndMergePR(childTaskId, projectId) {
223
286
  return this.call("approveProjectMergePR", {
224
- projectId: this.config.projectId,
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.config.projectId,
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.config.projectId,
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.config.projectId,
311
+ projectId: this.resolveProjectId(projectId),
248
312
  taskId,
249
- ...params
313
+ ...rest
250
314
  });
251
315
  }
252
- confirmFileUpload(taskId, fileId, comment) {
316
+ confirmFileUpload(taskId, fileId, comment, projectId) {
253
317
  const payload = {
254
- projectId: this.config.projectId,
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("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
+ );
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.config.projectId, ...params },
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.config.projectId,
277
- ...params
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.config.projectId,
283
- ...params
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.config.projectId,
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.config.projectId,
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.config.projectId,
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.config.projectId,
308
- ...params
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.config.projectId,
314
- ...params
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.config.projectId,
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.config.projectId,
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.config.projectId,
335
- ...params
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-OAHSTMYM.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":[]}