@rallycry/conveyor-mcp 4.3.13 → 4.3.15
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/cli.js +114 -45
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -140,7 +140,7 @@ function registerUpdateProjectSettings(server2, conn2) {
|
|
|
140
140
|
projectId: z3.string().optional().describe("Target Conveyor project ID"),
|
|
141
141
|
name: z3.string().optional().describe("New project name"),
|
|
142
142
|
description: z3.string().optional().describe("New project description"),
|
|
143
|
-
settings: z3.record(z3.unknown()).optional().describe(
|
|
143
|
+
settings: z3.record(z3.string(), z3.unknown()).optional().describe(
|
|
144
144
|
"Deep-merged patch of the project settings JSON (JSON Merge Patch semantics: null deletes a key; advanced)"
|
|
145
145
|
),
|
|
146
146
|
defaultPmAgentId: z3.string().nullable().optional().describe("Default PM agent ID"),
|
|
@@ -447,13 +447,13 @@ var childTaskIdForMerge = f.string({
|
|
|
447
447
|
var approveAndMergePrContract = defineToolContract({
|
|
448
448
|
name: "approve_and_merge_pr",
|
|
449
449
|
agent: {
|
|
450
|
-
description: "Approve and merge a child task's PR. Preconditions: child in ReviewPR. Returns { merged }: true = merged (status\u2192ReviewDev); false = automerge queued, wait for ReviewDev.",
|
|
450
|
+
description: "Approve and merge a child task's PR. Preconditions: child in ReviewPR. Returns { merged }: true = merged (status\u2192ReviewDev); false = automerge queued, wait for ReviewDev. Requires project Admin, or a sub-project merge grant covering every changed file; release PRs require Admin.",
|
|
451
451
|
fields: {
|
|
452
452
|
childTaskId: childTaskIdForMerge
|
|
453
453
|
}
|
|
454
454
|
},
|
|
455
455
|
mcp: {
|
|
456
|
-
description: "Approve and merge a child task's pull request. Pass projectId to target a specific project; otherwise the configured default project is used. Only succeeds if all CI/CD checks are passing. The child task must be in ReviewPR status with a PR.",
|
|
456
|
+
description: "Approve and merge a child task's pull request. Pass projectId to target a specific project; otherwise the configured default project is used. Only succeeds if all CI/CD checks are passing. The child task must be in ReviewPR status with a PR. Requires project Admin, or a sub-project merge grant covering every changed file; release PRs require Admin.",
|
|
457
457
|
fields: {
|
|
458
458
|
projectId: mcpProjectId,
|
|
459
459
|
childTaskId: childTaskIdForMerge
|
|
@@ -870,13 +870,13 @@ var getAttachmentContract = defineToolContract({
|
|
|
870
870
|
var uploadAttachmentContract = defineToolContract({
|
|
871
871
|
name: "upload_attachment",
|
|
872
872
|
agent: {
|
|
873
|
-
description: "Upload
|
|
873
|
+
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.",
|
|
874
874
|
fields: {
|
|
875
875
|
path: f.string({
|
|
876
|
-
desc: "Path to the
|
|
876
|
+
desc: "Path to the file \u2014 absolute, or relative to the workspace root"
|
|
877
877
|
}),
|
|
878
878
|
title: f.optional(
|
|
879
|
-
f.string({ desc: "Short caption posted with the
|
|
879
|
+
f.string({ desc: "Short caption posted with the file (defaults to the file name)" })
|
|
880
880
|
)
|
|
881
881
|
}
|
|
882
882
|
},
|
|
@@ -988,7 +988,17 @@ import { z as z4 } from "zod";
|
|
|
988
988
|
function mcpShape(surface) {
|
|
989
989
|
return compileShape(z4, surface.fields);
|
|
990
990
|
}
|
|
991
|
-
function registerContractTool(server2, contract, handler) {
|
|
991
|
+
function registerContractTool(server2, contract, handler, options) {
|
|
992
|
+
if (options?.alwaysLoad) {
|
|
993
|
+
registerHotTool(
|
|
994
|
+
server2,
|
|
995
|
+
contract.name,
|
|
996
|
+
contract.mcp.description,
|
|
997
|
+
mcpShape(contract.mcp),
|
|
998
|
+
handler
|
|
999
|
+
);
|
|
1000
|
+
return;
|
|
1001
|
+
}
|
|
992
1002
|
server2.tool(
|
|
993
1003
|
contract.name,
|
|
994
1004
|
contract.mcp.description,
|
|
@@ -996,6 +1006,17 @@ function registerContractTool(server2, contract, handler) {
|
|
|
996
1006
|
handler
|
|
997
1007
|
);
|
|
998
1008
|
}
|
|
1009
|
+
function registerHotTool(server2, name, description, schema, handler) {
|
|
1010
|
+
server2.registerTool(
|
|
1011
|
+
name,
|
|
1012
|
+
{
|
|
1013
|
+
description,
|
|
1014
|
+
inputSchema: schema,
|
|
1015
|
+
_meta: { "anthropic/alwaysLoad": true }
|
|
1016
|
+
},
|
|
1017
|
+
handler
|
|
1018
|
+
);
|
|
1019
|
+
}
|
|
999
1020
|
|
|
1000
1021
|
// src/tools/tasks-format.ts
|
|
1001
1022
|
var CLI_EVENT_FORMATTERS = {
|
|
@@ -1009,9 +1030,23 @@ var CLI_EVENT_FORMATTERS = {
|
|
|
1009
1030
|
start_command_output: (data) => `[${data.stream ?? "stdout"}] ${String(data.data ?? "")}`,
|
|
1010
1031
|
turn_end: (data) => `Turn complete (${Array.isArray(data.toolCalls) ? data.toolCalls.length : 0} tool calls)`
|
|
1011
1032
|
};
|
|
1033
|
+
var EVENT_SUMMARY_MAX_CHARS = 1200;
|
|
1012
1034
|
function formatCliEventSummary(type, data) {
|
|
1013
1035
|
const formatter = CLI_EVENT_FORMATTERS[type];
|
|
1014
|
-
|
|
1036
|
+
const summary = formatter ? formatter(data) : JSON.stringify(data);
|
|
1037
|
+
if (summary.length <= EVENT_SUMMARY_MAX_CHARS) return summary;
|
|
1038
|
+
return `${summary.slice(0, EVENT_SUMMARY_MAX_CHARS)}\u2026[+${summary.length - EVENT_SUMMARY_MAX_CHARS}c]`;
|
|
1039
|
+
}
|
|
1040
|
+
var CHAT_MESSAGE_PREVIEW_CHARS = 2e3;
|
|
1041
|
+
function compactChatMessage(message) {
|
|
1042
|
+
if (typeof message !== "object" || message === null) return message;
|
|
1043
|
+
const obj = { ...message };
|
|
1044
|
+
const content = obj.content;
|
|
1045
|
+
if (typeof content === "string" && content.length > CHAT_MESSAGE_PREVIEW_CHARS) {
|
|
1046
|
+
const overflow = content.length - CHAT_MESSAGE_PREVIEW_CHARS;
|
|
1047
|
+
obj.content = `${content.slice(0, CHAT_MESSAGE_PREVIEW_CHARS)}\u2026[+${overflow}c truncated]`;
|
|
1048
|
+
}
|
|
1049
|
+
return obj;
|
|
1015
1050
|
}
|
|
1016
1051
|
function formatLegacyComputeSession(s) {
|
|
1017
1052
|
return ` - session ${s.id} [${s.provider}] pod=${s.instanceName ?? "-"} status=${s.status} runner=${s.agentRunnerStatus ?? "-"} lastHeartbeat=${s.lastHeartbeatAt ?? "-"} created=${s.createdAt} stopped=${s.stoppedAt ?? "-"}` + (s.deletionRequestedAt ? ` deletionRequested=${s.deletionRequestedAt} (attempts ${s.deletionAttempts})` : "") + (s.lastAgentEvent ? ` lastAgentEvent=${s.lastAgentEvent}` : "");
|
|
@@ -1030,19 +1065,32 @@ function formatWorkspace(w) {
|
|
|
1030
1065
|
lines.push(...w.sessions.map(formatWorkspaceSession));
|
|
1031
1066
|
return lines;
|
|
1032
1067
|
}
|
|
1033
|
-
function
|
|
1068
|
+
function latestByCreatedAt(items, limit) {
|
|
1069
|
+
if (items.length <= limit) return { kept: items, omitted: 0 };
|
|
1070
|
+
const sorted = [...items].sort((a, b) => b.createdAt.localeCompare(a.createdAt));
|
|
1071
|
+
return { kept: sorted.slice(0, limit), omitted: items.length - limit };
|
|
1072
|
+
}
|
|
1073
|
+
function formatTaskSessionState(t, limit = 20) {
|
|
1034
1074
|
const review = t.codeReviewStatus ? ` codeReview=${t.codeReviewStatus} (attempts ${t.codeReviewAttempts})` : "";
|
|
1035
1075
|
const kind = t.reviewTargetTaskId ? `review card for ${t.reviewTargetTaskId}` : t.type;
|
|
1036
1076
|
const lines = [`# ${t.slug} \u2014 ${t.title} [${kind}, status ${t.status}]${review}`];
|
|
1037
1077
|
if (t.sessions.length === 0) {
|
|
1038
1078
|
lines.push(" (no compute sessions)");
|
|
1039
1079
|
} else {
|
|
1040
|
-
|
|
1080
|
+
const { kept, omitted } = latestByCreatedAt(t.sessions, limit);
|
|
1081
|
+
lines.push(...kept.map(formatLegacyComputeSession));
|
|
1082
|
+
if (omitted > 0) {
|
|
1083
|
+
lines.push(` (\u2026 +${omitted} older compute sessions \u2014 pass a higher limit to see them)`);
|
|
1084
|
+
}
|
|
1041
1085
|
}
|
|
1042
1086
|
if (t.workspaces.length === 0) {
|
|
1043
1087
|
lines.push(" (no v3 workspaces)");
|
|
1044
1088
|
} else {
|
|
1045
|
-
|
|
1089
|
+
const { kept, omitted } = latestByCreatedAt(t.workspaces, limit);
|
|
1090
|
+
lines.push(...kept.flatMap(formatWorkspace));
|
|
1091
|
+
if (omitted > 0) {
|
|
1092
|
+
lines.push(` (\u2026 +${omitted} older workspaces \u2014 pass a higher limit to see them)`);
|
|
1093
|
+
}
|
|
1046
1094
|
}
|
|
1047
1095
|
return lines;
|
|
1048
1096
|
}
|
|
@@ -1076,7 +1124,8 @@ var BOARD_ASSIGN = z5.string().nullable().optional().describe(
|
|
|
1076
1124
|
"Assign the card to a sub-project board. Omit to use the connection's default board (CONVEYOR_SUBPROJECT_ID) when set, else the parent project; pass null to force the parent project. Use list_accessible_subprojects to find board IDs."
|
|
1077
1125
|
);
|
|
1078
1126
|
function registerListTasks(server2, conn2) {
|
|
1079
|
-
|
|
1127
|
+
registerHotTool(
|
|
1128
|
+
server2,
|
|
1080
1129
|
"list_tasks",
|
|
1081
1130
|
"List project cards, optionally filtered by card type, status, or assignment (a specific assignee, or unassigned tasks). Defaults to type=task \u2014 pass typeFilters to list incidents/suggestions. Results are relevance-ordered: highest priority first then newest; suggestions-only queries rank by upvote score. Pass projectId to target a specific project; otherwise the configured default project is used. Returns summaries \u2014 plan omitted, description truncated; use get_task for full details.",
|
|
1082
1131
|
{
|
|
@@ -1099,10 +1148,15 @@ function registerListTasks(server2, conn2) {
|
|
|
1099
1148
|
);
|
|
1100
1149
|
}
|
|
1101
1150
|
function registerGetTask(server2, conn2) {
|
|
1102
|
-
registerContractTool(
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1151
|
+
registerContractTool(
|
|
1152
|
+
server2,
|
|
1153
|
+
getTaskContract,
|
|
1154
|
+
async (params) => {
|
|
1155
|
+
const task = await conn2.getTask(params.taskId, params.projectId);
|
|
1156
|
+
return { content: [{ type: "text", text: JSON.stringify(task, null, 2) }] };
|
|
1157
|
+
},
|
|
1158
|
+
{ alwaysLoad: true }
|
|
1159
|
+
);
|
|
1106
1160
|
}
|
|
1107
1161
|
function registerGetCardBySlug(server2, conn2) {
|
|
1108
1162
|
server2.tool(
|
|
@@ -1209,27 +1263,34 @@ function registerMoveCard(server2, conn2) {
|
|
|
1209
1263
|
}
|
|
1210
1264
|
function registerChatTools(server2, conn2) {
|
|
1211
1265
|
registerContractTool(server2, readTaskChatContract, async (params) => {
|
|
1212
|
-
const messages = await conn2.getTaskChat(params.taskId, params.limit, params.projectId);
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
registerContractTool(server2, postToChatContract, async (params) => {
|
|
1216
|
-
const text = params.content ?? params.message;
|
|
1217
|
-
if (text === void 0) {
|
|
1218
|
-
return {
|
|
1219
|
-
content: [
|
|
1220
|
-
{
|
|
1221
|
-
type: "text",
|
|
1222
|
-
text: "Nothing to post \u2014 provide `content` (or its alias `message`)."
|
|
1223
|
-
}
|
|
1224
|
-
]
|
|
1225
|
-
};
|
|
1226
|
-
}
|
|
1227
|
-
await conn2.postToTaskChat(params.taskId, text, params.projectId);
|
|
1228
|
-
return { content: [{ type: "text", text: "Message posted" }] };
|
|
1266
|
+
const messages = await conn2.getTaskChat(params.taskId, params.limit ?? 50, params.projectId);
|
|
1267
|
+
const compacted = messages.map(compactChatMessage);
|
|
1268
|
+
return { content: [{ type: "text", text: JSON.stringify(compacted, null, 2) }] };
|
|
1229
1269
|
});
|
|
1270
|
+
registerContractTool(
|
|
1271
|
+
server2,
|
|
1272
|
+
postToChatContract,
|
|
1273
|
+
async (params) => {
|
|
1274
|
+
const text = params.content ?? params.message;
|
|
1275
|
+
if (text === void 0) {
|
|
1276
|
+
return {
|
|
1277
|
+
content: [
|
|
1278
|
+
{
|
|
1279
|
+
type: "text",
|
|
1280
|
+
text: "Nothing to post \u2014 provide `content` (or its alias `message`)."
|
|
1281
|
+
}
|
|
1282
|
+
]
|
|
1283
|
+
};
|
|
1284
|
+
}
|
|
1285
|
+
await conn2.postToTaskChat(params.taskId, text, params.projectId);
|
|
1286
|
+
return { content: [{ type: "text", text: "Message posted" }] };
|
|
1287
|
+
},
|
|
1288
|
+
{ alwaysLoad: true }
|
|
1289
|
+
);
|
|
1230
1290
|
}
|
|
1231
1291
|
function registerGetTaskCli(server2, conn2) {
|
|
1232
|
-
|
|
1292
|
+
registerHotTool(
|
|
1293
|
+
server2,
|
|
1233
1294
|
"get_task_logs",
|
|
1234
1295
|
"Read CLI execution logs from a task. Pass projectId to target a specific project; otherwise the configured default project is used. Returns agent reasoning, tool calls, setup output, and other execution events. For human chat use read_task_chat.",
|
|
1235
1296
|
{
|
|
@@ -1258,11 +1319,12 @@ function registerGetTaskSessions(server2, conn2) {
|
|
|
1258
1319
|
"Read compute-session state for a task: legacy CodespaceSession rows plus v3 workspaces, including purpose=review review workspaces. Shows pod identity, liveness, lifecycle, and code-review claim state. Use to diagnose stalled/dead agents or code-review runs. Pass projectId to target a specific project; otherwise the configured default project is used.",
|
|
1259
1320
|
{
|
|
1260
1321
|
projectId: z5.string().optional().describe("Target Conveyor project ID"),
|
|
1261
|
-
taskId: z5.string().describe("The task ID or slug")
|
|
1322
|
+
taskId: z5.string().describe("The task ID or slug"),
|
|
1323
|
+
limit: z5.number().int().min(1).max(200).optional().describe("Max sessions/workspaces listed per task, newest first (default 20)")
|
|
1262
1324
|
},
|
|
1263
|
-
async ({ taskId, projectId: projectId2 }) => {
|
|
1325
|
+
async ({ taskId, projectId: projectId2, limit }) => {
|
|
1264
1326
|
const tasks = await conn2.getTaskSessions(taskId, projectId2);
|
|
1265
|
-
const lines = tasks.flatMap(formatTaskSessionState);
|
|
1327
|
+
const lines = tasks.flatMap((t) => formatTaskSessionState(t, limit ?? 20));
|
|
1266
1328
|
return {
|
|
1267
1329
|
content: [
|
|
1268
1330
|
{ type: "text", text: lines.join("\n") || "No sessions found for this task." }
|
|
@@ -1272,7 +1334,8 @@ function registerGetTaskSessions(server2, conn2) {
|
|
|
1272
1334
|
);
|
|
1273
1335
|
}
|
|
1274
1336
|
function registerSearchTasks(server2, conn2) {
|
|
1275
|
-
|
|
1337
|
+
registerHotTool(
|
|
1338
|
+
server2,
|
|
1276
1339
|
"search_tasks",
|
|
1277
1340
|
"Search cards by tag name, text query, status, type, and/or assignment. Defaults to type=task \u2014 pass typeFilters to include incidents/suggestions. Results are relevance-ordered: highest priority first then newest; suggestions-only queries rank by upvote score. Pass projectId to target a specific project; otherwise the configured default project is used. Use tag names like 'agent-runner', not IDs. Returns summaries \u2014 plan omitted, description truncated; use get_task for full details.",
|
|
1278
1341
|
{
|
|
@@ -1644,12 +1707,17 @@ function registerAttachmentTools(server2, conn2) {
|
|
|
1644
1707
|
|
|
1645
1708
|
// src/tools/pull-request.ts
|
|
1646
1709
|
function registerPullRequestTools(server2, conn2) {
|
|
1647
|
-
registerContractTool(
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1710
|
+
registerContractTool(
|
|
1711
|
+
server2,
|
|
1712
|
+
createPullRequestContract,
|
|
1713
|
+
async (params) => {
|
|
1714
|
+
const result = await conn2.createPullRequest(params);
|
|
1715
|
+
return {
|
|
1716
|
+
content: [{ type: "text", text: `PR #${result.prNumber} opened: ${result.prUrl}` }]
|
|
1717
|
+
};
|
|
1718
|
+
},
|
|
1719
|
+
{ alwaysLoad: true }
|
|
1720
|
+
);
|
|
1653
1721
|
}
|
|
1654
1722
|
|
|
1655
1723
|
// src/tools/subtasks.ts
|
|
@@ -2183,7 +2251,8 @@ async function runQueryGrafanaLogs(conn2, params, now = Date.now) {
|
|
|
2183
2251
|
`entries=${result.entries.length}`
|
|
2184
2252
|
].join(" ");
|
|
2185
2253
|
const lines = result.entries.map(formatLogEntryLine);
|
|
2186
|
-
const
|
|
2254
|
+
const oldest = result.entries.map((e) => e.timestamp).sort()[0];
|
|
2255
|
+
const footer = result.hasMore ? [`-- hit the limit: older lines exist \u2014 pass endTime="${oldest}" to page further back`] : [];
|
|
2187
2256
|
if (lines.length === 0) {
|
|
2188
2257
|
return [
|
|
2189
2258
|
header,
|