@rallycry/conveyor-mcp 5.0.6 → 5.0.8

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.
@@ -789,6 +789,13 @@ var ConveyorConnection = class {
789
789
  if (tags?.length) payload.tags = tags;
790
790
  return this.call("confirmProjectFileUpload", payload, 3e4);
791
791
  }
792
+ deleteAttachment(taskId, fileId, projectId) {
793
+ return this.call("deleteProjectTaskFile", {
794
+ projectId: this.resolveProjectId(projectId),
795
+ taskId,
796
+ fileId
797
+ });
798
+ }
792
799
  // ── Releases ────────────────────────────────────────────────────────
793
800
  createRelease(taskIds, projectId) {
794
801
  return this.call(
package/dist/cli.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-5KU3QS6A.js";
5
5
  import {
6
6
  ConveyorConnection
7
- } from "./chunk-77XLXIFP.js";
7
+ } from "./chunk-L3AI3EU2.js";
8
8
 
9
9
  // src/cli.ts
10
10
  import { createRequire } from "module";
@@ -72,14 +72,14 @@ function registerProjectTools(server2, conn2) {
72
72
  // src/tools/connection.ts
73
73
  import { z as z4 } from "zod";
74
74
 
75
- // ../shared/dist/chunk-6NPOGQPP.js
75
+ // ../shared/dist/chunk-U3HGG5NX.js
76
76
  import { z as z2 } from "zod";
77
77
  var DEFAULT_SONNET_MODEL = "claude-sonnet-5";
78
- var DEFAULT_OPUS_MODEL = "claude-opus-5";
78
+ var DEFAULT_OPUS_MODEL = "claude-opus-5-5";
79
79
  var DEFAULT_HAIKU_MODEL = "claude-haiku-4-5-20251001";
80
80
  var FABLE_MODEL = "claude-fable-5-1";
81
81
  var PREVIOUS_SONNET_MODEL = "claude-sonnet-4-6";
82
- var PREVIOUS_OPUS_MODEL = "claude-opus-4-8";
82
+ var PREVIOUS_OPUS_MODEL = "claude-opus-5";
83
83
  var PTY_STREAM_PORT_BASE = 7420;
84
84
  var PTY_STREAM_PORT_ATTEMPTS = 8;
85
85
  var PREVIEW_PORT_DENY_LIST = [
@@ -1057,11 +1057,18 @@ var subtasksContracts = [
1057
1057
  setTaskParentContract
1058
1058
  ];
1059
1059
  var mcpTaskIdOrSlug = f.string({ desc: "The task ID or slug" });
1060
+ var agentTaskIdOrSlug = f.optional(
1061
+ f.string({
1062
+ desc: "Omit for the current card; pass a parent, sibling, or any other card in this project (id or slug) to read its files instead."
1063
+ })
1064
+ );
1060
1065
  var listTaskFilesContract = defineToolContract({
1061
1066
  name: "list_task_files",
1062
1067
  agent: {
1063
- description: "List all files attached to this task with metadata. Use before fetching a specific file to see what is available and how large each is. For file contents use get_attachment.",
1064
- fields: {}
1068
+ description: "List all files attached to this task with metadata. Use before fetching a specific file to see what is available and how large each is. For file contents use get_attachment. Pass task_id to list another card's files in this project, for example the pack parent's source documents.",
1069
+ fields: {
1070
+ task_id: agentTaskIdOrSlug
1071
+ }
1065
1072
  },
1066
1073
  mcp: {
1067
1074
  description: "List all files attached to a task with metadata (no contents \u2014 fast and small). Pass projectId to target a specific project; otherwise the configured default project is used. Use before fetching a specific file to see what is available and how large each is. For file contents use get_attachment.",
@@ -1074,13 +1081,14 @@ var listTaskFilesContract = defineToolContract({
1074
1081
  var getAttachmentContract = defineToolContract({
1075
1082
  name: "get_attachment",
1076
1083
  agent: {
1077
- description: "Fetch one task file's content plus metadata by file ID. Call list_task_files first to discover IDs and check sizes \u2014 large binaries may be truncated by the service's size limit.",
1084
+ description: "Fetch one task file's content plus metadata by file ID. This is the way to read attachment bytes: a document `downloadUrl` (anything that is not an image or video) answers 404 without a signed-in project member's session, so do not curl or WebFetch it from the pod. Call list_task_files first to discover IDs and check sizes \u2014 large binaries may be truncated by the service's size limit. Pass task_id when the file is attached to another card in this project, such as the pack parent.",
1078
1085
  fields: {
1079
- fileId: f.string({ desc: "The file ID to retrieve" })
1086
+ fileId: f.string({ desc: "The file ID to retrieve" }),
1087
+ task_id: agentTaskIdOrSlug
1080
1088
  }
1081
1089
  },
1082
1090
  mcp: {
1083
- description: "Fetch one task file's content plus metadata by file ID (accepts task id or slug). Pass projectId to target a specific project; otherwise the configured default project is used. Images are returned as viewable image blocks. Large text files (logs, JSON) are returned in pages \u2014 use `offset`/`maxBytes` to read more, or fetch `downloadUrl` for the whole file. Call list_task_files first to discover IDs and sizes.",
1091
+ description: "Fetch one task file's content plus metadata by file ID (accepts task id or slug). Pass projectId to target a specific project; otherwise the configured default project is used. Images are returned as viewable image blocks. Large text files (logs, JSON) are returned in pages \u2014 use `offset`/`maxBytes` to read more. This tool is the way to read bytes: a document `downloadUrl` (anything that is not an image or video) answers 404 unless the request carries a signed-in project member's session, so do not curl or fetch it. Call list_task_files first to discover IDs and sizes.",
1084
1092
  fields: {
1085
1093
  projectId: mcpProjectId,
1086
1094
  taskId: mcpTaskIdOrSlug,
@@ -1147,10 +1155,29 @@ var uploadAttachmentContract = defineToolContract({
1147
1155
  }
1148
1156
  }
1149
1157
  });
1158
+ var DELETE_ATTACHMENT_WARNING = "Permanent, with no trash and no undo (unlike drive_delete_file): the file and its bytes are gone, and the chat message that announced it keeps its text but loses the attachment. Use it to remove a superseded upload once its replacement is attached. `fileId` comes from list_task_files.";
1159
+ var deleteAttachmentContract = defineToolContract({
1160
+ name: "delete_attachment",
1161
+ agent: {
1162
+ description: `Delete one attachment from this task. ${DELETE_ATTACHMENT_WARNING} A pod can only delete files on its own card.`,
1163
+ fields: {
1164
+ fileId: f.string({ desc: "The file ID to delete" })
1165
+ }
1166
+ },
1167
+ mcp: {
1168
+ description: `Delete one attachment from a task (accepts task id or slug). ${DELETE_ATTACHMENT_WARNING} Requires Moderate on the project, the same bar as the web Files delete button. Pass projectId to target a specific project; otherwise the configured default project is used.`,
1169
+ fields: {
1170
+ projectId: mcpProjectId,
1171
+ taskId: mcpTaskIdOrSlug,
1172
+ fileId: f.string({ desc: "The file ID to delete" })
1173
+ }
1174
+ }
1175
+ });
1150
1176
  var attachmentsContracts = [
1151
1177
  listTaskFilesContract,
1152
1178
  getAttachmentContract,
1153
- uploadAttachmentContract
1179
+ uploadAttachmentContract,
1180
+ deleteAttachmentContract
1154
1181
  ];
1155
1182
  var createSuggestionContract = defineToolContract({
1156
1183
  name: "create_suggestion",
@@ -1473,7 +1500,7 @@ var createPullRequestContract = defineToolContract({
1473
1500
  fields: {
1474
1501
  title: f.string({ desc: "The PR title" }),
1475
1502
  body: f.string({
1476
- desc: "The PR description/body in markdown. If the diff changes anything a user sees rendered, the body MUST show the visual proof inline, not just point at the card: upload the capture with upload_attachment, then embed the downloadUrl it returns under a '## Screenshots' heading (![caption](url) for images, [caption](url) for video). Attach to the card as well \u2014 the card is the durable home, the PR body is what the reviewer reads."
1503
+ desc: "The PR description/body in markdown. If the diff changes anything a user sees rendered, the body MUST show the visual proof inline, not just point at the card: upload the capture with upload_attachment, then embed the downloadUrl it returns under a '## Screenshots' heading (![caption](url) for images, [caption](url) for video). Only image and video URLs belong in a PR body: a document downloadUrl (csv, pdf, md, \u2026) needs a signed-in project member and shows 404 to a reviewer on GitHub, so point at the card instead. Attach to the card as well \u2014 the card is the durable home, the PR body is what the reviewer reads."
1477
1504
  }),
1478
1505
  branch: f.optional(
1479
1506
  f.string({
@@ -3010,6 +3037,9 @@ var MIME_BY_EXT = {
3010
3037
  ".yaml": "application/yaml",
3011
3038
  ".yml": "application/yaml",
3012
3039
  ".pdf": "application/pdf",
3040
+ ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
3041
+ ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
3042
+ ".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
3013
3043
  ".zip": "application/zip",
3014
3044
  ".gz": "application/gzip",
3015
3045
  ".mp4": "video/mp4",
@@ -3031,9 +3061,9 @@ function buildTextContent(file, content) {
3031
3061
  const start = file.contentByteOffset ?? 0;
3032
3062
  const shown = Buffer.byteLength(content, "utf-8");
3033
3063
  const total = file.contentTotalBytes ?? shown;
3034
- const more = file.contentTruncated ? ` \u2014 showing bytes ${start}\u2013${start + shown} of ${total}; pass offset=${start + shown} for the next page, or fetch the full file at downloadUrl` : "";
3064
+ const more = file.contentTruncated ? ` \u2014 showing bytes ${start}\u2013${start + shown} of ${total}; pass offset=${start + shown} for the next page` : "";
3035
3065
  const header = `${file.fileName ?? "file"} (${file.mimeType ?? "?"}, ${total} bytes)${more}
3036
- ${file.downloadUrl ? `downloadUrl: ${file.downloadUrl}
3066
+ ${file.downloadUrl ? `downloadUrl (signed-in project members only; read bytes with this tool): ${file.downloadUrl}
3037
3067
  ` : ""}---
3038
3068
  `;
3039
3069
  return [{ type: "text", text: header + content }];
@@ -3159,10 +3189,24 @@ function registerSetFileTags(server2, conn2) {
3159
3189
  }
3160
3190
  );
3161
3191
  }
3192
+ function registerDeleteAttachment(server2, conn2) {
3193
+ registerContractTool(server2, deleteAttachmentContract, async (params) => {
3194
+ const result = await conn2.deleteAttachment(params.taskId, params.fileId, params.projectId);
3195
+ return {
3196
+ content: [
3197
+ {
3198
+ type: "text",
3199
+ text: `Deleted ${result.fileName} (${result.id}) permanently. Any chat message that announced it keeps its text without the attachment.`
3200
+ }
3201
+ ]
3202
+ };
3203
+ });
3204
+ }
3162
3205
  function registerAttachmentTools(server2, conn2) {
3163
3206
  registerListTaskFiles(server2, conn2);
3164
3207
  registerGetAttachment(server2, conn2);
3165
3208
  registerUploadAttachment(server2, conn2);
3209
+ registerDeleteAttachment(server2, conn2);
3166
3210
  registerSetFileTags(server2, conn2);
3167
3211
  }
3168
3212
 
@@ -3701,6 +3745,35 @@ var DEFAULT_TASK_STATUS_COLOR_INT = Number.parseInt(DEFAULT_TASK_STATUS_COLOR.sl
3701
3745
  var MAX_FILE_SIZE_BYTES2 = 25 * 1024 * 1024;
3702
3746
  var MAX_FILE_TAGS2 = 5;
3703
3747
  var MAX_FILE_TAG_LENGTH = 100;
3748
+ var ALLOWED_FILE_MIME_TYPES = [
3749
+ "image/png",
3750
+ "image/jpeg",
3751
+ "image/gif",
3752
+ "image/webp",
3753
+ "application/json",
3754
+ "text/csv",
3755
+ "text/plain",
3756
+ "text/markdown",
3757
+ "text/vnd.mermaid",
3758
+ "application/pdf",
3759
+ // Reports (conveyor-consensus and friends) are single-file, no-JS HTML. Safe
3760
+ // to store because the DOWNLOAD route serves these under a sandbox CSP with
3761
+ // an opaque origin — see SANDBOXED_MIME in services/file/routes.ts.
3762
+ "text/html",
3763
+ // Office documents: the OOXML trio only (legacy .doc/.xls/.ppt stay out).
3764
+ // Served inline like PDFs; browsers download them and nothing renders
3765
+ // in-origin, so they need no SANDBOXED_MIME entry.
3766
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
3767
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
3768
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation"
3769
+ ];
3770
+ var ALLOWED_FILE_ACCEPT = [
3771
+ ...ALLOWED_FILE_MIME_TYPES,
3772
+ // Extensions too: a mime-only `accept` filters the OS picker by its own mime
3773
+ // registry, which greys out .md/.mmd (and Office files on a machine without
3774
+ // Office) even though the upload would succeed.
3775
+ ".png,.jpg,.jpeg,.gif,.webp,.json,.csv,.txt,.md,.mmd,.pdf,.html,.docx,.xlsx,.pptx"
3776
+ ].join(",");
3704
3777
  var EMBED_THRESHOLD_IMAGES = 5 * 1024 * 1024;
3705
3778
  var EMBED_THRESHOLD_TEXT = 2 * 1024 * 1024;
3706
3779
  var IDLE_HEARTBEAT_MS = 90 * 1e3;
@@ -3896,9 +3969,15 @@ var GetChatMessagesRequestSchema = z32.object({
3896
3969
  taskId: z32.string().optional()
3897
3970
  });
3898
3971
  var GetTaskFilesRequestSchema = z32.object({
3899
- sessionId: z32.string()
3972
+ sessionId: z32.string(),
3973
+ taskId: z32.string().optional()
3900
3974
  });
3901
3975
  var GetTaskFileRequestSchema = z32.object({
3976
+ sessionId: z32.string(),
3977
+ fileId: z32.string(),
3978
+ taskId: z32.string().optional()
3979
+ });
3980
+ var DeleteTaskFileRequestSchema = z32.object({
3902
3981
  sessionId: z32.string(),
3903
3982
  fileId: z32.string()
3904
3983
  });
@@ -4828,6 +4907,12 @@ var GetProjectAttachmentRequestSchema = z52.object({
4828
4907
  /** Max bytes of text content to return from `offset`. Server default applies. */
4829
4908
  maxBytes: z52.number().int().positive().optional()
4830
4909
  });
4910
+ var DeleteProjectTaskFileRequestSchema = z52.object({
4911
+ projectId: z52.string(),
4912
+ taskId: z52.string(),
4913
+ fileId: z52.string(),
4914
+ requestingUserId: z52.string().optional()
4915
+ });
4831
4916
  var RequestProjectFileUploadRequestSchema = z52.object({
4832
4917
  projectId: z52.string(),
4833
4918
  taskId: z52.string(),
@@ -5185,6 +5270,10 @@ var CancelDecisionRequestSchema = z102.object({
5185
5270
  /** Why it is being dropped. Posted to the decision thread. */
5186
5271
  reason: z102.string().max(DECISION_RESOLUTION_MAX).optional()
5187
5272
  });
5273
+ var BulkDecisionIdsRequestSchema = z102.object({
5274
+ projectId: z102.string().cuid("Invalid project ID"),
5275
+ decisionIds: z102.array(z102.string().cuid()).min(1).max(200)
5276
+ });
5188
5277
  var ReopenDecisionRequestSchema = z102.object({
5189
5278
  decisionId: decisionIdSchema,
5190
5279
  deadlineHours: z102.number().min(DECISION_DEADLINE_MIN_HOURS).max(DECISION_DEADLINE_MAX_HOURS).optional()
@@ -5449,8 +5538,8 @@ function anthropicEntry(model, label, inputPerMillion, outputPerMillion, opts =
5449
5538
  };
5450
5539
  }
5451
5540
  var ANTHROPIC_CATALOG = [
5452
- anthropicEntry(DEFAULT_OPUS_MODEL, "Opus 5 Latest", 5, 25),
5453
- anthropicEntry(PREVIOUS_OPUS_MODEL, "Opus 4.8", 5, 25),
5541
+ anthropicEntry(DEFAULT_OPUS_MODEL, "Opus 5.5 Latest", 4, 20),
5542
+ anthropicEntry(PREVIOUS_OPUS_MODEL, "Opus 5", 5, 25),
5454
5543
  anthropicEntry(DEFAULT_SONNET_MODEL, "Sonnet 5 Latest", 3, 15),
5455
5544
  anthropicEntry(PREVIOUS_SONNET_MODEL, "Sonnet 4.6", 3, 15),
5456
5545
  // The Haiku line (4.5 and older) predates the tuning surface and 400s on it.
@@ -1,5 +1,5 @@
1
1
  import { io, Socket } from 'socket.io-client';
2
- import { ListDriveFilesResponse, ReadDriveFileResponse, DriveFileDTO, DeleteDriveFileResponse, ProjectIntegrationsSummary, GaAnalyticsSummaryDTO, ProjectChannelDTO, ReadChannelMessagesResponse, PostChannelMessageResponse, CreateProjectDecisionRequest, CreateProjectDecisionResponse, ListProjectDecisionsRequest, ProjectDecisionRow, ProjectDecisionDetail, VoteProjectDecisionRequest, ResolveProjectDecisionRequest, UpdateProjectDecisionRequest, ListMeetingsResponse, MeetingForAgent, ReadMeetingTranscriptResponse, MeetingChecklistItemForAgent } from '@project/shared';
2
+ import { ListDriveFilesResponse, ReadDriveFileResponse, DriveFileDTO, DeleteDriveFileResponse, ProjectIntegrationsSummary, GaAnalyticsSummaryDTO, ProjectChannelDTO, ReadChannelMessagesResponse, PostChannelMessageResponse, CreateProjectDecisionRequest, CreateProjectDecisionResponse, ListProjectDecisionsRequest, ProjectDecisionRow, ProjectDecisionDetail, VoteProjectDecisionRequest, ResolveProjectDecisionRequest, UpdateProjectDecisionRequest, ListMeetingsResponse, MeetingForAgent, ReadMeetingTranscriptResponse, MeetingChecklistItemForAgent, DeletedTaskFile } from '@project/shared';
3
3
 
4
4
  interface ConveyorMcpConfig {
5
5
  apiUrl: string;
@@ -818,6 +818,7 @@ declare class ConveyorConnection {
818
818
  appliedTags?: string[];
819
819
  unknownTags?: string[];
820
820
  }>;
821
+ deleteAttachment(taskId: string, fileId: string, projectId?: string): Promise<DeletedTaskFile>;
821
822
  createRelease(taskIds?: string[], projectId?: string): Promise<{
822
823
  taskId: string;
823
824
  version: string;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as ActivePtySession, d as ConveyorConnection, e as ConveyorMcpConfig, P as PtyAttachSnapshot, c as PtyDataChunk } from './connection-DeBZ_T6f.js';
1
+ export { A as ActivePtySession, d as ConveyorConnection, e as ConveyorMcpConfig, P as PtyAttachSnapshot, c as PtyDataChunk } from './connection-K8I1nT9o.js';
2
2
  export { AttachTunnelOptions, ResolvedPtySession, RunTunnelOptions, TunnelConnection, TunnelHandle, TunnelSession, TunnelTty, WaitForPtySessionOptions, attachTunnel, runTunnel, waitForPtySession } from './tunnel.js';
3
3
  import 'socket.io-client';
4
4
  import '@project/shared';
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  } from "./chunk-HIVOGGE3.js";
6
6
  import {
7
7
  ConveyorConnection
8
- } from "./chunk-77XLXIFP.js";
8
+ } from "./chunk-L3AI3EU2.js";
9
9
  export {
10
10
  ConveyorConnection,
11
11
  attachTunnel,
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-5KU3QS6A.js";
8
8
  import {
9
9
  ConveyorConnection
10
- } from "./chunk-77XLXIFP.js";
10
+ } from "./chunk-L3AI3EU2.js";
11
11
 
12
12
  // src/tunnel-cli.ts
13
13
  var HELP = `conveyor-tunnel \u2014 attach your local terminal to a cloud Claude Code session.
package/dist/tunnel.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { A as ActivePtySession, P as PtyAttachSnapshot, c as PtyDataChunk } from './connection-DeBZ_T6f.js';
1
+ import { A as ActivePtySession, P as PtyAttachSnapshot, c as PtyDataChunk } from './connection-K8I1nT9o.js';
2
2
  import 'socket.io-client';
3
3
  import '@project/shared';
4
4
 
package/dist/wait-cli.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-5KU3QS6A.js";
5
5
  import {
6
6
  ConveyorConnection
7
- } from "./chunk-77XLXIFP.js";
7
+ } from "./chunk-L3AI3EU2.js";
8
8
  import {
9
9
  runWait
10
10
  } from "./chunk-OPZL4NDT.js";
@@ -1,4 +1,4 @@
1
- import { C as CardCollectionPage, a as CardCollectionDelta } from './connection-DeBZ_T6f.js';
1
+ import { C as CardCollectionPage, a as CardCollectionDelta } from './connection-K8I1nT9o.js';
2
2
  import { WaitFilter, WaitResult } from './wait.js';
3
3
  import 'socket.io-client';
4
4
  import '@project/shared';
package/dist/wait.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { b as CardCollectionItem } from './connection-DeBZ_T6f.js';
1
+ import { b as CardCollectionItem } from './connection-K8I1nT9o.js';
2
2
  import 'socket.io-client';
3
3
  import '@project/shared';
4
4
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rallycry/conveyor-mcp",
3
- "version": "5.0.6",
3
+ "version": "5.0.8",
4
4
  "description": "Conveyor MCP server for Claude Code PM integration",
5
5
  "keywords": [
6
6
  "claude",
@@ -45,6 +45,6 @@
45
45
  "@types/ws": "^8.18.1",
46
46
  "tsup": "^8.0.0",
47
47
  "typescript": "^5.3.0",
48
- "vitest": "^4.0.17"
48
+ "vitest": "^5.0.1"
49
49
  }
50
50
  }