fix(pi-extension): guard status bar render when ui has no theme (#279)

syncStatus guarded setStatus but used theme.fg unguarded, so a Pi host
exposing setStatus without a theme threw TypeError on session_start (and
agent_start/agent_end/setMode). Require both before rendering.

Add tests for the render path (previously untested) and the theme-absent
degradation. Follow-up to #275 / #84.
This commit is contained in:
DietrichGebert
2026-06-24 01:10:04 +02:00
committed by GitHub
parent 947f2ff4de
commit c8b12b6384
2 changed files with 31 additions and 1 deletions
+1 -1
View File
@@ -63,7 +63,7 @@ export default function ponytailExtension(pi) {
function syncStatus(ctx) {
if (ctx) lastCtx = ctx;
const c = ctx || lastCtx;
if (!c?.ui?.setStatus) return;
if (!c?.ui?.setStatus || !c.ui.theme?.fg) return;
const theme = c.ui.theme;
if (currentMode === "off") {
c.ui.setStatus("ponytail", "");
+30
View File
@@ -135,3 +135,33 @@ test("a request mentioning normal mode stays active", async () => withTempConfig
const result = await events.get("before_agent_start")({ systemPrompt: "BASE" }, ctx);
assert.match(result.systemPrompt, /PONYTAIL MODE ACTIVE/);
}));
test("status bar renders the mode and flips active on agent_start", async () => withTempConfig(async () => {
const { events } = createPiHarness();
const statusWrites = [];
const ctx = createCommandContext({
sessionManager: { getEntries: () => [{ type: "custom", customType: "ponytail-mode", data: { mode: "ultra" } }] },
ui: { notify() {}, setStatus: (key, text) => statusWrites.push({ key, text }), theme: { fg: (_color, text) => text } },
});
await events.get("session_start")({ reason: "resume" }, ctx);
await events.get("agent_start")({}, ctx);
assert.equal(statusWrites.at(-2).key, "ponytail");
assert.match(statusWrites.at(-2).text, /○.*ULTRA/);
assert.match(statusWrites.at(-1).text, /●.*ULTRA/);
}));
test("status bar stays silent when ui lacks a theme", async () => withTempConfig(async () => {
const { events } = createPiHarness();
const calls = [];
const ctx = createCommandContext({
sessionManager: { getEntries: () => [{ type: "custom", customType: "ponytail-mode", data: { mode: "ultra" } }] },
ui: { notify() {}, setStatus: (_key, text) => calls.push(text) }, // setStatus present, theme absent
});
await events.get("session_start")({ reason: "resume" }, ctx);
await events.get("agent_start")({}, ctx);
assert.deepEqual(calls, []);
}));