Skip to content

Commit f8a7c60

Browse files
committed
fix(pi): restore the session's mode after OMP session switches
OMP keeps Pi's legacy session_switch and session_branch events instead of re-emitting session_start on /new, /resume, /fork and /branch, so a new session inherited the previous session's mode. Restore the mode on those events, like session_tree.
1 parent 9b58c1f commit f8a7c60

2 files changed

Lines changed: 26 additions & 3 deletions

File tree

‎pi-extension/index.js‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,13 @@ export default function ponytailExtension(pi) {
200200
}
201201
});
202202

203-
pi.on("session_tree", async (_event, ctx) => {
204-
restoreSessionMode(ctx);
205-
});
203+
// Both hosts emit session_tree. Pi re-emits session_start on /new, /resume and
204+
// /fork; OMP emits session_switch and session_branch instead.
205+
for (const eventName of ["session_tree", "session_switch", "session_branch"]) {
206+
pi.on(eventName, async (_event, ctx) => {
207+
restoreSessionMode(ctx);
208+
});
209+
}
206210

207211
pi.on("agent_start", async (_event, ctx) => {
208212
isActive = true;

‎pi-extension/test/extension.test.js‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,25 @@ test("session_tree restores the selected branch's mode without persisting it", a
181181
assert.equal(notifications.length, notificationCount, "navigation must not repeat the startup toast");
182182
}));
183183

184+
test("OMP session_switch and session_branch restore the target session's mode", async () => withTempConfig(async () => {
185+
// OMP keeps the legacy Pi events instead of re-emitting session_start on /new, /resume, /fork and /branch.
186+
const { events, appendedEntries } = createPiHarness();
187+
const lite = { type: "custom", customType: "ponytail-mode", data: { mode: "lite" } };
188+
const off = { type: "custom", customType: "ponytail-mode", data: { mode: "off" } };
189+
let branch = [off];
190+
const ctx = createCommandContext({ sessionManager: { getBranch: () => branch } });
191+
192+
await events.get("session_start")({ type: "session_start" }, ctx);
193+
for (const [type, entries, mode] of [["session_switch", [lite], "lite"], ["session_branch", [off], "off"], ["session_switch", [], "full"]]) {
194+
branch = entries;
195+
await events.get(type)?.({ type }, ctx);
196+
const result = await events.get("before_agent_start")({ systemPrompt: ["BASE"] }, ctx);
197+
if (mode === "off") assert.equal(result, undefined, `${type} should restore off`);
198+
else assert.ok(result?.systemPrompt.at(-1).startsWith(`PONYTAIL MODE ACTIVE — level: ${mode}\n`), `${type} should restore ${mode}`);
199+
}
200+
assert.deepEqual(appendedEntries, [], "restoring must not append a new mode entry");
201+
}));
202+
184203
test("skill alias commands delegate to Pi skill commands", async () => {
185204
const { commands, sentUserMessages } = createPiHarness();
186205
const ctx = createCommandContext();

0 commit comments

Comments
 (0)