Skip to content

Commit d13994e

Browse files
committed
fix(pi): terminate agent loop on plan approval so model switch takes effect
Pi snapshots the model at the start of each agent.prompt() call, so calling pi.setModel() mid-loop has no effect until the next user turn. Return terminate: true from the approval tool to end the current loop, then use an agent_end handler with deferred sendUserMessage to start a fresh turn that picks up the executing model. Closes #674
1 parent ff2759b commit d13994e

2 files changed

Lines changed: 18 additions & 4 deletions

File tree

apps/pi-extension/index.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ export default function plannotator(pi: ExtensionAPI): void {
212212
let checklistItems: ChecklistItem[] = [];
213213
let savedState: SavedPhaseState | null = null;
214214
let plannotatorConfig = {};
215+
let justApprovedPlan = false;
215216

216217
pi.on("session_start", (_event, ctx) => {
217218
currentPiSession.update(ctx);
@@ -349,7 +350,7 @@ export default function plannotator(pi: ExtensionAPI): void {
349350
await applyPhaseConfig(ctx, { restoreSavedState: false });
350351
persistState();
351352
ctx.ui.notify(
352-
"Plannotator: planning mode enabled. Write a markdown plan, then submit it for review.",
353+
"Plannotator: planning mode enabled.",
353354
);
354355
const warning = getPlanReviewAvailabilityWarning({ hasUI: ctx.hasUI, hasPlanHtml: hasPlanBrowserHtml() });
355356
if (warning) {
@@ -853,6 +854,7 @@ export default function plannotator(pi: ExtensionAPI): void {
853854
await applyPhaseConfig(ctx, { restoreSavedState: true });
854855
pi.appendEntry("plannotator-execute", { lastSubmittedPath });
855856
persistState();
857+
justApprovedPlan = true;
856858
return {
857859
content: [
858860
{
@@ -861,6 +863,7 @@ export default function plannotator(pi: ExtensionAPI): void {
861863
},
862864
],
863865
details: { approved: true },
866+
terminate: true,
864867
};
865868
}
866869

@@ -881,6 +884,7 @@ export default function plannotator(pi: ExtensionAPI): void {
881884
await applyPhaseConfig(ctx, { restoreSavedState: true });
882885
pi.appendEntry("plannotator-execute", { lastSubmittedPath });
883886
persistState();
887+
justApprovedPlan = true;
884888

885889
const doneMsg =
886890
checklistItems.length > 0
@@ -900,6 +904,7 @@ export default function plannotator(pi: ExtensionAPI): void {
900904
},
901905
],
902906
details: { approved: true, feedback: result.feedback },
907+
terminate: true,
903908
};
904909
}
905910

@@ -914,6 +919,7 @@ export default function plannotator(pi: ExtensionAPI): void {
914919
},
915920
],
916921
details: { approved: true },
922+
terminate: true,
917923
};
918924
}
919925

@@ -1131,6 +1137,14 @@ Execute each step in order. After completing a step, include [DONE:n] in your re
11311137

11321138
// Detect execution completion
11331139
pi.on("agent_end", async (_event, ctx) => {
1140+
if (phase === "executing" && justApprovedPlan) {
1141+
justApprovedPlan = false;
1142+
setTimeout(() => {
1143+
pi.sendUserMessage("Continue with the approved plan.");
1144+
}, 0);
1145+
return;
1146+
}
1147+
11341148
if (phase !== "executing" || checklistItems.length === 0) return;
11351149

11361150
if (checklistItems.every((t) => t.completed)) {

bun.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)