Compare commits

...

6 Commits

+66 -7
View File
@@ -148,6 +148,9 @@ async function runOllamaLoop(ctx: AgentRunContext): Promise<AgentResult> {
let pendingModeNudge = false; let pendingModeNudge = false;
let calledOutputTool = false; let calledOutputTool = false;
let addedContinueNudge = false; let addedContinueNudge = false;
let reportProgressCount = 0;
let editCommentCount = 0;
let selectedModeName = "";
while (iterations < MAX_ITERATIONS) { while (iterations < MAX_ITERATIONS) {
iterations++; iterations++;
@@ -222,13 +225,16 @@ async function runOllamaLoop(ctx: AgentRunContext): Promise<AgentResult> {
"» model stopped before completing task — nudging to continue", "» model stopped before completing task — nudging to continue",
); );
addedContinueNudge = true; addedContinueNudge = true;
const isReview =
selectedModeName === "Review" || selectedModeName === "IncrementalReview";
messages.push({ messages.push({
role: "user", role: "user",
content: content:
"Your task is not complete yet. Continue executing the workflow — " + "Your task is not complete yet. Continue executing the workflow — " +
"call the next required tool to finish. " + "call the next required tool to finish. " +
"Do not stop until you have submitted a review (create_pull_request_review) " + (isReview
"or called report_progress with a final summary.", ? "Do not stop until you have submitted a review via create_pull_request_review."
: "Do not stop until you have submitted a review (create_pull_request_review) or called report_progress with a final summary."),
}); });
continue; continue;
} }
@@ -279,6 +285,51 @@ async function runOllamaLoop(ctx: AgentRunContext): Promise<AgentResult> {
role: "tool", role: "tool",
content: result, content: result,
}); });
// After checkout_pr returns, extract and pin the diffPath as a user
// message. Only tool messages are pruned — user messages survive context
// pressure — so the model retains the exact diff file path and knows how
// to call read_file with offset/limit to read diff ranges.
if (toolName === "checkout_pr") {
try {
const parsed = JSON.parse(result) as Record<string, unknown>;
if (typeof parsed?.diffPath === "string") {
const dp = parsed.diffPath;
messages.push({
role: "user",
content:
`The diff file is at: ${dp}\n\n` +
`Read each file's diff by calling read_file on this path with start_line/end_line from the TOC.\n` +
`Example — for "device.ts (163 lines, 1146-1308)": read_file(path="${dp}", start_line=1146, end_line=1308)\n` +
`IMPORTANT: Do NOT call read_file on source files (apps/..., packages/...). ` +
`Use read_file on the diff file path above with the TOC line ranges.`,
});
log.info(`» pinned diffPath to context: ${dp}`);
}
} catch {
// best-effort: if checkout_pr result isn't JSON, skip
}
}
// report_progress called repeatedly means the model is stuck.
if (toolName === "report_progress") {
reportProgressCount++;
if (reportProgressCount >= 2) {
log.info("» report_progress loop — stopping");
await unloadModel(ollama, model);
return { success: true };
}
}
// edit_issue_comment called repeatedly means the model is stuck.
if (toolName === "edit_issue_comment") {
editCommentCount++;
if (editCommentCount >= 2) {
log.info("» edit_issue_comment loop — stopping");
await unloadModel(ollama, model);
return { success: true };
}
}
} }
// After the FIRST select_mode call, nudge the model to act on the guidance. // After the FIRST select_mode call, nudge the model to act on the guidance.
@@ -301,10 +352,18 @@ async function runOllamaLoop(ctx: AgentRunContext): Promise<AgentResult> {
// best-effort // best-effort
} }
const firstStep = const isReviewMode =
selectedMode === "Review" || selectedMode === "IncrementalReview" selectedMode === "Review" || selectedMode === "IncrementalReview";
? "Your first tool call must be checkout_pr with the PR number from the event context."
: "Call the first tool required by the workflow now."; selectedModeName = selectedMode;
const firstStep = isReviewMode
? "Your first tool call must be checkout_pr. After that: (1) read diff ranges from the returned diffPath using the TOC line numbers — do NOT read full source files one-by-one, that will exhaust your context window; (2) every inline comment MUST identify a specific problem — never write praise or 'looks good' observations."
: "Call the first tool required by the workflow now.";
const endCondition = isReviewMode
? "Your ONLY valid final action is create_pull_request_review. Do NOT call report_progress — the mode workflow explicitly forbids it."
: "Execute the complete workflow step by step until you call create_pull_request_review or report_progress.";
messages.push({ messages.push({
role: "user", role: "user",
@@ -312,7 +371,7 @@ async function runOllamaLoop(ctx: AgentRunContext): Promise<AgentResult> {
`Good. You have selected ${selectedMode || "a"} mode and received the workflow. ` + `Good. You have selected ${selectedMode || "a"} mode and received the workflow. ` +
"Do NOT call select_mode again. " + "Do NOT call select_mode again. " +
`${firstStep} ` + `${firstStep} ` +
"Execute the complete workflow step by step until you call create_pull_request_review or report_progress.", endCondition,
}); });
} }
} }