@rallycry/conveyor-mcp 4.3.28 → 4.3.29

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.
@@ -0,0 +1,888 @@
1
+ interface ConveyorMcpConfig {
2
+ apiUrl: string;
3
+ projectToken: string;
4
+ projectId?: string;
5
+ /**
6
+ * Optional default board (sub-project) scope. When set, unqualified
7
+ * task create/list/search default to this board instead of the whole
8
+ * project — so a connection scoped to a board lands cards on that board.
9
+ */
10
+ subProjectId?: string;
11
+ }
12
+ /** Actions a connection is authorized for, mirrors ConveyorCapability in @project/shared. */
13
+ type ConveyorCapability = "read" | "create" | "update" | "chat" | "files" | "build";
14
+ /** Immutable id + human name/slug + web URL for one connection scope level. */
15
+ interface ConnectionScopeRef {
16
+ id: string;
17
+ name: string;
18
+ slug: string;
19
+ url: string;
20
+ }
21
+ /** Result of `get_connection_context` — effective identity + scope + grants. */
22
+ interface ConnectionContext {
23
+ account: {
24
+ userId: string;
25
+ name: string | null;
26
+ email: string;
27
+ };
28
+ project: ConnectionScopeRef & {
29
+ githubRepoOwner: string | null;
30
+ githubRepoName: string | null;
31
+ };
32
+ subProject: (ConnectionScopeRef & {
33
+ rootPath: string | null;
34
+ }) | null;
35
+ role: string;
36
+ capabilities: ConveyorCapability[];
37
+ managementUrls: {
38
+ board: string;
39
+ projectSettings: string;
40
+ memberSettings: string;
41
+ };
42
+ summary: string;
43
+ }
44
+ /** One layer of the verify_connection ladder. */
45
+ interface VerifyConnectionLayer {
46
+ key: string;
47
+ label: string;
48
+ ok: boolean;
49
+ detail: string;
50
+ }
51
+ /** Result of `verify_connection` — a layered, verify-by-scope probe. */
52
+ interface VerifyConnectionResult {
53
+ ok: boolean;
54
+ layers: VerifyConnectionLayer[];
55
+ summary: string;
56
+ nextAction: string | null;
57
+ scope: {
58
+ projectId: string;
59
+ projectName: string;
60
+ subProjectId: string | null;
61
+ subProjectName: string | null;
62
+ capabilities: ConveyorCapability[];
63
+ };
64
+ }
65
+ /** The project + board a task mutation actually landed on. Returned so a caller
66
+ * can confirm where the write went (name-vs-board-label ambiguity guard). */
67
+ interface EffectiveScope {
68
+ projectId: string;
69
+ subProjectId: string | null;
70
+ }
71
+ /** One board under the connected project, for list_accessible_subprojects. */
72
+ interface AccessibleSubproject {
73
+ id: string;
74
+ name: string;
75
+ slug: string;
76
+ url: string;
77
+ rootPath: string | null;
78
+ role: string;
79
+ capabilities: ConveyorCapability[];
80
+ }
81
+ /**
82
+ * Canonical risk levels — kept in lockstep with `RISK_LEVELS` in
83
+ * `@project/shared` (conveyor-mcp is published standalone and does not depend on
84
+ * the shared package, so the vocabulary is duplicated here).
85
+ */
86
+ type RiskLevel = "critical" | "high" | "medium" | "low";
87
+ /** A single PTY output frame broadcast on the `pty:data` room event. */
88
+ interface PtyDataChunk {
89
+ sessionId: string;
90
+ seq: number;
91
+ data: string;
92
+ cols?: number;
93
+ rows?: number;
94
+ }
95
+ /** Ring-buffer snapshot returned by `ptyAttach` for catch-up replay. */
96
+ interface PtyAttachSnapshot {
97
+ sessionId: string;
98
+ chunks: {
99
+ seq: number;
100
+ data: string;
101
+ }[];
102
+ cols: number;
103
+ rows: number;
104
+ totalBytes: number;
105
+ }
106
+ /**
107
+ * One card as it appears on the live `cardsByProject` collection. A structural
108
+ * subset of `TaskCardDTO` — only what `conveyor-wait` filters on and prints, so
109
+ * the standalone package does not have to mirror the whole board DTO. Note
110
+ * there is no flat assignee id: the assignee rides the `assignedUser` relation.
111
+ */
112
+ interface CardCollectionItem {
113
+ id: string;
114
+ slug?: string;
115
+ title?: string;
116
+ type?: string;
117
+ status?: string;
118
+ assignedUser?: {
119
+ id: string;
120
+ } | null;
121
+ }
122
+ /** One page of the `cardsByProject` snapshot, as returned by the subscribe ack. */
123
+ interface CardCollectionPage {
124
+ items: CardCollectionItem[];
125
+ nextCursor: string | null;
126
+ totalCount: number;
127
+ }
128
+ /**
129
+ * A quickdraw collection change on a card scope. `added` vs `updated` is
130
+ * cosmetic — most card writes go through a hand-rolled upsert that always
131
+ * emits `updated`, creates included.
132
+ */
133
+ type CardCollectionDelta = {
134
+ type: "added";
135
+ item: CardCollectionItem;
136
+ rev: number;
137
+ } | {
138
+ type: "updated";
139
+ item: CardCollectionItem;
140
+ rev: number;
141
+ } | {
142
+ type: "removed";
143
+ id: string;
144
+ rev: number;
145
+ } | {
146
+ type: "reset";
147
+ rev: number;
148
+ };
149
+ /**
150
+ * Result of `getActivePtySession`. `sessionId` is null until the cloud agent
151
+ * has booted a PTY and produced at least one ring frame (readiness signal).
152
+ */
153
+ interface ActivePtySession {
154
+ sessionId: string | null;
155
+ cols?: number;
156
+ rows?: number;
157
+ }
158
+ interface WorkspaceAttachInfo {
159
+ taskId: string;
160
+ sessionId: string;
161
+ workspaceRoot: string;
162
+ /** "codespace" means preview-only — GitHub owns the VM's forwarded ports, so
163
+ * `tunnelUrl`/`attachToken`/`ssh` are null/absent. Older servers omit it. */
164
+ backend?: "gke" | "codespace";
165
+ tunnelUrl: string | null;
166
+ attachToken: string | null;
167
+ expiresAt: string;
168
+ previewPorts: Array<{
169
+ port: number;
170
+ label: string;
171
+ }>;
172
+ previewUrls: Record<string, string>;
173
+ ssh?: {
174
+ remotePort: number;
175
+ preferredLocalPort: number;
176
+ username: string;
177
+ };
178
+ }
179
+ /** One Cloud Logging entry as returned by the API's queryProjectGcpLogs. */
180
+ interface GcpLogEntry {
181
+ timestamp: string;
182
+ severity: string;
183
+ message: string;
184
+ resource: Record<string, string>;
185
+ labels: Record<string, string>;
186
+ resourceType?: string;
187
+ insertId?: string;
188
+ trace?: string;
189
+ httpRequest?: {
190
+ status?: number;
191
+ method?: string;
192
+ url?: string;
193
+ latencyMs?: number;
194
+ };
195
+ payload?: string;
196
+ payloadTruncated?: boolean;
197
+ }
198
+ interface GcpLogQueryResult {
199
+ entries: GcpLogEntry[];
200
+ hasMore: boolean;
201
+ nextPageToken?: string;
202
+ scopedServices?: string[];
203
+ error?: string;
204
+ }
205
+ /** Loki entries normalize onto the same row shape as Cloud Logging entries. */
206
+ interface GrafanaLogQueryResult {
207
+ entries: GcpLogEntry[];
208
+ hasMore: boolean;
209
+ /** The LogQL the server composed or executed — agents can iterate on it. */
210
+ logql?: string;
211
+ error?: string;
212
+ }
213
+ /**
214
+ * One row of the project onboarding checklist. Mirrors the API's
215
+ * `ReadinessCheck` (conveyor-mcp is published standalone and does not depend on
216
+ * `@project/shared`, so the shape is duplicated here).
217
+ */
218
+ interface OnboardingCheck {
219
+ key: string;
220
+ status: "ok" | "warn" | "fail";
221
+ reason: string;
222
+ fix?: {
223
+ label: string;
224
+ href?: string | null;
225
+ action?: string;
226
+ };
227
+ }
228
+ /** Result of `get_onboarding_status` — the project's setup readiness report. */
229
+ interface OnboardingStatus {
230
+ ok: boolean;
231
+ checks: OnboardingCheck[];
232
+ bypassedAt: string | null;
233
+ }
234
+ /** The single next onboarding step. Mirrors the API's `OnboardingStep`. */
235
+ interface OnboardingStep {
236
+ key: string;
237
+ status: "warn" | "fail";
238
+ title: string;
239
+ reason: string;
240
+ guidance: string;
241
+ autoFixable: boolean;
242
+ fix?: {
243
+ label: string;
244
+ href?: string | null;
245
+ action?: string;
246
+ };
247
+ connectUrls?: Record<string, string>;
248
+ }
249
+ /** Result of `get_onboarding_step` — the choose-your-own-adventure step driver.
250
+ * Mirrors the API's `OnboardingStepReport`. */
251
+ interface OnboardingStepReport {
252
+ done: boolean;
253
+ ok: boolean;
254
+ bypassedAt: string | null;
255
+ step: OnboardingStep | null;
256
+ remaining: Array<{
257
+ key: string;
258
+ status: "warn" | "fail";
259
+ reason: string;
260
+ }>;
261
+ checks: OnboardingCheck[];
262
+ }
263
+ interface MoveCardResult {
264
+ cardId: string;
265
+ sourceProjectId: string;
266
+ destinationProjectId: string;
267
+ slug: string;
268
+ clearedFields: string[];
269
+ }
270
+ interface ProjectConnectUrls {
271
+ gcpConnect: string;
272
+ gcpSettings: string;
273
+ memberSettings: string;
274
+ projectSettings: string;
275
+ setupWizard: string;
276
+ }
277
+ interface TagSummary {
278
+ id: string;
279
+ name: string;
280
+ color: string;
281
+ description?: string | null;
282
+ }
283
+ /** A tag context-path link (rule/doc/file/folder) loaded into agent context.
284
+ * A locator turns the link into a VERIFIED repo link — mirrors
285
+ * TagContextLink in @project/shared types/tag-types.ts. */
286
+ interface ContextPathInput {
287
+ type: "rule" | "doc" | "file" | "folder";
288
+ path: string;
289
+ label?: string;
290
+ locator?: string;
291
+ locatorType?: "test" | "code";
292
+ }
293
+ interface PrioritySummary {
294
+ id: string;
295
+ value: number;
296
+ name: string;
297
+ color: string;
298
+ description?: string | null;
299
+ }
300
+ declare class ConveyorConnection {
301
+ private socket;
302
+ private config;
303
+ /** project slug → id, for resolving `<project>/<card>` card paths. */
304
+ private projectSlugIds;
305
+ constructor(config: ConveyorMcpConfig);
306
+ get projectId(): string;
307
+ private resolveProjectId;
308
+ /** The configured default board (CONVEYOR_SUBPROJECT_ID), if any. */
309
+ get defaultSubProjectId(): string | undefined;
310
+ /**
311
+ * Resolve the board scope for a task create/list/search:
312
+ * - `null` explicitly means "the whole project" (never fall back to the default).
313
+ * - `undefined` (not passed) falls back to the connection's default board.
314
+ * - a concrete id is used as-is.
315
+ * Returning `undefined` leaves the request unscoped (whole project).
316
+ */
317
+ private resolveSubProjectId;
318
+ private normalizeProjectList;
319
+ connect(): Promise<void>;
320
+ private call;
321
+ /**
322
+ * Fire-and-forget emit (no ack). The quickdraw-core server method handler
323
+ * invokes the ack callback via optional chaining, so omitting it still runs
324
+ * the full auth/schema/ACL pipeline — it just skips the response round-trip.
325
+ * Used for high-frequency PTY input/resize so each keystroke does not arm a
326
+ * 15s timeout timer.
327
+ */
328
+ private emit;
329
+ private callService;
330
+ queryGcpLogs(params: {
331
+ projectId?: string;
332
+ env?: "prod" | "dev" | "claudespace";
333
+ severity?: string;
334
+ services?: string[];
335
+ sqlInstances?: string[];
336
+ allServices?: boolean;
337
+ search?: string;
338
+ filter?: string;
339
+ startTime?: string;
340
+ endTime?: string;
341
+ limit?: number;
342
+ pageToken?: string;
343
+ }): Promise<GcpLogQueryResult>;
344
+ queryGrafanaLogs(params: {
345
+ projectId?: string;
346
+ env?: "prod" | "dev";
347
+ services?: string[];
348
+ level?: "debug" | "info" | "warn" | "error" | "fatal";
349
+ search?: string;
350
+ logql?: string;
351
+ startTime?: string;
352
+ endTime?: string;
353
+ limit?: number;
354
+ }): Promise<GrafanaLogQueryResult>;
355
+ listTasks(params: {
356
+ projectId?: string;
357
+ status?: string;
358
+ typeFilters?: string[];
359
+ assigneeId?: string;
360
+ unassigned?: boolean;
361
+ subProjectId?: string | null;
362
+ limit?: number;
363
+ }): Promise<unknown[]>;
364
+ getTask(taskId: string, projectId?: string): Promise<unknown>;
365
+ getCardBySlug(slug: string, projectId?: string): Promise<unknown>;
366
+ searchTasks(params: {
367
+ projectId?: string;
368
+ tagNames?: string[];
369
+ tagMatch?: "any" | "all";
370
+ includeChildTags?: boolean;
371
+ searchQuery?: string;
372
+ statusFilters?: string[];
373
+ typeFilters?: string[];
374
+ assigneeId?: string;
375
+ unassigned?: boolean;
376
+ subProjectId?: string | null;
377
+ limit?: number;
378
+ }): Promise<unknown[]>;
379
+ createTask(params: {
380
+ projectId?: string;
381
+ title: string;
382
+ description?: string;
383
+ plan?: string;
384
+ status?: string;
385
+ subProjectId?: string | null;
386
+ tags?: string[];
387
+ }): Promise<{
388
+ id: string;
389
+ slug: string;
390
+ effectiveScope: EffectiveScope;
391
+ }>;
392
+ updateTask(params: {
393
+ projectId?: string;
394
+ taskId: string;
395
+ title?: string;
396
+ description?: string;
397
+ plan?: string;
398
+ status?: string;
399
+ risk?: RiskLevel | null;
400
+ storyPointValue?: number | null;
401
+ assignedUserId?: string | null;
402
+ subProjectId?: string | null;
403
+ githubBranch?: string | null;
404
+ addTags?: string[];
405
+ removeTags?: string[];
406
+ }): Promise<{
407
+ id: string;
408
+ status: string | null;
409
+ risk: RiskLevel | null;
410
+ storyPointValue: number | null;
411
+ assignedUserId: string | null;
412
+ addedTags: string[];
413
+ removedTags: string[];
414
+ }>;
415
+ /** Resolve tag names to IDs within a project, throwing on any unknown name. */
416
+ private resolveTagIds;
417
+ private assignTagsToTask;
418
+ private removeTagsFromTask;
419
+ /** Guarded status transition used by the review tools (approve/request). */
420
+ transitionTaskStatus(params: {
421
+ projectId?: string;
422
+ taskId: string;
423
+ toStatus: string;
424
+ expectedFromStatus?: string;
425
+ risk?: RiskLevel;
426
+ }): Promise<{
427
+ id: string;
428
+ status: string;
429
+ risk: RiskLevel | null;
430
+ }>;
431
+ moveCard(params: {
432
+ projectId?: string;
433
+ taskId: string;
434
+ destinationProjectId: string;
435
+ }): Promise<MoveCardResult>;
436
+ addReviewer(params: {
437
+ projectId?: string;
438
+ taskId: string;
439
+ userId: string;
440
+ }): Promise<{
441
+ taskId: string;
442
+ reviewers: Array<{
443
+ userId: string;
444
+ name: string | null;
445
+ }>;
446
+ }>;
447
+ removeReviewer(params: {
448
+ projectId?: string;
449
+ taskId: string;
450
+ userId: string;
451
+ }): Promise<{
452
+ taskId: string;
453
+ reviewers: Array<{
454
+ userId: string;
455
+ name: string | null;
456
+ }>;
457
+ }>;
458
+ listProjectMembers(projectId?: string): Promise<Array<{
459
+ userId: string;
460
+ name: string | null;
461
+ email: string;
462
+ level: string;
463
+ }>>;
464
+ listProjects(): Promise<unknown[]>;
465
+ /**
466
+ * Resolve a project SLUG (as pasted in a `<project>/<card>` card path) to its
467
+ * id.
468
+ *
469
+ * Cached, because a slug→id mapping effectively never changes and this sits
470
+ * in front of an ordinary card lookup. A miss refetches once before failing,
471
+ * so a project created after the cache warmed still resolves.
472
+ *
473
+ * Throws naming the slug rather than falling back to the configured default
474
+ * project: the caller pasted a specific project, and silently answering about
475
+ * a different one is the worst possible outcome here.
476
+ */
477
+ resolveProjectIdBySlug(slug: string): Promise<string>;
478
+ private refreshProjectSlugCache;
479
+ startBuild(taskId: string, projectId?: string): Promise<{
480
+ taskId: string;
481
+ status: string;
482
+ }>;
483
+ stopBuild(taskId: string, projectId?: string): Promise<{
484
+ taskId: string;
485
+ stopped: boolean;
486
+ }>;
487
+ sleepTask(taskId: string, projectId?: string): Promise<{
488
+ taskId: string;
489
+ codespaceStatus: string;
490
+ }>;
491
+ resumeTask(taskId: string, projectId?: string): Promise<{
492
+ status: string;
493
+ }>;
494
+ deleteTaskEnvironment(taskId: string, projectId?: string): Promise<{
495
+ taskId: string;
496
+ status: string;
497
+ }>;
498
+ getBuildStatus(taskId: string, projectId?: string): Promise<{
499
+ session: {
500
+ status: string | null;
501
+ agentRunnerStatus: string | null;
502
+ } | null;
503
+ }>;
504
+ getWorkspaceAttachInfo(taskId: string, sshPublicKey?: string): Promise<WorkspaceAttachInfo>;
505
+ getTaskChat(taskId: string, limit?: number, projectId?: string): Promise<unknown[]>;
506
+ postToTaskChat(taskId: string, content: string, projectId?: string): Promise<{
507
+ messageId: string;
508
+ }>;
509
+ getTaskCli(taskId: string, limit?: number, source?: string, projectId?: string): Promise<{
510
+ type: string;
511
+ data: Record<string, unknown>;
512
+ timestamp: string;
513
+ }[]>;
514
+ getTaskSessions(taskId: string, projectId?: string): Promise<Array<{
515
+ taskId: string;
516
+ slug: string;
517
+ title: string;
518
+ type: string;
519
+ status: string;
520
+ codeReviewStatus: string | null;
521
+ codeReviewAttempts: number;
522
+ workspaces: Array<{
523
+ id: string;
524
+ purpose: string;
525
+ desiredState: string;
526
+ observedState: string;
527
+ branch: string | null;
528
+ checkoutRef: string | null;
529
+ createdAt: string;
530
+ updatedAt: string;
531
+ pod: {
532
+ name: string;
533
+ namespace: string;
534
+ phase: string;
535
+ imageUri: string | null;
536
+ } | null;
537
+ sessions: Array<{
538
+ id: string;
539
+ role: string;
540
+ mode: string;
541
+ status: string;
542
+ userId: string;
543
+ leaseUntil: string | null;
544
+ createdAt: string;
545
+ }>;
546
+ }>;
547
+ sessions: Array<{
548
+ id: string;
549
+ provider: string;
550
+ instanceName: string | null;
551
+ status: string;
552
+ agentRunnerStatus: string | null;
553
+ lastHeartbeatAt: string | null;
554
+ agentRunningAt: string | null;
555
+ lastAgentEvent: string | null;
556
+ deletionRequestedAt: string | null;
557
+ deletionAttempts: number;
558
+ createdAt: string;
559
+ stoppedAt: string | null;
560
+ }>;
561
+ }>>;
562
+ listTags(projectId?: string): Promise<{
563
+ id: string;
564
+ name: string;
565
+ color: string;
566
+ description: string | null;
567
+ parentTagIds: string[];
568
+ childTagIds: string[];
569
+ hasOverview: boolean;
570
+ /** Files labelled as examples of the tag — read the tiles with list_tag_attachments. */
571
+ attachmentCount: number;
572
+ /** Rule/doc/file/folder links the tag wires into agent context; `[]` when none. */
573
+ contextPaths: ContextPathInput[];
574
+ }[]>;
575
+ getTag(params: {
576
+ projectId?: string;
577
+ tag: string;
578
+ }): Promise<unknown>;
579
+ /** One page of a tag's attachment gallery, newest label first. */
580
+ listTagAttachments(params: {
581
+ projectId?: string;
582
+ tag: string;
583
+ limit?: number;
584
+ offset?: number;
585
+ }): Promise<unknown>;
586
+ /** Replace the glossary tags on a file that is already uploaded. */
587
+ setFileTags(params: {
588
+ projectId?: string;
589
+ taskId: string;
590
+ fileId: string;
591
+ tags: string[];
592
+ }): Promise<{
593
+ fileId: string;
594
+ fileName: string;
595
+ appliedTags?: string[];
596
+ unknownTags?: string[];
597
+ }>;
598
+ getProjectSummary(projectId?: string): Promise<unknown>;
599
+ /** Effective account/project/board identity + capabilities for this token. */
600
+ getConnectionContext(projectId?: string): Promise<ConnectionContext>;
601
+ /** Layered verify-by-scope probe (auth → account → project → board →
602
+ * capabilities → read). Proves create/update on the intended board. */
603
+ verifyConnection(params?: {
604
+ projectId?: string;
605
+ intendedActions?: ConveyorCapability[];
606
+ }): Promise<VerifyConnectionResult>;
607
+ /** Boards under the connected project with id/name/slug/url/role/capabilities. */
608
+ listAccessibleSubprojects(projectId?: string): Promise<AccessibleSubproject[]>;
609
+ getOnboardingStatus(projectId?: string): Promise<OnboardingStatus>;
610
+ getOnboardingStep(projectId?: string): Promise<OnboardingStepReport>;
611
+ approveTask(taskId: string, projectId?: string, risk?: RiskLevel): Promise<{
612
+ status: string;
613
+ }>;
614
+ requestChanges(taskId: string, feedback: string, projectId?: string, risk?: RiskLevel): Promise<void>;
615
+ approveAndMergePR(childTaskId: string, projectId?: string): Promise<{
616
+ merged: boolean;
617
+ childTaskId: string;
618
+ prNumber: number;
619
+ }>;
620
+ listTaskFiles(taskId: string, projectId?: string): Promise<unknown[]>;
621
+ getAttachment(taskId: string, fileId: string, opts?: {
622
+ offset?: number;
623
+ maxBytes?: number;
624
+ projectId?: string;
625
+ }): Promise<unknown>;
626
+ requestFileUpload(taskId: string, params: {
627
+ fileName: string;
628
+ mimeType: string;
629
+ fileSize: number;
630
+ projectId?: string;
631
+ }): Promise<{
632
+ fileId: string;
633
+ uploadUrl: string;
634
+ }>;
635
+ confirmFileUpload(taskId: string, fileId: string, comment?: string, projectId?: string, tags?: string[]): Promise<{
636
+ fileId: string;
637
+ fileName: string;
638
+ downloadUrl?: string;
639
+ messageId?: string;
640
+ appliedTags?: string[];
641
+ unknownTags?: string[];
642
+ }>;
643
+ createRelease(taskIds?: string[], projectId?: string): Promise<{
644
+ taskId: string;
645
+ version: string;
646
+ }>;
647
+ addTasksToRelease(taskIds: string[], projectId?: string): Promise<{
648
+ releaseTaskId: string;
649
+ added: number;
650
+ releaseBranchUpdated: boolean;
651
+ }>;
652
+ createPullRequest(params: {
653
+ projectId?: string;
654
+ taskId: string;
655
+ title: string;
656
+ body: string;
657
+ head?: string;
658
+ base?: string;
659
+ }): Promise<{
660
+ prNumber: number;
661
+ prUrl: string;
662
+ }>;
663
+ createSubtask(params: {
664
+ projectId?: string;
665
+ parentTaskId: string;
666
+ title: string;
667
+ description?: string;
668
+ plan?: string;
669
+ ordinal?: number;
670
+ storyPointValue?: number;
671
+ followParentStatus?: boolean;
672
+ dependsOn?: string[];
673
+ tags?: string[];
674
+ }): Promise<{
675
+ id: string;
676
+ slug: string;
677
+ }>;
678
+ updateSubtask(params: {
679
+ projectId?: string;
680
+ subtaskId: string;
681
+ title?: string;
682
+ description?: string;
683
+ plan?: string;
684
+ status?: string;
685
+ ordinal?: number;
686
+ storyPointValue?: number;
687
+ followParentStatus?: boolean;
688
+ dependsOn?: string[];
689
+ }): Promise<{
690
+ id: string;
691
+ status: string;
692
+ }>;
693
+ listSubtasks(taskId: string, projectId?: string): Promise<unknown[]>;
694
+ deleteSubtask(subtaskId: string, projectId?: string): Promise<{
695
+ deleted: boolean;
696
+ }>;
697
+ getDependencies(taskId: string, projectId?: string): Promise<unknown[]>;
698
+ addDependency(params: {
699
+ projectId?: string;
700
+ taskId: string;
701
+ dependsOnSlugOrId: string;
702
+ }): Promise<{
703
+ success: boolean;
704
+ }>;
705
+ removeDependency(params: {
706
+ projectId?: string;
707
+ taskId: string;
708
+ dependsOnSlugOrId: string;
709
+ }): Promise<{
710
+ success: boolean;
711
+ }>;
712
+ listManualTests(taskId: string, projectId?: string): Promise<Array<{
713
+ id: string;
714
+ type: string;
715
+ title: string;
716
+ ordinal: number;
717
+ createdAt: string;
718
+ checked: boolean;
719
+ failures: Array<{
720
+ userName: string | null;
721
+ reason: string | null;
722
+ createdAt: string;
723
+ }>;
724
+ }>>;
725
+ setManualTests(taskId: string, items: Array<{
726
+ title: string;
727
+ }>, projectId?: string): Promise<{
728
+ created: number;
729
+ skipped: number;
730
+ }>;
731
+ editManualTest(taskId: string, title: string, newTitle: string, projectId?: string): Promise<{
732
+ updated: boolean;
733
+ }>;
734
+ removeManualTest(taskId: string, title: string, projectId?: string): Promise<{
735
+ removed: boolean;
736
+ }>;
737
+ approveManualTest(taskId: string, title: string, projectId?: string): Promise<{
738
+ approved: boolean;
739
+ }>;
740
+ rejectManualTest(taskId: string, title: string, reason: string, projectId?: string): Promise<{
741
+ rejected: boolean;
742
+ }>;
743
+ queryManualTests(params: {
744
+ projectId?: string;
745
+ cardStatuses?: string[];
746
+ testStatuses?: Array<"open" | "approved" | "rejected">;
747
+ }): Promise<Array<{
748
+ taskId: string;
749
+ slug: string;
750
+ title: string;
751
+ status: string;
752
+ tests: Array<{
753
+ id: string;
754
+ title: string;
755
+ status: "open" | "approved" | "rejected";
756
+ failures: Array<{
757
+ userName: string | null;
758
+ reason: string | null;
759
+ createdAt: string;
760
+ }>;
761
+ }>;
762
+ }>>;
763
+ getConnectUrls(projectId?: string): Promise<ProjectConnectUrls>;
764
+ updateProjectConfig(params: {
765
+ projectId?: string;
766
+ name?: string;
767
+ description?: string;
768
+ settings?: Record<string, unknown>;
769
+ }): Promise<unknown>;
770
+ updateProjectAgentDefaults(params: {
771
+ projectId?: string;
772
+ defaultPmAgentId?: string | null;
773
+ defaultTaskAgentId?: string | null;
774
+ defaultReviewerAgentId?: string | null;
775
+ helperAgentId?: string | null;
776
+ }): Promise<unknown>;
777
+ listTagsDetailed(projectId?: string): Promise<TagSummary[]>;
778
+ createTag(params: {
779
+ projectId?: string;
780
+ name: string;
781
+ color?: string;
782
+ description?: string;
783
+ overview?: string;
784
+ /** Repo file to source the overview from (stored overview stays as the pending fallback). */
785
+ overviewPath?: string;
786
+ /** Parents to link at create time (multi-parent DAG). */
787
+ parentTagIds?: string[];
788
+ contextPaths?: ContextPathInput[];
789
+ }): Promise<{
790
+ id: string;
791
+ }>;
792
+ updateTag(params: {
793
+ id: string;
794
+ name?: string;
795
+ color?: string;
796
+ description?: string;
797
+ overview?: string | null;
798
+ /** Repo file to source the overview from; null clears back to the stored overview. */
799
+ overviewPath?: string | null;
800
+ parentTagIds?: string[];
801
+ reason?: string;
802
+ contextPaths?: ContextPathInput[];
803
+ }): Promise<unknown>;
804
+ deleteTag(id: string): Promise<unknown>;
805
+ previewTagMerge(params: {
806
+ sourceTagId: string;
807
+ targetTagId: string;
808
+ }): Promise<unknown>;
809
+ mergeTag(params: {
810
+ sourceTagId: string;
811
+ targetTagId: string;
812
+ reason?: string;
813
+ }): Promise<unknown>;
814
+ listPriorities(projectId?: string): Promise<PrioritySummary[]>;
815
+ createPriority(params: {
816
+ projectId?: string;
817
+ value: number;
818
+ name: string;
819
+ color: string;
820
+ description?: string;
821
+ }): Promise<{
822
+ id: string;
823
+ }>;
824
+ updatePriority(params: {
825
+ id: string;
826
+ value?: number;
827
+ name?: string;
828
+ color?: string;
829
+ description?: string;
830
+ }): Promise<unknown>;
831
+ deletePriority(id: string): Promise<unknown>;
832
+ createSuggestion(params: {
833
+ projectId?: string;
834
+ title: string;
835
+ description?: string;
836
+ tagNames?: string[];
837
+ }): Promise<{
838
+ id: string;
839
+ merged: boolean;
840
+ mergedIntoId?: string;
841
+ }>;
842
+ /**
843
+ * Poll target: returns the active cloud PTY session for a task once its ring
844
+ * buffer has frames. `sessionId` is resolved server-side from `taskId` (never
845
+ * accepted from the wire), preserving the one-active-session-per-task invariant.
846
+ */
847
+ getActivePtySession(taskId: string): Promise<ActivePtySession>;
848
+ /** Fetch the ring-buffer snapshot for catch-up replay on (re)attach. */
849
+ ptyAttach(sessionId: string): Promise<PtyAttachSnapshot>;
850
+ /**
851
+ * Join the session room so `pty:data` frames are delivered. Uses the standard
852
+ * quickdraw-core subscribe envelope; "Read" is sufficient for output streaming.
853
+ */
854
+ subscribeToSession(sessionId: string): void;
855
+ /** Relay a stdin chunk to the cloud PTY (raw utf8, fire-and-forget). */
856
+ ptyInput(sessionId: string, data: string): void;
857
+ /** Relay a terminal resize to the cloud PTY (fire-and-forget). */
858
+ ptyResize(sessionId: string, cols: number, rows: number): void;
859
+ /** Subscribe to raw PTY output frames. Returns an unsubscribe function. */
860
+ onPtyData(handler: (chunk: PtyDataChunk) => void): () => void;
861
+ /**
862
+ * Fetch one page of a project's live card collection.
863
+ *
864
+ * A cursor-less call also joins the scope room, which is what starts (or
865
+ * restarts, after a reconnect) delta delivery. Cursor-bearing calls are pure
866
+ * paging and join nothing, so always lead with the cursor-less call.
867
+ */
868
+ subscribeToCardCollection(projectId: string, opts?: {
869
+ cursor?: string | null;
870
+ limit?: number;
871
+ }): Promise<CardCollectionPage>;
872
+ /**
873
+ * Listen for card collection deltas on a project scope. The event name is
874
+ * the room name by design — no id parsing client-side. Returns an
875
+ * unsubscribe function.
876
+ */
877
+ onCardDelta(projectId: string, handler: (delta: CardCollectionDelta) => void): () => void;
878
+ /**
879
+ * Run `handler` on every reconnect of the underlying socket. A reconnect
880
+ * drops every room this socket had joined, so long-lived subscribers must
881
+ * re-subscribe and reconcile whatever they missed. Returns an unsubscribe
882
+ * function.
883
+ */
884
+ onReconnect(handler: () => void): () => void;
885
+ disconnect(): void;
886
+ }
887
+
888
+ export { type ActivePtySession as A, type CardCollectionPage as C, type PtyAttachSnapshot as P, type CardCollectionDelta as a, type CardCollectionItem as b, type PtyDataChunk as c, ConveyorConnection as d, type ConveyorMcpConfig as e };