@rallycry/conveyor-agent 6.0.7 → 6.0.9
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-ANYHEBDY.js → chunk-R6BFXUS7.js} +282 -82
- package/dist/chunk-R6BFXUS7.js.map +1 -0
- package/dist/cli.js +6 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-ANYHEBDY.js.map +0 -1
|
@@ -487,6 +487,10 @@ var ConveyorConnection = class _ConveyorConnection {
|
|
|
487
487
|
if (!this.socket) return;
|
|
488
488
|
this.socket.emit("agentRunner:debugReproduceRequested", { hypothesis });
|
|
489
489
|
}
|
|
490
|
+
emitCodeReviewResult(content, approved) {
|
|
491
|
+
if (!this.socket) throw new Error("Not connected");
|
|
492
|
+
this.socket.emit("agentRunner:codeReviewResult", { content, approved });
|
|
493
|
+
}
|
|
490
494
|
searchIncidents(status, source) {
|
|
491
495
|
return searchIncidents(this.socket, status, source);
|
|
492
496
|
}
|
|
@@ -2035,10 +2039,52 @@ function buildModePrompt(agentMode, context) {
|
|
|
2035
2039
|
].join("\n");
|
|
2036
2040
|
case "auto":
|
|
2037
2041
|
return buildAutoPrompt(context);
|
|
2042
|
+
case "code-review":
|
|
2043
|
+
return buildCodeReviewPrompt();
|
|
2038
2044
|
default:
|
|
2039
2045
|
return null;
|
|
2040
2046
|
}
|
|
2041
2047
|
}
|
|
2048
|
+
function buildCodeReviewPrompt() {
|
|
2049
|
+
return [
|
|
2050
|
+
`
|
|
2051
|
+
## Mode: Code Review`,
|
|
2052
|
+
`You are an automated code reviewer. A PR has passed all CI checks and you are performing a final code quality review before merge.`,
|
|
2053
|
+
``,
|
|
2054
|
+
`## Review Process`,
|
|
2055
|
+
`1. Run \`git diff <devBranch>..HEAD\` to see all changes in this PR`,
|
|
2056
|
+
`2. Read the task plan to understand the intended changes`,
|
|
2057
|
+
`3. Explore the surrounding codebase to verify pattern consistency`,
|
|
2058
|
+
`4. Review against the criteria below`,
|
|
2059
|
+
``,
|
|
2060
|
+
`### Review Criteria`,
|
|
2061
|
+
`- **Correctness**: Does the code do what the plan says? Logic errors, off-by-one, race conditions?`,
|
|
2062
|
+
`- **Pattern Consistency**: Does the code follow existing patterns in the codebase? Check nearby files.`,
|
|
2063
|
+
`- **Security**: No hardcoded secrets, no injection vulnerabilities, proper input validation at boundaries.`,
|
|
2064
|
+
`- **Performance**: No unnecessary loops, no N+1 queries, no blocking in async contexts.`,
|
|
2065
|
+
`- **Error Handling**: Appropriate error handling at system boundaries. No swallowed errors.`,
|
|
2066
|
+
`- **Test Coverage**: Are new code paths tested? Edge cases covered?`,
|
|
2067
|
+
`- **TypeScript Best Practices**: Proper typing (no unnecessary \`any\`), correct React patterns, proper async/await.`,
|
|
2068
|
+
`- **Naming & Readability**: Clear names, no misleading comments, self-documenting code.`,
|
|
2069
|
+
``,
|
|
2070
|
+
`## Output \u2014 You MUST do exactly ONE of:`,
|
|
2071
|
+
``,
|
|
2072
|
+
`### If code passes review:`,
|
|
2073
|
+
`Use the \`approve_code_review\` tool with a brief summary of what looks good.`,
|
|
2074
|
+
``,
|
|
2075
|
+
`### If changes are needed:`,
|
|
2076
|
+
`Use the \`request_code_changes\` tool with specific issues:`,
|
|
2077
|
+
`- Reference specific files and line numbers`,
|
|
2078
|
+
`- Explain what's wrong and suggest fixes`,
|
|
2079
|
+
`- Focus on substantive issues, not style nitpicks (linting handles that)`,
|
|
2080
|
+
``,
|
|
2081
|
+
`## Rules`,
|
|
2082
|
+
`- You are READ-ONLY. Do NOT modify any files.`,
|
|
2083
|
+
`- Do NOT re-review things CI already validates (formatting, lint rules).`,
|
|
2084
|
+
`- Be concise \u2014 the task agent needs actionable feedback, not essays.`,
|
|
2085
|
+
`- Max 5-7 issues per review. Prioritize the most important ones.`
|
|
2086
|
+
].join("\n");
|
|
2087
|
+
}
|
|
2042
2088
|
|
|
2043
2089
|
// src/execution/system-prompt.ts
|
|
2044
2090
|
function formatProjectAgentLine(pa) {
|
|
@@ -2410,6 +2456,18 @@ ${context.plan}`);
|
|
|
2410
2456
|
}
|
|
2411
2457
|
return parts;
|
|
2412
2458
|
}
|
|
2459
|
+
function buildCodeReviewInstructions(context) {
|
|
2460
|
+
const parts = [
|
|
2461
|
+
`You are performing an automated code review for this task.`,
|
|
2462
|
+
`The PR branch is "${context.githubBranch}"${context.baseBranch ? ` based on "${context.baseBranch}"` : ""}.`,
|
|
2463
|
+
`Begin your code review by running \`git diff ${context.baseBranch ?? "dev"}..HEAD\` to see all changes.`,
|
|
2464
|
+
``,
|
|
2465
|
+
`CRITICAL: You are in Code Review mode. You are READ-ONLY \u2014 do NOT modify any files.`,
|
|
2466
|
+
`After reviewing, you MUST call exactly one of: \`approve_code_review\` or \`request_code_changes\`.`,
|
|
2467
|
+
`Do NOT go idle, ask for confirmation, or wait for instructions \u2014 complete the review and exit.`
|
|
2468
|
+
];
|
|
2469
|
+
return parts;
|
|
2470
|
+
}
|
|
2413
2471
|
function buildFreshInstructions(isPm, isAutoMode, context, agentMode) {
|
|
2414
2472
|
if (isPm && agentMode === "building") {
|
|
2415
2473
|
return [
|
|
@@ -2507,6 +2565,10 @@ Address the requested changes directly. Do NOT re-investigate the codebase from
|
|
|
2507
2565
|
function buildInstructions(mode, context, scenario, agentMode, isAuto) {
|
|
2508
2566
|
const parts = [`
|
|
2509
2567
|
## Instructions`];
|
|
2568
|
+
if (agentMode === "code-review") {
|
|
2569
|
+
parts.push(...buildCodeReviewInstructions(context));
|
|
2570
|
+
return parts;
|
|
2571
|
+
}
|
|
2510
2572
|
const isPm = mode === "pm";
|
|
2511
2573
|
if (scenario === "fresh") {
|
|
2512
2574
|
parts.push(...buildFreshInstructions(isPm, agentMode === "auto", context, agentMode));
|
|
@@ -2558,7 +2620,7 @@ function buildInstructions(mode, context, scenario, agentMode, isAuto) {
|
|
|
2558
2620
|
}
|
|
2559
2621
|
async function buildInitialPrompt(mode, context, isAuto, agentMode) {
|
|
2560
2622
|
const isPackRunner = mode === "pm" && !!isAuto && !!context.isParentTask;
|
|
2561
|
-
if (!isPackRunner) {
|
|
2623
|
+
if (!isPackRunner && agentMode !== "code-review") {
|
|
2562
2624
|
const sessionRelaunch = buildRelaunchWithSession(mode, context, agentMode, isAuto);
|
|
2563
2625
|
if (sessionRelaunch) return sessionRelaunch;
|
|
2564
2626
|
}
|
|
@@ -4365,6 +4427,73 @@ function buildDebugTools(manager) {
|
|
|
4365
4427
|
];
|
|
4366
4428
|
}
|
|
4367
4429
|
|
|
4430
|
+
// src/tools/code-review-tools.ts
|
|
4431
|
+
import { tool as tool7 } from "@anthropic-ai/claude-agent-sdk";
|
|
4432
|
+
import { z as z7 } from "zod";
|
|
4433
|
+
function buildCodeReviewTools(connection) {
|
|
4434
|
+
return [
|
|
4435
|
+
tool7(
|
|
4436
|
+
"approve_code_review",
|
|
4437
|
+
"Approve the code review. Use this when the code passes all review criteria and is ready to merge.",
|
|
4438
|
+
{
|
|
4439
|
+
summary: z7.string().describe("Brief summary of what was reviewed and why it looks good")
|
|
4440
|
+
},
|
|
4441
|
+
// eslint-disable-next-line require-await -- SDK tool() API requires async handler
|
|
4442
|
+
async ({ summary }) => {
|
|
4443
|
+
connection.emitCodeReviewResult(
|
|
4444
|
+
`**Code Review: Approved** :white_check_mark:
|
|
4445
|
+
|
|
4446
|
+
${summary}`,
|
|
4447
|
+
true
|
|
4448
|
+
);
|
|
4449
|
+
connection.sendEvent({
|
|
4450
|
+
type: "code_review_complete",
|
|
4451
|
+
result: "approved",
|
|
4452
|
+
summary
|
|
4453
|
+
});
|
|
4454
|
+
return textResult("Code review approved. Exiting.");
|
|
4455
|
+
}
|
|
4456
|
+
),
|
|
4457
|
+
tool7(
|
|
4458
|
+
"request_code_changes",
|
|
4459
|
+
"Request changes during code review. Use this when substantive issues are found that need to be fixed before merge.",
|
|
4460
|
+
{
|
|
4461
|
+
issues: z7.array(
|
|
4462
|
+
z7.object({
|
|
4463
|
+
file: z7.string().describe("File path where the issue was found"),
|
|
4464
|
+
line: z7.number().optional().describe("Line number (if applicable)"),
|
|
4465
|
+
severity: z7.enum(["critical", "major", "minor"]).describe("Issue severity"),
|
|
4466
|
+
description: z7.string().describe("What is wrong and how to fix it")
|
|
4467
|
+
})
|
|
4468
|
+
).describe("List of issues found during review"),
|
|
4469
|
+
summary: z7.string().describe("Brief overall summary of the review findings")
|
|
4470
|
+
},
|
|
4471
|
+
// eslint-disable-next-line require-await -- SDK tool() API requires async handler
|
|
4472
|
+
async ({ issues, summary }) => {
|
|
4473
|
+
const issueLines = issues.map((issue) => {
|
|
4474
|
+
const loc = issue.line ? `:${issue.line}` : "";
|
|
4475
|
+
return `- **[${issue.severity}]** \`${issue.file}${loc}\`: ${issue.description}`;
|
|
4476
|
+
}).join("\n");
|
|
4477
|
+
connection.emitCodeReviewResult(
|
|
4478
|
+
`**Code Review: Changes Requested** :warning:
|
|
4479
|
+
|
|
4480
|
+
${summary}
|
|
4481
|
+
|
|
4482
|
+
${issueLines}`,
|
|
4483
|
+
false
|
|
4484
|
+
);
|
|
4485
|
+
connection.sendEvent({
|
|
4486
|
+
type: "code_review_complete",
|
|
4487
|
+
result: "changes_requested",
|
|
4488
|
+
summary,
|
|
4489
|
+
issues
|
|
4490
|
+
});
|
|
4491
|
+
return textResult("Code review complete \u2014 changes requested. Exiting.");
|
|
4492
|
+
}
|
|
4493
|
+
)
|
|
4494
|
+
];
|
|
4495
|
+
}
|
|
4496
|
+
|
|
4368
4497
|
// src/tools/index.ts
|
|
4369
4498
|
function textResult(text) {
|
|
4370
4499
|
return { content: [{ type: "text", text }] };
|
|
@@ -4395,8 +4524,22 @@ function getModeTools(agentMode, connection, config, context) {
|
|
|
4395
4524
|
}
|
|
4396
4525
|
}
|
|
4397
4526
|
function createConveyorMcpServer(connection, config, context, agentMode, debugManager) {
|
|
4398
|
-
const commonTools = buildCommonTools(connection, config);
|
|
4399
4527
|
const effectiveMode = agentMode ?? context?.agentMode ?? void 0;
|
|
4528
|
+
if (effectiveMode === "code-review") {
|
|
4529
|
+
return createSdkMcpServer({
|
|
4530
|
+
name: "conveyor",
|
|
4531
|
+
tools: [
|
|
4532
|
+
buildReadTaskChatTool(connection),
|
|
4533
|
+
buildGetTaskPlanTool(connection, config),
|
|
4534
|
+
buildGetTaskTool(connection),
|
|
4535
|
+
buildGetTaskCliTool(connection),
|
|
4536
|
+
buildListTaskFilesTool(connection),
|
|
4537
|
+
buildGetTaskFileTool(connection),
|
|
4538
|
+
...buildCodeReviewTools(connection)
|
|
4539
|
+
]
|
|
4540
|
+
});
|
|
4541
|
+
}
|
|
4542
|
+
const commonTools = buildCommonTools(connection, config);
|
|
4400
4543
|
const modeTools = getModeTools(effectiveMode, connection, config, context);
|
|
4401
4544
|
const discoveryTools = effectiveMode === "discovery" || effectiveMode === "auto" ? buildDiscoveryTools(connection, context) : [];
|
|
4402
4545
|
const debugTools = debugManager && effectiveMode === "building" ? buildDebugTools(debugManager) : [];
|
|
@@ -4411,6 +4554,7 @@ function createConveyorMcpServer(connection, config, context, agentMode, debugMa
|
|
|
4411
4554
|
import { randomUUID } from "crypto";
|
|
4412
4555
|
var PM_PLAN_FILE_TOOLS = /* @__PURE__ */ new Set(["Write", "Edit", "MultiEdit"]);
|
|
4413
4556
|
var DESTRUCTIVE_CMD_PATTERN = /git\s+push\s+--force(?!\s*-with-lease)|git\s+reset\s+--hard|rm\s+-rf\s+\//;
|
|
4557
|
+
var CODE_REVIEW_WRITE_CMD_PATTERN = /git\s+push|git\s+commit|git\s+add|rm\s+|mv\s+|cp\s+|mkdir\s+|touch\s+|chmod\s+|chown\s+/;
|
|
4414
4558
|
function isPlanFile(input) {
|
|
4415
4559
|
const filePath = String(input.file_path ?? input.path ?? "");
|
|
4416
4560
|
return filePath.includes(".claude/plans/");
|
|
@@ -4460,6 +4604,24 @@ function handleReviewToolAccess(toolName, input, isParentTask) {
|
|
|
4460
4604
|
}
|
|
4461
4605
|
return { behavior: "allow", updatedInput: input };
|
|
4462
4606
|
}
|
|
4607
|
+
function handleCodeReviewToolAccess(toolName, input) {
|
|
4608
|
+
if (PM_PLAN_FILE_TOOLS.has(toolName)) {
|
|
4609
|
+
return {
|
|
4610
|
+
behavior: "deny",
|
|
4611
|
+
message: "Code review mode is fully read-only. File writes are not permitted."
|
|
4612
|
+
};
|
|
4613
|
+
}
|
|
4614
|
+
if (toolName === "Bash") {
|
|
4615
|
+
const cmd = String(input.command ?? "");
|
|
4616
|
+
if (DESTRUCTIVE_CMD_PATTERN.test(cmd) || CODE_REVIEW_WRITE_CMD_PATTERN.test(cmd)) {
|
|
4617
|
+
return {
|
|
4618
|
+
behavior: "deny",
|
|
4619
|
+
message: "Code review mode is read-only. Write operations and destructive commands are blocked."
|
|
4620
|
+
};
|
|
4621
|
+
}
|
|
4622
|
+
}
|
|
4623
|
+
return { behavior: "allow", updatedInput: input };
|
|
4624
|
+
}
|
|
4463
4625
|
function handleAutoToolAccess(toolName, input, hasExitedPlanMode, isParentTask) {
|
|
4464
4626
|
if (hasExitedPlanMode) {
|
|
4465
4627
|
return isParentTask ? handleReviewToolAccess(toolName, input, true) : handleBuildingToolAccess(toolName, input);
|
|
@@ -4564,6 +4726,9 @@ function buildCanUseTool(host) {
|
|
|
4564
4726
|
case "auto":
|
|
4565
4727
|
result = handleAutoToolAccess(toolName, input, host.hasExitedPlanMode, host.isParentTask);
|
|
4566
4728
|
break;
|
|
4729
|
+
case "code-review":
|
|
4730
|
+
result = handleCodeReviewToolAccess(toolName, input);
|
|
4731
|
+
break;
|
|
4567
4732
|
default:
|
|
4568
4733
|
result = { behavior: "allow", updatedInput: input };
|
|
4569
4734
|
}
|
|
@@ -4611,10 +4776,13 @@ function buildHooks(host) {
|
|
|
4611
4776
|
};
|
|
4612
4777
|
}
|
|
4613
4778
|
function isReadOnlyMode(mode, hasExitedPlanMode) {
|
|
4614
|
-
return mode === "discovery" || mode === "help" || mode === "auto" && !hasExitedPlanMode;
|
|
4779
|
+
return mode === "discovery" || mode === "help" || mode === "code-review" || mode === "auto" && !hasExitedPlanMode;
|
|
4615
4780
|
}
|
|
4616
4781
|
function buildDisallowedTools(settings, mode, hasExitedPlanMode) {
|
|
4617
4782
|
const modeDisallowed = isReadOnlyMode(mode, hasExitedPlanMode) ? ["TodoWrite", "TodoRead", "NotebookEdit"] : [];
|
|
4783
|
+
if (mode === "code-review") {
|
|
4784
|
+
modeDisallowed.push("ExitPlanMode", "EnterPlanMode");
|
|
4785
|
+
}
|
|
4618
4786
|
const configured = settings.disallowedTools ?? [];
|
|
4619
4787
|
const combined = [...configured, ...modeDisallowed];
|
|
4620
4788
|
return combined.length > 0 ? combined : void 0;
|
|
@@ -4647,11 +4815,11 @@ function buildQueryOptions(host, context) {
|
|
|
4647
4815
|
tools: { type: "preset", preset: "claude_code" },
|
|
4648
4816
|
mcpServers: { conveyor: createConveyorMcpServer(host.connection, host.config, context, mode) },
|
|
4649
4817
|
hooks: buildHooks(host),
|
|
4650
|
-
maxTurns: settings.maxTurns,
|
|
4818
|
+
maxTurns: mode === "code-review" ? Math.min(settings.maxTurns ?? 15, 15) : settings.maxTurns,
|
|
4651
4819
|
effort: settings.effort,
|
|
4652
4820
|
thinking: settings.thinking,
|
|
4653
4821
|
betas: settings.betas,
|
|
4654
|
-
maxBudgetUsd: settings.maxBudgetUsd ?? 50,
|
|
4822
|
+
maxBudgetUsd: mode === "code-review" ? Math.min(settings.maxBudgetUsd ?? 10, 10) : settings.maxBudgetUsd ?? 50,
|
|
4655
4823
|
disallowedTools: buildDisallowedTools(settings, mode, host.hasExitedPlanMode),
|
|
4656
4824
|
enableFileCheckpointing: settings.enableFileCheckpointing,
|
|
4657
4825
|
stderr: (data) => {
|
|
@@ -5362,6 +5530,7 @@ var AgentRunner = class {
|
|
|
5362
5530
|
agentMode = null;
|
|
5363
5531
|
hasExitedPlanMode = false;
|
|
5364
5532
|
pendingModeRestart = false;
|
|
5533
|
+
pendingModeAutoStart = false;
|
|
5365
5534
|
sessionIds = /* @__PURE__ */ new Map();
|
|
5366
5535
|
lastQueryModeRestart = false;
|
|
5367
5536
|
startCommandStarted = false;
|
|
@@ -5565,6 +5734,12 @@ var AgentRunner = class {
|
|
|
5565
5734
|
async executeInitialMode() {
|
|
5566
5735
|
if (!this.taskContext) return;
|
|
5567
5736
|
const mode = this.effectiveAgentMode;
|
|
5737
|
+
if (mode === "code-review") {
|
|
5738
|
+
await this.setState("running");
|
|
5739
|
+
await this.runQuerySafe(this.taskContext);
|
|
5740
|
+
this.stopped = true;
|
|
5741
|
+
return;
|
|
5742
|
+
}
|
|
5568
5743
|
const shouldRun = mode === "building" || mode === "auto" || mode === "review" && !!this.taskContext.isParentTask;
|
|
5569
5744
|
if (shouldRun) {
|
|
5570
5745
|
await this.setState("running");
|
|
@@ -5621,6 +5796,12 @@ var AgentRunner = class {
|
|
|
5621
5796
|
await this.handleModeRestartCycle();
|
|
5622
5797
|
continue;
|
|
5623
5798
|
}
|
|
5799
|
+
if (this.pendingModeAutoStart) {
|
|
5800
|
+
this.pendingModeAutoStart = false;
|
|
5801
|
+
this.interrupted = false;
|
|
5802
|
+
await this.handleModeRestartCycle();
|
|
5803
|
+
continue;
|
|
5804
|
+
}
|
|
5624
5805
|
if (this._state === "idle") {
|
|
5625
5806
|
const msg = await this.waitForUserContent();
|
|
5626
5807
|
if (!msg) {
|
|
@@ -5772,15 +5953,32 @@ var AgentRunner = class {
|
|
|
5772
5953
|
handleModeChange(newAgentMode) {
|
|
5773
5954
|
if (this.config.mode !== "pm") return;
|
|
5774
5955
|
if (newAgentMode) this.agentMode = newAgentMode;
|
|
5956
|
+
this.updateExitedPlanModeFlag(newAgentMode);
|
|
5775
5957
|
const effectiveMode = this.effectiveAgentMode;
|
|
5958
|
+
const isBuildCapable = effectiveMode === "building" || effectiveMode === "auto" && this.hasExitedPlanMode;
|
|
5776
5959
|
this.connection.emitModeChanged(effectiveMode);
|
|
5777
5960
|
this.connection.postChatMessage(
|
|
5778
5961
|
`Mode switched to **${effectiveMode}**${effectiveMode === "building" ? " \u2014 I now have direct coding access." : ""}`
|
|
5779
5962
|
);
|
|
5780
|
-
if (
|
|
5963
|
+
if (isBuildCapable && this.taskContext?.status === "Open") {
|
|
5781
5964
|
this.connection.updateStatus("InProgress");
|
|
5782
5965
|
this.taskContext.status = "InProgress";
|
|
5783
5966
|
}
|
|
5967
|
+
if (isBuildCapable) {
|
|
5968
|
+
this.pendingModeAutoStart = true;
|
|
5969
|
+
this.softStop();
|
|
5970
|
+
}
|
|
5971
|
+
}
|
|
5972
|
+
updateExitedPlanModeFlag(newAgentMode) {
|
|
5973
|
+
if (newAgentMode === "building") {
|
|
5974
|
+
this.hasExitedPlanMode = true;
|
|
5975
|
+
return;
|
|
5976
|
+
}
|
|
5977
|
+
if (newAgentMode !== "auto") return;
|
|
5978
|
+
const pastPlanning = this.taskContext?.status !== "Planning" && this.taskContext?.status !== "Unidentified";
|
|
5979
|
+
if (pastPlanning) {
|
|
5980
|
+
this.hasExitedPlanMode = true;
|
|
5981
|
+
}
|
|
5784
5982
|
}
|
|
5785
5983
|
softStop() {
|
|
5786
5984
|
this.interrupted = true;
|
|
@@ -5926,17 +6124,17 @@ import {
|
|
|
5926
6124
|
} from "@anthropic-ai/claude-agent-sdk";
|
|
5927
6125
|
|
|
5928
6126
|
// src/tools/project-tools.ts
|
|
5929
|
-
import { tool as
|
|
5930
|
-
import { z as
|
|
6127
|
+
import { tool as tool8 } from "@anthropic-ai/claude-agent-sdk";
|
|
6128
|
+
import { z as z8 } from "zod";
|
|
5931
6129
|
function buildReadTools(connection) {
|
|
5932
6130
|
return [
|
|
5933
|
-
|
|
6131
|
+
tool8(
|
|
5934
6132
|
"list_tasks",
|
|
5935
6133
|
"List tasks in the project. Optionally filter by status or assignee.",
|
|
5936
6134
|
{
|
|
5937
|
-
status:
|
|
5938
|
-
assigneeId:
|
|
5939
|
-
limit:
|
|
6135
|
+
status: z8.string().optional().describe("Filter by task status (e.g. Planning, Open, InProgress, ReviewPR, Complete)"),
|
|
6136
|
+
assigneeId: z8.string().optional().describe("Filter by assigned user ID"),
|
|
6137
|
+
limit: z8.number().optional().describe("Max number of tasks to return (default 50)")
|
|
5940
6138
|
},
|
|
5941
6139
|
async (params) => {
|
|
5942
6140
|
try {
|
|
@@ -5950,10 +6148,10 @@ function buildReadTools(connection) {
|
|
|
5950
6148
|
},
|
|
5951
6149
|
{ annotations: { readOnlyHint: true } }
|
|
5952
6150
|
),
|
|
5953
|
-
|
|
6151
|
+
tool8(
|
|
5954
6152
|
"get_task",
|
|
5955
6153
|
"Get detailed information about a task including its chat messages, child tasks, and codespace status.",
|
|
5956
|
-
{ task_id:
|
|
6154
|
+
{ task_id: z8.string().describe("The task ID to look up") },
|
|
5957
6155
|
async ({ task_id }) => {
|
|
5958
6156
|
try {
|
|
5959
6157
|
const task = await connection.requestGetTask(task_id);
|
|
@@ -5966,14 +6164,14 @@ function buildReadTools(connection) {
|
|
|
5966
6164
|
},
|
|
5967
6165
|
{ annotations: { readOnlyHint: true } }
|
|
5968
6166
|
),
|
|
5969
|
-
|
|
6167
|
+
tool8(
|
|
5970
6168
|
"search_tasks",
|
|
5971
6169
|
"Search tasks by tags, text query, or status filters.",
|
|
5972
6170
|
{
|
|
5973
|
-
tagNames:
|
|
5974
|
-
searchQuery:
|
|
5975
|
-
statusFilters:
|
|
5976
|
-
limit:
|
|
6171
|
+
tagNames: z8.array(z8.string()).optional().describe("Filter by tag names"),
|
|
6172
|
+
searchQuery: z8.string().optional().describe("Text search in title/description"),
|
|
6173
|
+
statusFilters: z8.array(z8.string()).optional().describe("Filter by statuses"),
|
|
6174
|
+
limit: z8.number().optional().describe("Max results (default 20)")
|
|
5977
6175
|
},
|
|
5978
6176
|
async (params) => {
|
|
5979
6177
|
try {
|
|
@@ -5987,7 +6185,7 @@ function buildReadTools(connection) {
|
|
|
5987
6185
|
},
|
|
5988
6186
|
{ annotations: { readOnlyHint: true } }
|
|
5989
6187
|
),
|
|
5990
|
-
|
|
6188
|
+
tool8(
|
|
5991
6189
|
"list_tags",
|
|
5992
6190
|
"List all tags available in the project.",
|
|
5993
6191
|
{},
|
|
@@ -6003,7 +6201,7 @@ function buildReadTools(connection) {
|
|
|
6003
6201
|
},
|
|
6004
6202
|
{ annotations: { readOnlyHint: true } }
|
|
6005
6203
|
),
|
|
6006
|
-
|
|
6204
|
+
tool8(
|
|
6007
6205
|
"get_project_summary",
|
|
6008
6206
|
"Get a summary of the project including task counts by status and active builds.",
|
|
6009
6207
|
{},
|
|
@@ -6023,15 +6221,15 @@ function buildReadTools(connection) {
|
|
|
6023
6221
|
}
|
|
6024
6222
|
function buildMutationTools(connection) {
|
|
6025
6223
|
return [
|
|
6026
|
-
|
|
6224
|
+
tool8(
|
|
6027
6225
|
"create_task",
|
|
6028
6226
|
"Create a new task in the project.",
|
|
6029
6227
|
{
|
|
6030
|
-
title:
|
|
6031
|
-
description:
|
|
6032
|
-
plan:
|
|
6033
|
-
status:
|
|
6034
|
-
isBug:
|
|
6228
|
+
title: z8.string().describe("Task title"),
|
|
6229
|
+
description: z8.string().optional().describe("Task description"),
|
|
6230
|
+
plan: z8.string().optional().describe("Implementation plan in markdown"),
|
|
6231
|
+
status: z8.string().optional().describe("Initial status (default: Planning)"),
|
|
6232
|
+
isBug: z8.boolean().optional().describe("Whether this is a bug report")
|
|
6035
6233
|
},
|
|
6036
6234
|
async (params) => {
|
|
6037
6235
|
try {
|
|
@@ -6044,16 +6242,16 @@ function buildMutationTools(connection) {
|
|
|
6044
6242
|
}
|
|
6045
6243
|
}
|
|
6046
6244
|
),
|
|
6047
|
-
|
|
6245
|
+
tool8(
|
|
6048
6246
|
"update_task",
|
|
6049
6247
|
"Update an existing task's title, description, plan, status, or assignee.",
|
|
6050
6248
|
{
|
|
6051
|
-
task_id:
|
|
6052
|
-
title:
|
|
6053
|
-
description:
|
|
6054
|
-
plan:
|
|
6055
|
-
status:
|
|
6056
|
-
assignedUserId:
|
|
6249
|
+
task_id: z8.string().describe("The task ID to update"),
|
|
6250
|
+
title: z8.string().optional().describe("New title"),
|
|
6251
|
+
description: z8.string().optional().describe("New description"),
|
|
6252
|
+
plan: z8.string().optional().describe("New plan in markdown"),
|
|
6253
|
+
status: z8.string().optional().describe("New status"),
|
|
6254
|
+
assignedUserId: z8.string().nullable().optional().describe("Assign to user ID, or null to unassign")
|
|
6057
6255
|
},
|
|
6058
6256
|
async ({ task_id, ...fields }) => {
|
|
6059
6257
|
try {
|
|
@@ -6285,8 +6483,8 @@ import { query as query3 } from "@anthropic-ai/claude-agent-sdk";
|
|
|
6285
6483
|
|
|
6286
6484
|
// src/tools/audit-tools.ts
|
|
6287
6485
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
6288
|
-
import { tool as
|
|
6289
|
-
import { z as
|
|
6486
|
+
import { tool as tool9, createSdkMcpServer as createSdkMcpServer3 } from "@anthropic-ai/claude-agent-sdk";
|
|
6487
|
+
import { z as z9 } from "zod";
|
|
6290
6488
|
function mapCreateTag(input) {
|
|
6291
6489
|
return {
|
|
6292
6490
|
type: "create_tag",
|
|
@@ -6368,14 +6566,14 @@ function collectRecommendation(toolName, input, collector, onRecommendation) {
|
|
|
6368
6566
|
}
|
|
6369
6567
|
function createAuditMcpServer(collector, onRecommendation) {
|
|
6370
6568
|
const auditTools = [
|
|
6371
|
-
|
|
6569
|
+
tool9(
|
|
6372
6570
|
"recommend_create_tag",
|
|
6373
6571
|
"Recommend creating a new tag for an uncovered subsystem or area",
|
|
6374
6572
|
{
|
|
6375
|
-
name:
|
|
6376
|
-
color:
|
|
6377
|
-
description:
|
|
6378
|
-
reasoning:
|
|
6573
|
+
name: z9.string().describe("Proposed tag name (lowercase, hyphenated)"),
|
|
6574
|
+
color: z9.string().optional().describe("Hex color code"),
|
|
6575
|
+
description: z9.string().describe("What this tag covers"),
|
|
6576
|
+
reasoning: z9.string().describe("Why this tag should be created")
|
|
6379
6577
|
},
|
|
6380
6578
|
async (args) => {
|
|
6381
6579
|
const result = collectRecommendation(
|
|
@@ -6387,14 +6585,14 @@ function createAuditMcpServer(collector, onRecommendation) {
|
|
|
6387
6585
|
return { content: [{ type: "text", text: result }] };
|
|
6388
6586
|
}
|
|
6389
6587
|
),
|
|
6390
|
-
|
|
6588
|
+
tool9(
|
|
6391
6589
|
"recommend_update_description",
|
|
6392
6590
|
"Recommend updating a tag's description to better reflect its scope",
|
|
6393
6591
|
{
|
|
6394
|
-
tagId:
|
|
6395
|
-
tagName:
|
|
6396
|
-
description:
|
|
6397
|
-
reasoning:
|
|
6592
|
+
tagId: z9.string(),
|
|
6593
|
+
tagName: z9.string(),
|
|
6594
|
+
description: z9.string().describe("Proposed new description"),
|
|
6595
|
+
reasoning: z9.string()
|
|
6398
6596
|
},
|
|
6399
6597
|
async (args) => {
|
|
6400
6598
|
const result = collectRecommendation(
|
|
@@ -6406,16 +6604,16 @@ function createAuditMcpServer(collector, onRecommendation) {
|
|
|
6406
6604
|
return { content: [{ type: "text", text: result }] };
|
|
6407
6605
|
}
|
|
6408
6606
|
),
|
|
6409
|
-
|
|
6607
|
+
tool9(
|
|
6410
6608
|
"recommend_context_link",
|
|
6411
6609
|
"Recommend linking a doc, rule, file, or folder to a tag's contextPaths",
|
|
6412
6610
|
{
|
|
6413
|
-
tagId:
|
|
6414
|
-
tagName:
|
|
6415
|
-
linkType:
|
|
6416
|
-
path:
|
|
6417
|
-
label:
|
|
6418
|
-
reasoning:
|
|
6611
|
+
tagId: z9.string(),
|
|
6612
|
+
tagName: z9.string(),
|
|
6613
|
+
linkType: z9.enum(["rule", "doc", "file", "folder"]),
|
|
6614
|
+
path: z9.string(),
|
|
6615
|
+
label: z9.string().optional(),
|
|
6616
|
+
reasoning: z9.string()
|
|
6419
6617
|
},
|
|
6420
6618
|
async (args) => {
|
|
6421
6619
|
const result = collectRecommendation(
|
|
@@ -6427,16 +6625,16 @@ function createAuditMcpServer(collector, onRecommendation) {
|
|
|
6427
6625
|
return { content: [{ type: "text", text: result }] };
|
|
6428
6626
|
}
|
|
6429
6627
|
),
|
|
6430
|
-
|
|
6628
|
+
tool9(
|
|
6431
6629
|
"flag_documentation_gap",
|
|
6432
6630
|
"Flag a file that agents read heavily but has no tag documentation linked",
|
|
6433
6631
|
{
|
|
6434
|
-
tagName:
|
|
6435
|
-
tagId:
|
|
6436
|
-
filePath:
|
|
6437
|
-
readCount:
|
|
6438
|
-
suggestedAction:
|
|
6439
|
-
reasoning:
|
|
6632
|
+
tagName: z9.string().describe("Tag whose agents read this file"),
|
|
6633
|
+
tagId: z9.string().optional(),
|
|
6634
|
+
filePath: z9.string(),
|
|
6635
|
+
readCount: z9.number(),
|
|
6636
|
+
suggestedAction: z9.string().describe("What doc or rule should be created"),
|
|
6637
|
+
reasoning: z9.string()
|
|
6440
6638
|
},
|
|
6441
6639
|
async (args) => {
|
|
6442
6640
|
const result = collectRecommendation(
|
|
@@ -6448,15 +6646,15 @@ function createAuditMcpServer(collector, onRecommendation) {
|
|
|
6448
6646
|
return { content: [{ type: "text", text: result }] };
|
|
6449
6647
|
}
|
|
6450
6648
|
),
|
|
6451
|
-
|
|
6649
|
+
tool9(
|
|
6452
6650
|
"recommend_merge_tags",
|
|
6453
6651
|
"Recommend merging one tag into another",
|
|
6454
6652
|
{
|
|
6455
|
-
tagId:
|
|
6456
|
-
tagName:
|
|
6457
|
-
mergeIntoTagId:
|
|
6458
|
-
mergeIntoTagName:
|
|
6459
|
-
reasoning:
|
|
6653
|
+
tagId: z9.string().describe("Tag ID to be merged (removed after merge)"),
|
|
6654
|
+
tagName: z9.string().describe("Name of the tag to be merged"),
|
|
6655
|
+
mergeIntoTagId: z9.string().describe("Tag ID to merge into (kept)"),
|
|
6656
|
+
mergeIntoTagName: z9.string(),
|
|
6657
|
+
reasoning: z9.string()
|
|
6460
6658
|
},
|
|
6461
6659
|
async (args) => {
|
|
6462
6660
|
const result = collectRecommendation(
|
|
@@ -6468,14 +6666,14 @@ function createAuditMcpServer(collector, onRecommendation) {
|
|
|
6468
6666
|
return { content: [{ type: "text", text: result }] };
|
|
6469
6667
|
}
|
|
6470
6668
|
),
|
|
6471
|
-
|
|
6669
|
+
tool9(
|
|
6472
6670
|
"recommend_rename_tag",
|
|
6473
6671
|
"Recommend renaming a tag",
|
|
6474
6672
|
{
|
|
6475
|
-
tagId:
|
|
6476
|
-
tagName:
|
|
6477
|
-
newName:
|
|
6478
|
-
reasoning:
|
|
6673
|
+
tagId: z9.string(),
|
|
6674
|
+
tagName: z9.string().describe("Current tag name"),
|
|
6675
|
+
newName: z9.string().describe("Proposed new name"),
|
|
6676
|
+
reasoning: z9.string()
|
|
6479
6677
|
},
|
|
6480
6678
|
async (args) => {
|
|
6481
6679
|
const result = collectRecommendation(
|
|
@@ -6487,10 +6685,10 @@ function createAuditMcpServer(collector, onRecommendation) {
|
|
|
6487
6685
|
return { content: [{ type: "text", text: result }] };
|
|
6488
6686
|
}
|
|
6489
6687
|
),
|
|
6490
|
-
|
|
6688
|
+
tool9(
|
|
6491
6689
|
"complete_audit",
|
|
6492
6690
|
"Signal that the audit is complete with a summary of all findings",
|
|
6493
|
-
{ summary:
|
|
6691
|
+
{ summary: z9.string().describe("Brief overview of all findings") },
|
|
6494
6692
|
async (args) => {
|
|
6495
6693
|
collector.complete = true;
|
|
6496
6694
|
collector.summary = args.summary ?? "Audit completed.";
|
|
@@ -6706,21 +6904,22 @@ function setupWorkDir(projectDir, assignment) {
|
|
|
6706
6904
|
return { workDir, usesWorktree: shouldWorktree };
|
|
6707
6905
|
}
|
|
6708
6906
|
function spawnChildAgent(assignment, workDir) {
|
|
6709
|
-
const { taskToken, apiUrl, taskId, mode, isAuto, useSandbox } = assignment;
|
|
6907
|
+
const { taskToken, apiUrl, taskId, mode, isAuto, useSandbox, agentMode } = assignment;
|
|
6710
6908
|
const cliPath = path.resolve(__dirname, "cli.js");
|
|
6711
6909
|
const childEnv = { ...process.env };
|
|
6712
6910
|
delete childEnv.CONVEYOR_PROJECT_TOKEN;
|
|
6713
6911
|
delete childEnv.CONVEYOR_PROJECT_ID;
|
|
6912
|
+
const effectiveAgentMode = agentMode ?? (isAuto ? "auto" : "");
|
|
6714
6913
|
const child = fork(cliPath, [], {
|
|
6715
6914
|
env: {
|
|
6716
6915
|
...childEnv,
|
|
6717
6916
|
CONVEYOR_API_URL: apiUrl,
|
|
6718
6917
|
CONVEYOR_TASK_TOKEN: taskToken,
|
|
6719
6918
|
CONVEYOR_TASK_ID: taskId,
|
|
6720
|
-
CONVEYOR_MODE: mode,
|
|
6919
|
+
CONVEYOR_MODE: agentMode === "code-review" ? "code-review" : mode,
|
|
6721
6920
|
CONVEYOR_WORKSPACE: workDir,
|
|
6722
6921
|
CONVEYOR_USE_WORKTREE: "false",
|
|
6723
|
-
CONVEYOR_AGENT_MODE:
|
|
6922
|
+
CONVEYOR_AGENT_MODE: effectiveAgentMode,
|
|
6724
6923
|
CONVEYOR_IS_AUTO: isAuto ? "true" : "false",
|
|
6725
6924
|
CONVEYOR_USE_SANDBOX: useSandbox === true ? "true" : "false",
|
|
6726
6925
|
CONVEYOR_FROM_PROJECT_RUNNER: "true"
|
|
@@ -7155,8 +7354,9 @@ var ProjectRunner = class {
|
|
|
7155
7354
|
handleAssignment(assignment) {
|
|
7156
7355
|
const { taskId, mode } = assignment;
|
|
7157
7356
|
const shortId = taskId.slice(0, 8);
|
|
7158
|
-
|
|
7159
|
-
|
|
7357
|
+
const agentKey = assignment.agentMode === "code-review" ? `${taskId}:code-review` : taskId;
|
|
7358
|
+
if (this.activeAgents.has(agentKey)) {
|
|
7359
|
+
logger8.info("Task already running, skipping", { taskId: shortId, agentKey });
|
|
7160
7360
|
return;
|
|
7161
7361
|
}
|
|
7162
7362
|
if (this.activeAgents.size >= MAX_CONCURRENT) {
|
|
@@ -7175,16 +7375,16 @@ var ProjectRunner = class {
|
|
|
7175
7375
|
}
|
|
7176
7376
|
const { workDir, usesWorktree } = setupWorkDir(this.projectDir, assignment);
|
|
7177
7377
|
const child = spawnChildAgent(assignment, workDir);
|
|
7178
|
-
this.activeAgents.set(
|
|
7378
|
+
this.activeAgents.set(agentKey, {
|
|
7179
7379
|
process: child,
|
|
7180
7380
|
worktreePath: workDir,
|
|
7181
7381
|
mode,
|
|
7182
7382
|
usesWorktree
|
|
7183
7383
|
});
|
|
7184
7384
|
this.connection.emitTaskStarted(taskId);
|
|
7185
|
-
logger8.info("Started task", { taskId: shortId, mode, workDir });
|
|
7385
|
+
logger8.info("Started task", { taskId: shortId, mode, agentKey, workDir });
|
|
7186
7386
|
child.on("exit", (code) => {
|
|
7187
|
-
this.activeAgents.delete(
|
|
7387
|
+
this.activeAgents.delete(agentKey);
|
|
7188
7388
|
const reason = code === 0 ? "completed" : `exited with code ${code}`;
|
|
7189
7389
|
this.connection.emitTaskStopped(taskId, reason);
|
|
7190
7390
|
logger8.info("Task exited", { taskId: shortId, reason });
|
|
@@ -7344,4 +7544,4 @@ export {
|
|
|
7344
7544
|
ProjectRunner,
|
|
7345
7545
|
FileCache
|
|
7346
7546
|
};
|
|
7347
|
-
//# sourceMappingURL=chunk-
|
|
7547
|
+
//# sourceMappingURL=chunk-R6BFXUS7.js.map
|