@rallycry/conveyor-mcp 3.4.0 → 3.6.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-2DPMMT6S.js → chunk-VGAKBJ2O.js} +136 -73
- package/dist/chunk-VGAKBJ2O.js.map +1 -0
- package/dist/cli.js +274 -166
- 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 +51 -22
- package/package.json +1 -1
- package/dist/chunk-2DPMMT6S.js.map +0 -1
package/dist/tunnel.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
interface ConveyorMcpConfig {
|
|
2
2
|
apiUrl: string;
|
|
3
3
|
projectToken: string;
|
|
4
|
-
projectId
|
|
4
|
+
projectId?: string;
|
|
5
5
|
}
|
|
6
6
|
/** A single PTY output frame broadcast on the `pty:data` room event. */
|
|
7
7
|
interface PtyDataChunk {
|
|
@@ -54,6 +54,8 @@ declare class ConveyorConnection {
|
|
|
54
54
|
private config;
|
|
55
55
|
constructor(config: ConveyorMcpConfig);
|
|
56
56
|
get projectId(): string;
|
|
57
|
+
private resolveProjectId;
|
|
58
|
+
private normalizeProjectList;
|
|
57
59
|
connect(): Promise<void>;
|
|
58
60
|
private call;
|
|
59
61
|
/**
|
|
@@ -66,13 +68,16 @@ declare class ConveyorConnection {
|
|
|
66
68
|
private emit;
|
|
67
69
|
private callService;
|
|
68
70
|
listTasks(params: {
|
|
71
|
+
projectId?: string;
|
|
69
72
|
status?: string;
|
|
70
73
|
assigneeId?: string;
|
|
71
74
|
unassigned?: boolean;
|
|
72
75
|
limit?: number;
|
|
73
76
|
}): Promise<unknown[]>;
|
|
74
|
-
getTask(taskId: string): Promise<unknown>;
|
|
77
|
+
getTask(taskId: string, projectId?: string): Promise<unknown>;
|
|
78
|
+
getCardBySlug(slug: string, projectId?: string): Promise<unknown>;
|
|
75
79
|
searchTasks(params: {
|
|
80
|
+
projectId?: string;
|
|
76
81
|
tagNames?: string[];
|
|
77
82
|
searchQuery?: string;
|
|
78
83
|
statusFilters?: string[];
|
|
@@ -81,6 +86,7 @@ declare class ConveyorConnection {
|
|
|
81
86
|
limit?: number;
|
|
82
87
|
}): Promise<unknown[]>;
|
|
83
88
|
createTask(params: {
|
|
89
|
+
projectId?: string;
|
|
84
90
|
title: string;
|
|
85
91
|
description?: string;
|
|
86
92
|
plan?: string;
|
|
@@ -90,6 +96,7 @@ declare class ConveyorConnection {
|
|
|
90
96
|
slug: string;
|
|
91
97
|
}>;
|
|
92
98
|
updateTask(params: {
|
|
99
|
+
projectId?: string;
|
|
93
100
|
taskId: string;
|
|
94
101
|
title?: string;
|
|
95
102
|
description?: string;
|
|
@@ -101,6 +108,7 @@ declare class ConveyorConnection {
|
|
|
101
108
|
status: string;
|
|
102
109
|
}>;
|
|
103
110
|
addReviewer(params: {
|
|
111
|
+
projectId?: string;
|
|
104
112
|
taskId: string;
|
|
105
113
|
userId: string;
|
|
106
114
|
}): Promise<{
|
|
@@ -111,6 +119,7 @@ declare class ConveyorConnection {
|
|
|
111
119
|
}>;
|
|
112
120
|
}>;
|
|
113
121
|
removeReviewer(params: {
|
|
122
|
+
projectId?: string;
|
|
114
123
|
taskId: string;
|
|
115
124
|
userId: string;
|
|
116
125
|
}): Promise<{
|
|
@@ -120,75 +129,79 @@ declare class ConveyorConnection {
|
|
|
120
129
|
name: string | null;
|
|
121
130
|
}>;
|
|
122
131
|
}>;
|
|
123
|
-
listProjectMembers(): Promise<Array<{
|
|
132
|
+
listProjectMembers(projectId?: string): Promise<Array<{
|
|
124
133
|
userId: string;
|
|
125
134
|
name: string | null;
|
|
126
135
|
email: string;
|
|
127
136
|
level: string;
|
|
128
137
|
}>>;
|
|
129
|
-
|
|
138
|
+
listProjects(): Promise<unknown[]>;
|
|
139
|
+
startBuild(taskId: string, projectId?: string): Promise<{
|
|
130
140
|
taskId: string;
|
|
131
141
|
status: string;
|
|
132
142
|
}>;
|
|
133
|
-
stopBuild(taskId: string): Promise<{
|
|
143
|
+
stopBuild(taskId: string, projectId?: string): Promise<{
|
|
134
144
|
taskId: string;
|
|
135
145
|
stopped: boolean;
|
|
136
146
|
}>;
|
|
137
|
-
getBuildStatus(taskId: string): Promise<{
|
|
147
|
+
getBuildStatus(taskId: string, projectId?: string): Promise<{
|
|
138
148
|
session: {
|
|
139
149
|
status: string | null;
|
|
140
150
|
agentRunnerStatus: string | null;
|
|
141
151
|
} | null;
|
|
142
152
|
}>;
|
|
143
153
|
getWorkspaceAttachInfo(taskId: string, sshPublicKey?: string): Promise<WorkspaceAttachInfo>;
|
|
144
|
-
getTaskChat(taskId: string, limit?: number): Promise<unknown[]>;
|
|
145
|
-
postToTaskChat(taskId: string, content: string): Promise<{
|
|
154
|
+
getTaskChat(taskId: string, limit?: number, projectId?: string): Promise<unknown[]>;
|
|
155
|
+
postToTaskChat(taskId: string, content: string, projectId?: string): Promise<{
|
|
146
156
|
messageId: string;
|
|
147
157
|
}>;
|
|
148
|
-
getTaskCli(taskId: string, limit?: number, source?: string): Promise<{
|
|
158
|
+
getTaskCli(taskId: string, limit?: number, source?: string, projectId?: string): Promise<{
|
|
149
159
|
type: string;
|
|
150
160
|
data: Record<string, unknown>;
|
|
151
161
|
timestamp: string;
|
|
152
162
|
}[]>;
|
|
153
|
-
listTags(): Promise<{
|
|
163
|
+
listTags(projectId?: string): Promise<{
|
|
154
164
|
id: string;
|
|
155
165
|
name: string;
|
|
156
166
|
color: string;
|
|
157
167
|
}[]>;
|
|
158
|
-
getProjectSummary(): Promise<unknown>;
|
|
159
|
-
approveTask(taskId: string): Promise<{
|
|
168
|
+
getProjectSummary(projectId?: string): Promise<unknown>;
|
|
169
|
+
approveTask(taskId: string, projectId?: string): Promise<{
|
|
160
170
|
status: string;
|
|
161
171
|
}>;
|
|
162
|
-
requestChanges(taskId: string, feedback: string): Promise<void>;
|
|
163
|
-
approveAndMergePR(childTaskId: string): Promise<{
|
|
172
|
+
requestChanges(taskId: string, feedback: string, projectId?: string): Promise<void>;
|
|
173
|
+
approveAndMergePR(childTaskId: string, projectId?: string): Promise<{
|
|
164
174
|
merged: boolean;
|
|
165
175
|
childTaskId: string;
|
|
166
176
|
prNumber: number;
|
|
167
177
|
}>;
|
|
168
|
-
listTaskFiles(taskId: string): Promise<unknown[]>;
|
|
178
|
+
listTaskFiles(taskId: string, projectId?: string): Promise<unknown[]>;
|
|
169
179
|
getAttachment(taskId: string, fileId: string, opts?: {
|
|
170
180
|
offset?: number;
|
|
171
181
|
maxBytes?: number;
|
|
182
|
+
projectId?: string;
|
|
172
183
|
}): Promise<unknown>;
|
|
173
184
|
requestFileUpload(taskId: string, params: {
|
|
174
185
|
fileName: string;
|
|
175
186
|
mimeType: string;
|
|
176
187
|
fileSize: number;
|
|
188
|
+
projectId?: string;
|
|
177
189
|
}): Promise<{
|
|
178
190
|
fileId: string;
|
|
179
191
|
uploadUrl: string;
|
|
180
192
|
}>;
|
|
181
|
-
confirmFileUpload(taskId: string, fileId: string, comment?: string): Promise<{
|
|
193
|
+
confirmFileUpload(taskId: string, fileId: string, comment?: string, projectId?: string): Promise<{
|
|
182
194
|
fileId: string;
|
|
183
195
|
fileName: string;
|
|
184
196
|
downloadUrl?: string;
|
|
185
197
|
messageId?: string;
|
|
186
198
|
}>;
|
|
187
|
-
createRelease(taskIds?: string[]): Promise<{
|
|
199
|
+
createRelease(taskIds?: string[], projectId?: string): Promise<{
|
|
188
200
|
taskId: string;
|
|
189
201
|
version: string;
|
|
190
202
|
}>;
|
|
191
203
|
createPullRequest(params: {
|
|
204
|
+
projectId?: string;
|
|
192
205
|
taskId: string;
|
|
193
206
|
title: string;
|
|
194
207
|
body: string;
|
|
@@ -199,6 +212,7 @@ declare class ConveyorConnection {
|
|
|
199
212
|
prUrl: string;
|
|
200
213
|
}>;
|
|
201
214
|
createSubtask(params: {
|
|
215
|
+
projectId?: string;
|
|
202
216
|
parentTaskId: string;
|
|
203
217
|
title: string;
|
|
204
218
|
description?: string;
|
|
@@ -210,6 +224,7 @@ declare class ConveyorConnection {
|
|
|
210
224
|
slug: string;
|
|
211
225
|
}>;
|
|
212
226
|
updateSubtask(params: {
|
|
227
|
+
projectId?: string;
|
|
213
228
|
subtaskId: string;
|
|
214
229
|
title?: string;
|
|
215
230
|
description?: string;
|
|
@@ -221,38 +236,52 @@ declare class ConveyorConnection {
|
|
|
221
236
|
id: string;
|
|
222
237
|
status: string;
|
|
223
238
|
}>;
|
|
224
|
-
listSubtasks(taskId: string): Promise<unknown[]>;
|
|
225
|
-
deleteSubtask(subtaskId: string): Promise<{
|
|
239
|
+
listSubtasks(taskId: string, projectId?: string): Promise<unknown[]>;
|
|
240
|
+
deleteSubtask(subtaskId: string, projectId?: string): Promise<{
|
|
226
241
|
deleted: boolean;
|
|
227
242
|
}>;
|
|
228
|
-
getDependencies(taskId: string): Promise<unknown[]>;
|
|
243
|
+
getDependencies(taskId: string, projectId?: string): Promise<unknown[]>;
|
|
229
244
|
addDependency(params: {
|
|
245
|
+
projectId?: string;
|
|
230
246
|
taskId: string;
|
|
231
247
|
dependsOnSlugOrId: string;
|
|
232
248
|
}): Promise<{
|
|
233
249
|
success: boolean;
|
|
234
250
|
}>;
|
|
235
251
|
removeDependency(params: {
|
|
252
|
+
projectId?: string;
|
|
236
253
|
taskId: string;
|
|
237
254
|
dependsOnSlugOrId: string;
|
|
238
255
|
}): Promise<{
|
|
239
256
|
success: boolean;
|
|
240
257
|
}>;
|
|
241
|
-
listManualTests(taskId: string): Promise<Array<{
|
|
258
|
+
listManualTests(taskId: string, projectId?: string): Promise<Array<{
|
|
242
259
|
id: string;
|
|
243
260
|
type: string;
|
|
244
261
|
title: string;
|
|
245
262
|
ordinal: number;
|
|
246
263
|
createdAt: string;
|
|
247
264
|
checked: boolean;
|
|
265
|
+
failures: Array<{
|
|
266
|
+
userName: string | null;
|
|
267
|
+
reason: string | null;
|
|
268
|
+
createdAt: string;
|
|
269
|
+
}>;
|
|
248
270
|
}>>;
|
|
249
271
|
setManualTests(taskId: string, items: Array<{
|
|
250
272
|
title: string;
|
|
251
|
-
}
|
|
273
|
+
}>, projectId?: string): Promise<{
|
|
252
274
|
created: number;
|
|
253
275
|
skipped: number;
|
|
254
276
|
}>;
|
|
277
|
+
editManualTest(taskId: string, title: string, newTitle: string, projectId?: string): Promise<{
|
|
278
|
+
updated: boolean;
|
|
279
|
+
}>;
|
|
280
|
+
removeManualTest(taskId: string, title: string, projectId?: string): Promise<{
|
|
281
|
+
removed: boolean;
|
|
282
|
+
}>;
|
|
255
283
|
createSuggestion(params: {
|
|
284
|
+
projectId?: string;
|
|
256
285
|
title: string;
|
|
257
286
|
description?: string;
|
|
258
287
|
tagNames?: string[];
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
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\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.config.projectId;\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_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 status?: string;\n assigneeId?: string;\n unassigned?: boolean;\n limit?: number;\n }): Promise<unknown[]> {\n return this.call(\"listProjectTasks\", {\n projectId: this.config.projectId,\n ...params,\n });\n }\n\n getTask(taskId: string): Promise<unknown> {\n return this.call(\"getProjectTask\", {\n projectId: this.config.projectId,\n taskId,\n });\n }\n\n searchTasks(params: {\n tagNames?: string[];\n searchQuery?: string;\n statusFilters?: string[];\n assigneeId?: string;\n unassigned?: boolean;\n limit?: number;\n }): Promise<unknown[]> {\n return this.call(\"searchProjectTasks\", {\n projectId: this.config.projectId,\n ...params,\n });\n }\n\n // ── Task Mutations ──────────────────────────────────────────────────\n\n createTask(params: {\n title: string;\n description?: string;\n plan?: string;\n status?: string;\n }): Promise<{ id: string; slug: string }> {\n return this.call(\"createProjectTask\", {\n projectId: this.config.projectId,\n ...params,\n });\n }\n\n updateTask(params: {\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 return this.call(\"updateProjectTask\", {\n projectId: this.config.projectId,\n ...params,\n });\n }\n\n // ── Reviewers & Members ─────────────────────────────────────────────\n\n addReviewer(params: {\n taskId: string;\n userId: string;\n }): Promise<{ taskId: string; reviewers: Array<{ userId: string; name: string | null }> }> {\n return this.call(\"addProjectTaskReviewer\", {\n projectId: this.config.projectId,\n ...params,\n });\n }\n\n removeReviewer(params: {\n taskId: string;\n userId: string;\n }): Promise<{ taskId: string; reviewers: Array<{ userId: string; name: string | null }> }> {\n return this.call(\"removeProjectTaskReviewer\", {\n projectId: this.config.projectId,\n ...params,\n });\n }\n\n listProjectMembers(): Promise<\n Array<{ userId: string; name: string | null; email: string; level: string }>\n > {\n return this.call(\"listProjectMembers\", {\n projectId: this.config.projectId,\n });\n }\n\n // ── Build Management ────────────────────────────────────────────────\n\n startBuild(taskId: string): Promise<{ taskId: string; status: string }> {\n return this.call(\"startProjectBuild\", {\n projectId: this.config.projectId,\n taskId,\n });\n }\n\n stopBuild(taskId: string): Promise<{ taskId: string; stopped: boolean }> {\n return this.call(\"stopProjectBuild\", {\n projectId: this.config.projectId,\n taskId,\n });\n }\n\n getBuildStatus(taskId: string): 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.config.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): Promise<unknown[]> {\n // Uses getProjectTask and extracts chatMessages\n return this.call<Record<string, unknown>>(\"getProjectTask\", {\n projectId: this.config.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(taskId: string, content: string): Promise<{ messageId: string }> {\n return this.call(\"postToProjectTaskChat\", {\n projectId: this.config.projectId,\n taskId,\n content,\n });\n }\n\n // ── CLI History ─────────────────────────────────────────────────────\n\n getTaskCli(\n taskId: string,\n limit?: number,\n source?: string,\n ): Promise<{ type: string; data: Record<string, unknown>; timestamp: string }[]> {\n return this.call(\"getProjectTaskCli\", {\n projectId: this.config.projectId,\n taskId,\n limit,\n source,\n });\n }\n\n // ── Project Info ────────────────────────────────────────────────────\n\n listTags(): Promise<{ id: string; name: string; color: string }[]> {\n return this.call(\"listProjectTags\", {\n projectId: this.config.projectId,\n });\n }\n\n getProjectSummary(): Promise<unknown> {\n return this.call(\"getProjectSummary\", {\n projectId: this.config.projectId,\n });\n }\n\n // ── Review Flow ─────────────────────────────────────────────────────\n\n async approveTask(taskId: string): Promise<{ status: string }> {\n // Determine next status based on current status\n const task = (await this.call(\"getProjectTask\", {\n projectId: this.config.projectId,\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({ taskId, status: nextStatus });\n return { status: result.status };\n }\n\n async requestChanges(taskId: string, feedback: string): Promise<void> {\n // Post feedback to task chat then move to InProgress\n await this.postToTaskChat(taskId, feedback);\n await this.updateTask({ taskId, status: \"InProgress\" });\n }\n\n approveAndMergePR(\n childTaskId: string,\n ): Promise<{ merged: boolean; childTaskId: string; prNumber: number }> {\n return this.call(\"approveProjectMergePR\", {\n projectId: this.config.projectId,\n childTaskId,\n });\n }\n\n // ── File Attachments ────────────────────────────────────────────────\n\n listTaskFiles(taskId: string): Promise<unknown[]> {\n return this.call(\"listProjectTaskFiles\", {\n projectId: this.config.projectId,\n taskId,\n });\n }\n\n getAttachment(\n taskId: string,\n fileId: string,\n opts?: { offset?: number; maxBytes?: number },\n ): Promise<unknown> {\n const payload: Record<string, unknown> = {\n projectId: this.config.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 },\n ): Promise<{ fileId: string; uploadUrl: string }> {\n return this.call(\"requestProjectFileUpload\", {\n projectId: this.config.projectId,\n taskId,\n ...params,\n });\n }\n\n confirmFileUpload(\n taskId: string,\n fileId: string,\n comment?: string,\n ): Promise<{ fileId: string; fileName: string; downloadUrl?: string; messageId?: string }> {\n const payload: Record<string, unknown> = {\n projectId: this.config.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(taskIds?: string[]): 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(\"createProjectRelease\", { projectId: this.config.projectId, taskIds }, 45_000);\n }\n\n // ── Pull Requests ───────────────────────────────────────────────────\n\n createPullRequest(params: {\n taskId: string;\n title: string;\n body: string;\n head?: string;\n base?: string;\n }): Promise<{ prNumber: number; prUrl: string }> {\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.config.projectId, ...params },\n 45_000,\n );\n }\n\n // ── Subtasks ────────────────────────────────────────────────────────\n\n createSubtask(params: {\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 return this.call(\"createProjectSubtask\", {\n projectId: this.config.projectId,\n ...params,\n });\n }\n\n updateSubtask(params: {\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 return this.call(\"updateProjectSubtask\", {\n projectId: this.config.projectId,\n ...params,\n });\n }\n\n listSubtasks(taskId: string): Promise<unknown[]> {\n return this.call(\"listProjectSubtasks\", {\n projectId: this.config.projectId,\n taskId,\n });\n }\n\n deleteSubtask(subtaskId: string): Promise<{ deleted: boolean }> {\n return this.call(\"deleteProjectSubtask\", {\n projectId: this.config.projectId,\n subtaskId,\n });\n }\n\n // ── Dependencies ────────────────────────────────────────────────────\n\n getDependencies(taskId: string): Promise<unknown[]> {\n return this.call(\"getProjectTaskDependencies\", {\n projectId: this.config.projectId,\n taskId,\n });\n }\n\n addDependency(params: {\n taskId: string;\n dependsOnSlugOrId: string;\n }): Promise<{ success: boolean }> {\n return this.call(\"addProjectTaskDependency\", {\n projectId: this.config.projectId,\n ...params,\n });\n }\n\n removeDependency(params: {\n taskId: string;\n dependsOnSlugOrId: string;\n }): Promise<{ success: boolean }> {\n return this.call(\"removeProjectTaskDependency\", {\n projectId: this.config.projectId,\n ...params,\n });\n }\n\n // ── Manual Test Checklist ───────────────────────────────────────────\n\n listManualTests(taskId: string): 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.config.projectId,\n taskId,\n });\n }\n\n setManualTests(\n taskId: string,\n items: Array<{ title: string }>,\n ): Promise<{ created: number; skipped: number }> {\n return this.call(\"setProjectManualTests\", {\n projectId: this.config.projectId,\n taskId,\n items,\n });\n }\n\n // ── Suggestions ─────────────────────────────────────────────────────\n\n createSuggestion(params: {\n title: string;\n description?: string;\n tagNames?: string[];\n }): Promise<{ id: string; merged: boolean; mergedIntoId?: string }> {\n return this.call(\"createProjectSuggestion\", {\n projectId: this.config.projectId,\n ...params,\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":[]}
|