fix: reviews failing to call next tool
This commit is contained in:
+33
-2
@@ -95,8 +95,17 @@ async function runOllamaLoop(ctx: AgentRunContext): Promise<AgentResult> {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Tools that signal the agent has produced its final output.
|
||||||
|
const OUTPUT_TOOLS = new Set([
|
||||||
|
"create_pull_request_review",
|
||||||
|
"report_progress",
|
||||||
|
"set_output",
|
||||||
|
]);
|
||||||
|
|
||||||
let iterations = 0;
|
let iterations = 0;
|
||||||
let pendingModeNudge = false;
|
let pendingModeNudge = false;
|
||||||
|
let calledOutputTool = false;
|
||||||
|
let addedContinueNudge = false;
|
||||||
|
|
||||||
while (iterations < MAX_ITERATIONS) {
|
while (iterations < MAX_ITERATIONS) {
|
||||||
iterations++;
|
iterations++;
|
||||||
@@ -124,8 +133,26 @@ async function runOllamaLoop(ctx: AgentRunContext): Promise<AgentResult> {
|
|||||||
const toolCalls: ToolCall[] | undefined = assistantMessage.tool_calls;
|
const toolCalls: ToolCall[] | undefined = assistantMessage.tool_calls;
|
||||||
|
|
||||||
if (!toolCalls || toolCalls.length === 0) {
|
if (!toolCalls || toolCalls.length === 0) {
|
||||||
// If we just gave the model a nudge after select_mode and it still won't
|
log.debug(` model text: ${assistantMessage.content?.slice(0, 500)}`);
|
||||||
// call tools, it's genuinely done (or stuck) — exit cleanly.
|
|
||||||
|
// If the model stopped before ever calling an output tool and we haven't
|
||||||
|
// nudged yet, give it one more push to continue the workflow — regardless
|
||||||
|
// of whether the mode nudge is still pending (the model may have stopped
|
||||||
|
// right after select_mode before acting on the guidance).
|
||||||
|
if (!calledOutputTool && !addedContinueNudge) {
|
||||||
|
log.info("» model stopped before completing task — nudging to continue");
|
||||||
|
addedContinueNudge = true;
|
||||||
|
messages.push({
|
||||||
|
role: "user",
|
||||||
|
content:
|
||||||
|
"Your task is not complete yet. Continue executing the workflow — " +
|
||||||
|
"call the next required tool to finish. " +
|
||||||
|
"Do not stop until you have submitted a review (create_pull_request_review) " +
|
||||||
|
"or called report_progress with a final summary.",
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (pendingModeNudge) {
|
if (pendingModeNudge) {
|
||||||
log.info("» agent finished after mode nudge (no tool calls)");
|
log.info("» agent finished after mode nudge (no tool calls)");
|
||||||
} else {
|
} else {
|
||||||
@@ -150,6 +177,10 @@ async function runOllamaLoop(ctx: AgentRunContext): Promise<AgentResult> {
|
|||||||
log.info(`» calling tool: ${toolName}`);
|
log.info(`» calling tool: ${toolName}`);
|
||||||
log.debug(` args: ${JSON.stringify(toolArgs)}`);
|
log.debug(` args: ${JSON.stringify(toolArgs)}`);
|
||||||
|
|
||||||
|
if (OUTPUT_TOOLS.has(toolName)) {
|
||||||
|
calledOutputTool = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx.onToolUse) {
|
if (ctx.onToolUse) {
|
||||||
ctx.onToolUse({ toolName, input: toolArgs });
|
ctx.onToolUse({ toolName, input: toolArgs });
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -487,9 +487,9 @@ export function CheckoutPrTool(ctx: ToolContext) {
|
|||||||
hookWarning: checkoutResult.hookWarning,
|
hookWarning: checkoutResult.hookWarning,
|
||||||
instructions:
|
instructions:
|
||||||
`the diff file at diffPath contains a table of contents (TOC) listing every changed file with its line range. ` +
|
`the diff file at diffPath contains a table of contents (TOC) listing every changed file with its line range. ` +
|
||||||
`use the TOC line ranges as your checklist and read specific files from the diff. ` +
|
`to read the diff, use the shell MCP tool — for example: shell({ command: 'sed -n "<start>,<end>p" ${join(tempDir, `pr-${pull_number}-${headShort}.diff`)}', description: 'read diff section' }). ` +
|
||||||
`for example, if the TOC says "src/foo.ts → lines 5-42", read lines 5-42 from diffPath. ` +
|
`use the TOC line ranges as your checklist and read specific sections. ` +
|
||||||
`review files selectively based on relevance. ` +
|
`for example, if the TOC says "src/foo.ts → lines 5-42", run: shell({ command: 'sed -n "5,42p" <diffPath>', description: 'read foo.ts diff' }). ` +
|
||||||
`IMPORTANT: to inspect the PR's changed files, read diffPath directly — ` +
|
`IMPORTANT: to inspect the PR's changed files, read diffPath directly — ` +
|
||||||
`do NOT run git diff or git show. The PR base branch is '${pr.baseRef}', NOT necessarily 'main' — ` +
|
`do NOT run git diff or git show. The PR base branch is '${pr.baseRef}', NOT necessarily 'main' — ` +
|
||||||
`if you must use git, use 'origin/${pr.baseRef}' as the base (e.g. git log origin/${pr.baseRef}..HEAD), ` +
|
`if you must use git, use 'origin/${pr.baseRef}' as the base (e.g. git log origin/${pr.baseRef}..HEAD), ` +
|
||||||
|
|||||||
@@ -107,8 +107,11 @@ function getShellInstructions(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFileInstructions(): string {
|
function getFileInstructions(shell: ResolvedPayload["shell"]): string {
|
||||||
return `### File operations\n\nUse your native file read/write/edit tools for all file operations.`;
|
if (shell === "disabled") {
|
||||||
|
return `### File operations\n\nShell is disabled — you cannot read arbitrary files. Use the diff content returned by MCP tools directly.`;
|
||||||
|
}
|
||||||
|
return `### File operations\n\nUse the \`shell\` MCP tool for all file operations. Examples:\n- Read a file: \`shell({ command: 'cat /path/to/file', description: 'read file' })\`\n- Read specific lines: \`shell({ command: 'sed -n "<start>,<end>p" /path/to/file', description: 'read lines' })\`\n- Search in a file: \`shell({ command: 'grep -n "pattern" /path/to/file', description: 'search' })\``;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStandaloneModeInstructions(
|
function getStandaloneModeInstructions(
|
||||||
@@ -241,7 +244,7 @@ Use MCP tools from ${shockbotMcpName} for all Gitea operations. Never use the \`
|
|||||||
|
|
||||||
${getShellInstructions(ctx.payload.shell, t)}
|
${getShellInstructions(ctx.payload.shell, t)}
|
||||||
|
|
||||||
${getFileInstructions()}
|
${getFileInstructions(ctx.payload.shell)}
|
||||||
|
|
||||||
${getStandaloneModeInstructions(ctx.payload.event.trigger, t, ctx.outputSchema)}
|
${getStandaloneModeInstructions(ctx.payload.event.trigger, t, ctx.outputSchema)}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user