@rallycry/conveyor-agent 11.0.40 → 11.0.41
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-UB7QZE25.js → chunk-CG7AHC25.js} +396 -364
- package/dist/{chunk-RZNNJUGW.js → chunk-G2CE3NFY.js} +1 -1
- package/dist/{chunk-GI2FF7FX.js → chunk-SELXSOT7.js} +141 -55
- package/dist/cli.js +4 -4
- package/dist/index.js +2 -2
- package/dist/{serve-boot-ZJ4BI7P2.js → serve-boot-YARBQBSA.js} +2 -2
- package/package.json +1 -1
- package/skills/conveyor-build/SKILL.md +14 -5
- package/skills/conveyor-release-review/SKILL.md +372 -0
- package/skills/conveyor-release-review/references/dimensions.md +289 -0
- package/skills/conveyor-release-review/references/report-and-cards.md +183 -0
- package/skills/conveyor-workflows/SKILL.md +1 -0
|
@@ -97,7 +97,7 @@ import {
|
|
|
97
97
|
statWorkspacePath,
|
|
98
98
|
updateRemoteToken,
|
|
99
99
|
verifyGitCredential
|
|
100
|
-
} from "./chunk-
|
|
100
|
+
} from "./chunk-CG7AHC25.js";
|
|
101
101
|
import {
|
|
102
102
|
registerBootMilestoneSocketFallback,
|
|
103
103
|
reportBootMilestone
|
|
@@ -7350,6 +7350,7 @@ function defineToolContract(contract) {
|
|
|
7350
7350
|
var mcpProjectId = f.optional(f.string({ desc: "Target Conveyor project ID" }));
|
|
7351
7351
|
var cardDescriptionDesc = (lead) => `${lead} \u2014 ${CARD_DESCRIPTION_FIELD_HINT}`;
|
|
7352
7352
|
var storyPointValueDesc = "Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique)";
|
|
7353
|
+
var priorityValueDesc = "Priority value from manage_priorities list (1 = the project's highest level; seeded defaults are 1=High, 2=Medium, 3=Low)";
|
|
7353
7354
|
var getTaskContract = defineToolContract({
|
|
7354
7355
|
name: "get_task",
|
|
7355
7356
|
agent: {
|
|
@@ -7583,7 +7584,7 @@ var updateTaskContract = defineToolContract({
|
|
|
7583
7584
|
}
|
|
7584
7585
|
},
|
|
7585
7586
|
mcp: {
|
|
7586
|
-
description: "Update task fields: title, description, plan, status, risk, story points, assignment, githubBranch, onHold, or tags. Set status to claim a card (InProgress), triage it (Open), or cancel it (Cancelled); for review approvals prefer approve_task / request_changes, which guard against stale-state races. Set onHold to park a card (true) or bring it back to the active board (false) without cancelling it. Tags are additive/subtractive \u2014 pass addTags/removeTags with tag names (not a replace-set). Pass projectId to target a specific project; otherwise the configured default project is used. Moving a task beyond Planning auto-fills any missing icon, story points, and agent assignment \u2014 don't spend turns on them; pass storyPointValue only to correct the sizing yourself. For subtasks use update_subtask.",
|
|
7587
|
+
description: "Update task fields: title, description, plan, status, risk, story points, priority, assignment, githubBranch, onHold, or tags. Set status to claim a card (InProgress), triage it (Open), or cancel it (Cancelled); for review approvals prefer approve_task / request_changes, which guard against stale-state races. Set onHold to park a card (true) or bring it back to the active board (false) without cancelling it. Tags are additive/subtractive \u2014 pass addTags/removeTags with tag names (not a replace-set). Pass projectId to target a specific project; otherwise the configured default project is used. Moving a task beyond Planning auto-fills any missing icon, story points, and agent assignment \u2014 don't spend turns on them; pass storyPointValue only to correct the sizing yourself. For subtasks use update_subtask.",
|
|
7587
7588
|
fields: {
|
|
7588
7589
|
projectId: mcpProjectId,
|
|
7589
7590
|
taskId: f.string({ desc: "The task ID" }),
|
|
@@ -7605,6 +7606,13 @@ var updateTaskContract = defineToolContract({
|
|
|
7605
7606
|
})
|
|
7606
7607
|
)
|
|
7607
7608
|
),
|
|
7609
|
+
priorityValue: f.optional(
|
|
7610
|
+
f.nullable(
|
|
7611
|
+
f.number({
|
|
7612
|
+
desc: `${priorityValueDesc}. The levels are per-project \u2014 a value the project has not configured is rejected. Pass null to clear it.`
|
|
7613
|
+
})
|
|
7614
|
+
)
|
|
7615
|
+
),
|
|
7608
7616
|
assignedUserId: f.optional(f.nullable(f.string({ desc: "User ID to assign, or null" }))),
|
|
7609
7617
|
subProjectId: f.optional(
|
|
7610
7618
|
f.nullable(
|
|
@@ -8066,13 +8074,13 @@ var agentTaskIdOrSlug = f.optional(
|
|
|
8066
8074
|
var listTaskFilesContract = defineToolContract({
|
|
8067
8075
|
name: "list_task_files",
|
|
8068
8076
|
agent: {
|
|
8069
|
-
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.",
|
|
8077
|
+
description: "List all files attached to this task with metadata. Showcase files (the card's deliverables, `showcase: true` on each row) list first; a row with `supersedesFileId` is a newer version of that file. 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.",
|
|
8070
8078
|
fields: {
|
|
8071
8079
|
task_id: agentTaskIdOrSlug
|
|
8072
8080
|
}
|
|
8073
8081
|
},
|
|
8074
8082
|
mcp: {
|
|
8075
|
-
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.",
|
|
8083
|
+
description: "List all files attached to a task with metadata (no contents \u2014 fast and small). Showcase files (the card's deliverables, `showcase: true` on each row) list first; a row with `supersedesFileId` is a newer version of that file. 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.",
|
|
8076
8084
|
fields: {
|
|
8077
8085
|
projectId: mcpProjectId,
|
|
8078
8086
|
taskId: mcpTaskIdOrSlug
|
|
@@ -8116,10 +8124,20 @@ var attachmentTags = f.optional(
|
|
|
8116
8124
|
desc: `Glossary tag names this file is a relevant example of. MUST be a JSON array of quoted strings, e.g. ["ops-hub", "platform-support"] \u2014 bare unquoted words are invalid JSON and fail the whole call before it is parsed (21 fleet calls in one week died this way). Use it when the file shows a tagged entity in a particular state: the tag's page lists its recent tagged attachments, so a reader can see what the entity looks like across the app and spot visual changes over time. Names are matched case-insensitively within the project; a name that matches no tag is reported back and never fails the upload. Max 5.`
|
|
8117
8125
|
})
|
|
8118
8126
|
);
|
|
8127
|
+
var attachmentShowcase = f.optional(
|
|
8128
|
+
f.boolean({
|
|
8129
|
+
desc: "Mark this file as a showcase: the finished result of the card. Showcase files render first with a thumbnail on the card, are what a tag gallery shows, always post to chat, get a long-lived link, are kept past the 90-day purge, and are appended to the PR body under '## Showcase'. Use it for the final capture, not for scoping or before shots."
|
|
8130
|
+
})
|
|
8131
|
+
);
|
|
8132
|
+
var attachmentSupersedes = f.optional(
|
|
8133
|
+
f.string({
|
|
8134
|
+
desc: "File id (from list_task_files) of an older file on this card that this upload replaces, e.g. the previous cut of a video. The old file loses showcase and collapses under the new one as history; the new one inherits its showcase flag and tag labels. Naming a file that already has a newer version replaces the newest one. A bad id never fails the upload \u2014 the reason comes back instead."
|
|
8135
|
+
})
|
|
8136
|
+
);
|
|
8119
8137
|
var uploadAttachmentContract = defineToolContract({
|
|
8120
8138
|
name: "upload_attachment",
|
|
8121
8139
|
agent: {
|
|
8122
|
-
description: "Upload a file (doc, notes, data, diagram, screenshot \u2014 any file type, up to 25MB) as a task attachment AND post it to the task chat in one step \u2014 no follow-up post_to_chat call needed. This is how you deliver a file the user should keep: it attaches to the card. Never publish deliverables as an external Claude artifact. Pass `tags` when the file is a good example of a glossary tag in some state.",
|
|
8140
|
+
description: "Upload a file (doc, notes, data, diagram, screenshot \u2014 any file type, up to 25MB) as a task attachment AND post it to the task chat in one step \u2014 no follow-up post_to_chat call needed. This is how you deliver a file the user should keep: it attaches to the card. Never publish deliverables as an external Claude artifact. Pass `showcase: true` for the capture that shows the finished result, `supersedes` with the old file's id when this is a newer version of a file already on the card, and `tags` when the file is a good example of a glossary tag in some state.",
|
|
8123
8141
|
fields: {
|
|
8124
8142
|
path: f.string({
|
|
8125
8143
|
desc: "Path to the file \u2014 absolute, or relative to the workspace root"
|
|
@@ -8132,11 +8150,13 @@ var uploadAttachmentContract = defineToolContract({
|
|
|
8132
8150
|
desc: "Alias of `title` (the external conveyor-mcp surface names this field `comment`). Provide at most one of the two."
|
|
8133
8151
|
})
|
|
8134
8152
|
),
|
|
8135
|
-
tags: attachmentTags
|
|
8153
|
+
tags: attachmentTags,
|
|
8154
|
+
showcase: attachmentShowcase,
|
|
8155
|
+
supersedes: attachmentSupersedes
|
|
8136
8156
|
}
|
|
8137
8157
|
},
|
|
8138
8158
|
mcp: {
|
|
8139
|
-
description: "Upload a local file as a task attachment (any file type, up to 25MB). Pass projectId to target a specific project; otherwise the configured default project is used. The file appears under the task's Files. Pass `comment` to also post it to the task chat in the same step, and `tags` when the file is a good example of a glossary tag in some state.",
|
|
8159
|
+
description: "Upload a local file as a task attachment (any file type, up to 25MB). Pass projectId to target a specific project; otherwise the configured default project is used. The file appears under the task's Files. Pass `comment` to also post it to the task chat in the same step, `showcase: true` for the capture that shows the finished result (a showcase file always posts to chat), `supersedes` with the old file's id when this is a newer version of a file already on the card, and `tags` when the file is a good example of a glossary tag in some state.",
|
|
8140
8160
|
fields: {
|
|
8141
8161
|
projectId: mcpProjectId,
|
|
8142
8162
|
taskId: mcpTaskIdOrSlug,
|
|
@@ -8150,6 +8170,8 @@ var uploadAttachmentContract = defineToolContract({
|
|
|
8150
8170
|
})
|
|
8151
8171
|
),
|
|
8152
8172
|
tags: attachmentTags,
|
|
8173
|
+
showcase: attachmentShowcase,
|
|
8174
|
+
supersedes: attachmentSupersedes,
|
|
8153
8175
|
mimeType: f.optional(
|
|
8154
8176
|
f.string({ desc: "Override the mime type inferred from the file extension" })
|
|
8155
8177
|
)
|
|
@@ -8174,11 +8196,35 @@ var deleteAttachmentContract = defineToolContract({
|
|
|
8174
8196
|
}
|
|
8175
8197
|
}
|
|
8176
8198
|
});
|
|
8199
|
+
var SET_SHOWCASE_BEHAVIOR = "Mark an already-uploaded attachment as the card's showcase (`showcase: true`) or clear the flag (`showcase: false`) \u2014 the same flag upload_attachment sets at upload time, so promote an earlier capture here instead of uploading it again. A flip to showcase posts the file to the task chat once; a file that a chat message already carries is not posted again. `fileId` comes from list_task_files.";
|
|
8200
|
+
var showcaseFlag = f.boolean({
|
|
8201
|
+
desc: "true marks the file as the card's showcase; false clears the flag."
|
|
8202
|
+
});
|
|
8203
|
+
var setShowcaseContract = defineToolContract({
|
|
8204
|
+
name: "set_showcase",
|
|
8205
|
+
agent: {
|
|
8206
|
+
description: `${SET_SHOWCASE_BEHAVIOR} A pod can only change files on its own card.`,
|
|
8207
|
+
fields: {
|
|
8208
|
+
fileId: f.string({ desc: "The file ID to change" }),
|
|
8209
|
+
showcase: showcaseFlag
|
|
8210
|
+
}
|
|
8211
|
+
},
|
|
8212
|
+
mcp: {
|
|
8213
|
+
description: `${SET_SHOWCASE_BEHAVIOR} Requires Moderate on the project, the same bar as the star on the card's Files list. Pass projectId to target a specific project; otherwise the configured default project is used.`,
|
|
8214
|
+
fields: {
|
|
8215
|
+
projectId: mcpProjectId,
|
|
8216
|
+
taskId: f.string({ desc: "The task ID or slug the file is attached to" }),
|
|
8217
|
+
fileId: f.string({ desc: "The file ID to change" }),
|
|
8218
|
+
showcase: showcaseFlag
|
|
8219
|
+
}
|
|
8220
|
+
}
|
|
8221
|
+
});
|
|
8177
8222
|
var attachmentsContracts = [
|
|
8178
8223
|
listTaskFilesContract,
|
|
8179
8224
|
getAttachmentContract,
|
|
8180
8225
|
uploadAttachmentContract,
|
|
8181
|
-
deleteAttachmentContract
|
|
8226
|
+
deleteAttachmentContract,
|
|
8227
|
+
setShowcaseContract
|
|
8182
8228
|
];
|
|
8183
8229
|
var createSuggestionContract = defineToolContract({
|
|
8184
8230
|
name: "create_suggestion",
|
|
@@ -8501,7 +8547,7 @@ var createPullRequestContract = defineToolContract({
|
|
|
8501
8547
|
fields: {
|
|
8502
8548
|
title: f.string({ desc: "The PR title" }),
|
|
8503
8549
|
body: f.string({
|
|
8504
|
-
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 ( 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."
|
|
8550
|
+
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 ( 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. Showcase attachments (uploaded with `showcase: true`) are appended under '## Showcase' automatically when Conveyor creates the PR; mention them inline yourself only if you want them next to specific text."
|
|
8505
8551
|
}),
|
|
8506
8552
|
branch: f.optional(
|
|
8507
8553
|
f.string({
|
|
@@ -8532,7 +8578,7 @@ var createPullRequestContract = defineToolContract({
|
|
|
8532
8578
|
taskId: f.string({ desc: "The task ID whose branch should be opened as a PR" }),
|
|
8533
8579
|
title: f.string({ desc: "Pull request title" }),
|
|
8534
8580
|
body: f.string({
|
|
8535
|
-
desc: "Pull request body (markdown). For a diff that changes rendered UI, embed the visual proof inline: upload the capture with upload_attachment and paste the downloadUrl it returns as , in addition to leaving it on the card."
|
|
8581
|
+
desc: "Pull request body (markdown). For a diff that changes rendered UI, embed the visual proof inline: upload the capture with upload_attachment and paste the downloadUrl it returns as , in addition to leaving it on the card. Showcase attachments (uploaded with `showcase: true`) are appended under '## Showcase' automatically when Conveyor creates the PR; mention them inline yourself only if you want them next to specific text."
|
|
8536
8582
|
}),
|
|
8537
8583
|
head: f.optional(
|
|
8538
8584
|
f.string({ desc: "Source branch for the PR (defaults to the task's branch)" })
|
|
@@ -10137,6 +10183,8 @@ var MIME_BY_EXT = {
|
|
|
10137
10183
|
".gz": "application/gzip",
|
|
10138
10184
|
".mp4": "video/mp4",
|
|
10139
10185
|
".webm": "video/webm",
|
|
10186
|
+
".mov": "video/quicktime",
|
|
10187
|
+
".m4v": "video/x-m4v",
|
|
10140
10188
|
".mp3": "audio/mpeg",
|
|
10141
10189
|
".wav": "audio/wav"
|
|
10142
10190
|
};
|
|
@@ -10151,20 +10199,28 @@ function describeTags(applied, unknown) {
|
|
|
10151
10199
|
}
|
|
10152
10200
|
return parts.join("");
|
|
10153
10201
|
}
|
|
10202
|
+
function describeSupersede(superseded, error) {
|
|
10203
|
+
if (superseded) {
|
|
10204
|
+
return ` Replaces ${superseded.fileName} (${superseded.fileId}), which now collapses under it as history.`;
|
|
10205
|
+
}
|
|
10206
|
+
if (error) return ` Did not replace the older file: ${error}.`;
|
|
10207
|
+
return "";
|
|
10208
|
+
}
|
|
10154
10209
|
var EMBEDDABLE_IN_MARKDOWN = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".webp"]);
|
|
10155
|
-
function describeEmbed(fileName, downloadUrl) {
|
|
10210
|
+
function describeEmbed(fileName, downloadUrl, showcase) {
|
|
10156
10211
|
if (!downloadUrl) return "";
|
|
10157
10212
|
const isImage = EMBEDDABLE_IN_MARKDOWN.has(extname(fileName).toLowerCase());
|
|
10213
|
+
const lead = showcase ? "Put this line under '## Showcase' in the PR body (the server adds it if you forget)" : "Paste this into the PR description";
|
|
10158
10214
|
if (isImage) {
|
|
10159
10215
|
return `
|
|
10160
10216
|
|
|
10161
|
-
|
|
10217
|
+
${lead} to show it inline:
|
|
10162
10218
|
`;
|
|
10163
10219
|
}
|
|
10164
10220
|
if (isCapabilityServableMime(inferMimeType(fileName))) {
|
|
10165
10221
|
return `
|
|
10166
10222
|
|
|
10167
|
-
|
|
10223
|
+
${lead} to link it:
|
|
10168
10224
|
[${fileName}](${downloadUrl})`;
|
|
10169
10225
|
}
|
|
10170
10226
|
return `
|
|
@@ -10172,69 +10228,98 @@ Paste this into the PR description to link it:
|
|
|
10172
10228
|
downloadUrl (signed-in project members only; agents read it with get_attachment): ${downloadUrl}`;
|
|
10173
10229
|
}
|
|
10174
10230
|
function buildUploadAttachmentTool(connection, config) {
|
|
10175
|
-
return defineContractTool(
|
|
10176
|
-
|
|
10177
|
-
|
|
10178
|
-
const
|
|
10179
|
-
|
|
10180
|
-
|
|
10181
|
-
|
|
10182
|
-
|
|
10183
|
-
|
|
10184
|
-
|
|
10231
|
+
return defineContractTool(
|
|
10232
|
+
uploadAttachmentContract,
|
|
10233
|
+
async ({ path, title, comment, tags, showcase, supersedes }) => {
|
|
10234
|
+
const caption = title ?? comment;
|
|
10235
|
+
try {
|
|
10236
|
+
const filePath = isAbsolute(path) ? path : join17(config.workspaceDir, path);
|
|
10237
|
+
const mimeType = inferMimeType(filePath);
|
|
10238
|
+
const info = await statWorkspacePath(filePath);
|
|
10239
|
+
if (!info.isFile) {
|
|
10240
|
+
return textResult(`File not found: ${filePath}`);
|
|
10241
|
+
}
|
|
10242
|
+
if (info.size > MAX_FILE_SIZE_BYTES) {
|
|
10243
|
+
return textResult(
|
|
10244
|
+
`File is ${info.size} bytes \u2014 exceeds the ${MAX_FILE_SIZE_BYTES} byte (25MB) upload limit.`
|
|
10245
|
+
);
|
|
10246
|
+
}
|
|
10247
|
+
const fileName = basename2(filePath);
|
|
10248
|
+
const { fileId, uploadUrl } = await connection.call("requestFileUpload", {
|
|
10249
|
+
sessionId: connection.sessionId,
|
|
10250
|
+
fileName,
|
|
10251
|
+
mimeType,
|
|
10252
|
+
fileSize: info.size
|
|
10253
|
+
});
|
|
10254
|
+
const bytes = await readWorkspaceBytes(filePath);
|
|
10255
|
+
const res = await fetch(uploadUrl, {
|
|
10256
|
+
method: "PUT",
|
|
10257
|
+
headers: { "Content-Type": mimeType },
|
|
10258
|
+
// Normalize to a plain Uint8Array: the workbench proxy hands back a
|
|
10259
|
+
// Buffer<ArrayBufferLike> that newer @types/node rejects as a BodyInit.
|
|
10260
|
+
body: new Uint8Array(bytes)
|
|
10261
|
+
});
|
|
10262
|
+
if (!res.ok) {
|
|
10263
|
+
return textResult(
|
|
10264
|
+
`Upload to storage failed: HTTP ${res.status} ${await res.text().catch(() => "")}`
|
|
10265
|
+
);
|
|
10266
|
+
}
|
|
10267
|
+
const result = await connection.call("confirmFileUpload", {
|
|
10268
|
+
sessionId: connection.sessionId,
|
|
10269
|
+
fileId,
|
|
10270
|
+
title: caption,
|
|
10271
|
+
tags,
|
|
10272
|
+
// Omitted when unset so the payload stays byte-identical for callers
|
|
10273
|
+
// that never heard of the flag.
|
|
10274
|
+
...showcase === void 0 ? {} : { showcase },
|
|
10275
|
+
...supersedes ? { supersedes } : {}
|
|
10276
|
+
});
|
|
10277
|
+
const isShowcase = result.showcase === true;
|
|
10185
10278
|
return textResult(
|
|
10186
|
-
|
|
10279
|
+
`${isShowcase ? "Showcase attachment. " : ""}Uploaded ${fileName} (${info.size} bytes) and posted it to the task chat${caption ? ` with caption "${caption}"` : ""}. File ID: ${result.fileId}${describeTags(result.appliedTags, result.unknownTags)}${describeSupersede(result.superseded, result.supersedeError)}${describeEmbed(fileName, result.downloadUrl, isShowcase)}`
|
|
10187
10280
|
);
|
|
10188
|
-
}
|
|
10189
|
-
const fileName = basename2(filePath);
|
|
10190
|
-
const { fileId, uploadUrl } = await connection.call("requestFileUpload", {
|
|
10191
|
-
sessionId: connection.sessionId,
|
|
10192
|
-
fileName,
|
|
10193
|
-
mimeType,
|
|
10194
|
-
fileSize: info.size
|
|
10195
|
-
});
|
|
10196
|
-
const bytes = await readWorkspaceBytes(filePath);
|
|
10197
|
-
const res = await fetch(uploadUrl, {
|
|
10198
|
-
method: "PUT",
|
|
10199
|
-
headers: { "Content-Type": mimeType },
|
|
10200
|
-
// Normalize to a plain Uint8Array: the workbench proxy hands back a
|
|
10201
|
-
// Buffer<ArrayBufferLike> that newer @types/node rejects as a BodyInit.
|
|
10202
|
-
body: new Uint8Array(bytes)
|
|
10203
|
-
});
|
|
10204
|
-
if (!res.ok) {
|
|
10281
|
+
} catch (error) {
|
|
10205
10282
|
return textResult(
|
|
10206
|
-
`
|
|
10283
|
+
`Failed to upload attachment: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
10207
10284
|
);
|
|
10208
10285
|
}
|
|
10209
|
-
|
|
10286
|
+
}
|
|
10287
|
+
);
|
|
10288
|
+
}
|
|
10289
|
+
function buildDeleteAttachmentTool(connection) {
|
|
10290
|
+
return defineContractTool(deleteAttachmentContract, async ({ fileId }) => {
|
|
10291
|
+
try {
|
|
10292
|
+
const result = await connection.call("deleteTaskFile", {
|
|
10210
10293
|
sessionId: connection.sessionId,
|
|
10211
|
-
fileId
|
|
10212
|
-
title: caption,
|
|
10213
|
-
tags
|
|
10294
|
+
fileId
|
|
10214
10295
|
});
|
|
10215
10296
|
return textResult(
|
|
10216
|
-
`
|
|
10297
|
+
`Deleted ${result.fileName} (${result.id}) permanently. Any chat message that announced it keeps its text without the attachment.`
|
|
10217
10298
|
);
|
|
10218
10299
|
} catch (error) {
|
|
10219
10300
|
return textResult(
|
|
10220
|
-
`Failed to
|
|
10301
|
+
`Failed to delete attachment: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
10221
10302
|
);
|
|
10222
10303
|
}
|
|
10223
10304
|
});
|
|
10224
10305
|
}
|
|
10225
|
-
function
|
|
10226
|
-
return defineContractTool(
|
|
10306
|
+
function buildSetShowcaseTool(connection) {
|
|
10307
|
+
return defineContractTool(setShowcaseContract, async ({ fileId, showcase }) => {
|
|
10227
10308
|
try {
|
|
10228
|
-
const result = await connection.call("
|
|
10309
|
+
const result = await connection.call("setTaskFileShowcase", {
|
|
10229
10310
|
sessionId: connection.sessionId,
|
|
10230
|
-
fileId
|
|
10311
|
+
fileId,
|
|
10312
|
+
showcase
|
|
10231
10313
|
});
|
|
10314
|
+
if (!result.showcase) {
|
|
10315
|
+
return textResult(`${result.fileName} (${result.id}) is no longer a showcase file.`);
|
|
10316
|
+
}
|
|
10232
10317
|
return textResult(
|
|
10233
|
-
|
|
10318
|
+
`${result.fileName} (${result.id}) is now a showcase file. It is in the task chat and the server adds it to the PR body under '## Showcase'.${describeEmbed(result.fileName, result.downloadUrl, true)}`
|
|
10234
10319
|
);
|
|
10235
10320
|
} catch (error) {
|
|
10236
10321
|
return textResult(
|
|
10237
|
-
`Failed to
|
|
10322
|
+
`Failed to set showcase: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
10238
10323
|
);
|
|
10239
10324
|
}
|
|
10240
10325
|
});
|
|
@@ -10470,7 +10555,8 @@ function buildCommonTools(connection, config) {
|
|
|
10470
10555
|
...buildMutationTools(connection, config),
|
|
10471
10556
|
buildUpdateIncidentTool(connection),
|
|
10472
10557
|
buildUploadAttachmentTool(connection, config),
|
|
10473
|
-
buildDeleteAttachmentTool(connection)
|
|
10558
|
+
buildDeleteAttachmentTool(connection),
|
|
10559
|
+
buildSetShowcaseTool(connection)
|
|
10474
10560
|
];
|
|
10475
10561
|
}
|
|
10476
10562
|
|
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
WorkspaceCommandSupervisor,
|
|
8
8
|
startWorkspaceCommandsAfterConnect,
|
|
9
9
|
stopWorkspaceCommands
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-G2CE3NFY.js";
|
|
11
11
|
import {
|
|
12
12
|
PtyHarness,
|
|
13
13
|
SessionRunner,
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
runUsageProbe,
|
|
28
28
|
sampleKeyUsage,
|
|
29
29
|
usesNativeUsageReporting
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-SELXSOT7.js";
|
|
31
31
|
import "./chunk-37J5MMQT.js";
|
|
32
32
|
import {
|
|
33
33
|
inheritedEnv,
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
createServiceLogger,
|
|
47
47
|
fetchBootstrap,
|
|
48
48
|
loadConveyorConfig
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-CG7AHC25.js";
|
|
50
50
|
import "./chunk-Q4FQOJ7D.js";
|
|
51
51
|
import "./chunk-W4LZ7R6Z.js";
|
|
52
52
|
import "./chunk-372R6E4C.js";
|
|
@@ -1468,7 +1468,7 @@ if (!RUNNER_MODES.includes(CONVEYOR_MODE)) {
|
|
|
1468
1468
|
process.exit(1);
|
|
1469
1469
|
}
|
|
1470
1470
|
if (CONVEYOR_MODE === "serving") {
|
|
1471
|
-
const { runServingSession } = await import("./serve-boot-
|
|
1471
|
+
const { runServingSession } = await import("./serve-boot-YARBQBSA.js");
|
|
1472
1472
|
exitContext.runnerMode = "serving";
|
|
1473
1473
|
exitContext.sessionId = process.env.CONVEYOR_SESSION_ID ?? exitContext.sessionId;
|
|
1474
1474
|
const outcome = await runServingSession({
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SessionRunner,
|
|
3
3
|
unshallowRepo
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-SELXSOT7.js";
|
|
5
5
|
import "./chunk-37J5MMQT.js";
|
|
6
6
|
import "./chunk-EKTPDG3G.js";
|
|
7
7
|
import {
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
stageAndCommit,
|
|
18
18
|
updateRemoteToken,
|
|
19
19
|
workspacePathExists
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-CG7AHC25.js";
|
|
21
21
|
import "./chunk-Q4FQOJ7D.js";
|
|
22
22
|
import {
|
|
23
23
|
runAuthTokenCommand,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
WorkspaceCommandSupervisor
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-G2CE3NFY.js";
|
|
4
4
|
import {
|
|
5
5
|
AgentConnection,
|
|
6
6
|
CodespacePortVisibility,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
createServiceLogger,
|
|
12
12
|
ensureOnTaskBranch,
|
|
13
13
|
loadConveyorConfig
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-CG7AHC25.js";
|
|
15
15
|
import "./chunk-Q4FQOJ7D.js";
|
|
16
16
|
import "./chunk-W4LZ7R6Z.js";
|
|
17
17
|
import "./chunk-IA45XHOA.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rallycry/conveyor-agent",
|
|
3
|
-
"version": "11.0.
|
|
3
|
+
"version": "11.0.41",
|
|
4
4
|
"description": "Conveyor Agent Runner v10 - PTY harness for the task chat (SDK harness for audit/project-chat). Agent-as-User architecture with BaseService patterns. Works locally too.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -204,7 +204,14 @@ runner: the pod can sleep mid-run and nothing will wake you.
|
|
|
204
204
|
**A UI-visible change needs visual proof before the PR**, in both environments:
|
|
205
205
|
capture a screenshot (static) or a short recording (interaction) with the host
|
|
206
206
|
repo's own tooling and attach it with `mcp__conveyor__upload_attachment`, then
|
|
207
|
-
embed the returned URL in the PR body. A UI PR without it is incomplete.
|
|
207
|
+
embed the returned URL in the PR body. A UI PR without it is incomplete. Pass
|
|
208
|
+
`showcase: true` for the capture that shows the finished result (the after
|
|
209
|
+
shot, the final recording); leave it off for before shots and scoping captures.
|
|
210
|
+
Showcase files post to chat, render first on the card, and land in the PR body
|
|
211
|
+
under `## Showcase`. A re-capture of something already on the card (a new cut
|
|
212
|
+
of the same recording) passes `supersedes: "<old fileId>"` from
|
|
213
|
+
`list_task_files`: the new file takes the old one's star and tags, and the old
|
|
214
|
+
one collapses under it as history instead of showing twice.
|
|
208
215
|
|
|
209
216
|
**Manual tests are for human eyes, and few.** Before the PR, record with
|
|
210
217
|
`mcp__conveyor__set_manual_tests` only what a person must see in the running
|
|
@@ -262,10 +269,12 @@ Instead: post the answer, config, or findings with
|
|
|
262
269
|
`mcp__conveyor__upload_attachment` (any file type, up to 25MB), and complete
|
|
263
270
|
the card directly with `force_update_task_status("Complete")` — there is no PR
|
|
264
271
|
or review step for a no-code task. Never publish a deliverable as an off-card
|
|
265
|
-
link; the card is where it belongs. When a revision
|
|
266
|
-
upload,
|
|
267
|
-
`
|
|
268
|
-
|
|
272
|
+
link; the card is where it belongs. When a revision replaces an earlier
|
|
273
|
+
upload, upload it with `supersedes: "<old fileId>"` (the id from
|
|
274
|
+
`list_task_files`) so the card shows one current version of each deliverable
|
|
275
|
+
with the history collapsed under it. Reach for
|
|
276
|
+
`mcp__conveyor__delete_attachment` (permanent) only for a copy that should not
|
|
277
|
+
survive at all.
|
|
269
278
|
|
|
270
279
|
When unsure, check the diff: a real diff means open a PR, no diff means finish
|
|
271
280
|
in chat and mark it Complete.
|