fix: guard pi before_agent_start against bad event and missing systemPrompt (#482)
The before_agent_start handler read event.systemPrompt with no guard. A null/undefined event crashed the agent with a TypeError (#439), and a truthy event without a systemPrompt key stringified to the literal 'undefined', prepending garbage to every system prompt (#440). Both are fixed with one optional-chain guard that mirrors the event?. pattern the input handler already uses: prepend the base prompt only when present, otherwise inject the ruleset alone. Adds a regression test covering null/undefined event, missing systemPrompt, and the normal base-prompt path. Closes #439 Closes #440 Co-authored-by: Aroool <90670606+Aroool@users.noreply.github.com>
This commit is contained in:
parent
40e50d9e03
commit
39bad58d40
|
|
@ -184,6 +184,9 @@ export default function ponytailExtension(pi) {
|
|||
|
||||
pi.on("before_agent_start", async (event) => {
|
||||
if (!currentMode || currentMode === "off") return;
|
||||
return { systemPrompt: `${event.systemPrompt}\n\n${getPonytailInstructions(currentMode)}` };
|
||||
// Guard a null/undefined event or a missing systemPrompt: don't crash, and
|
||||
// don't prepend the literal string "undefined" to the prompt (#439, #440).
|
||||
const base = event?.systemPrompt ? `${event.systemPrompt}\n\n` : "";
|
||||
return { systemPrompt: `${base}${getPonytailInstructions(currentMode)}` };
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,6 +77,29 @@ test("/ponytail updates session mode and injects instructions", async () => with
|
|||
assert.ok(result.systemPrompt.includes("ultra"));
|
||||
}));
|
||||
|
||||
test("before_agent_start guards missing event and missing systemPrompt (#439, #440)", async () => withTempConfig(async () => {
|
||||
const { events } = createPiHarness();
|
||||
const ctx = createCommandContext();
|
||||
await events.get("session_start")({ reason: "startup" }, ctx); // currentMode -> default (full)
|
||||
|
||||
// #439: a null/undefined event must not crash, and still injects the ruleset.
|
||||
for (const bad of [undefined, null]) {
|
||||
const r = await events.get("before_agent_start")(bad, ctx);
|
||||
assert.ok(r.systemPrompt.includes("PONYTAIL MODE ACTIVE"));
|
||||
assert.ok(!r.systemPrompt.includes("undefined"), "must not contain the literal 'undefined'");
|
||||
}
|
||||
|
||||
// #440: an event without a systemPrompt must not prepend the literal "undefined".
|
||||
const empty = await events.get("before_agent_start")({}, ctx);
|
||||
assert.ok(empty.systemPrompt.includes("PONYTAIL MODE ACTIVE"));
|
||||
assert.ok(!empty.systemPrompt.startsWith("undefined"), "must not start with 'undefined'");
|
||||
|
||||
// A real base prompt is still preserved and prepended.
|
||||
const withBase = await events.get("before_agent_start")({ systemPrompt: "BASE" }, ctx);
|
||||
assert.ok(withBase.systemPrompt.startsWith("BASE\n\n"));
|
||||
assert.ok(withBase.systemPrompt.includes("PONYTAIL MODE ACTIVE"));
|
||||
}));
|
||||
|
||||
test("session_start restores latest persisted mode", async () => withTempConfig(async () => {
|
||||
const { events } = createPiHarness();
|
||||
const ctx = createCommandContext({
|
||||
|
|
|
|||
Loading…
Reference in New Issue