Bug Description
In Pi, createPiHooks().beforeAgentStart returns { systemPrompt: event.systemPrompt + injection }. Pi treats a returned systemPrompt as a full replacement of the prompt for that run, and from then on it ignores event.systemPromptOptions.sections. So a section added by any extension whose before_agent_start handler runs after Hindsight's is dropped, on every turn where Hindsight injects memory.
I hit this with two mode extensions that add a prompt section while the mode is on. With Hindsight loaded, the modes showed as on, but their text never reached the model. With HINDSIGHT_DISABLE_HOOKS=1 it came back.
Code:
|
return { systemPrompt: `${event.systemPrompt}\n\n${injection}` }; |
Steps to Reproduce
No Hindsight server needed. Two stub extensions:
// force.ts: what the Hindsight Pi hook does
export default function (pi) {
pi.on("before_agent_start", (event) => ({ systemPrompt: `${event.systemPrompt}\n\n<memory>turn 1</memory>` }));
}
// section.ts: any extension that adds a prompt section
export default function (pi) {
pi.on("before_agent_start", (event) => {
event.systemPromptOptions.sections.other_ext = "SECTION-MARKER";
});
}
pi --no-extensions -e ./force.ts -e ./section.ts -p "Reply OK", with a third extension that writes the before_provider_request payload to a file.
- Look for
SECTION-MARKER in the system message.
- Run again with the order swapped:
-e ./section.ts -e ./force.ts.
Expected Behavior
Memory and SECTION-MARKER both reach the model, whatever the load order.
Actual Behavior
force.ts first: memory present, SECTION-MARKER missing.
section.ts first: both present.
Suggested fix
Add the injection as a section and keep the old path for hosts without systemPromptOptions:
if (event.systemPromptOptions?.sections) {
event.systemPromptOptions.sections.hindsight = injection;
return undefined;
}
return { systemPrompt: `${event.systemPrompt}\n\n${injection}` };
I checked this with the same stubs: memory and SECTION-MARKER both arrive, in either order. Pi's extension docs say the same: "Returning systemPrompt, or setting forceSystemPrompt, replaces the whole prompt for that run."
Version
@vectorize-io/hindsight-coding-agents 0.7.0 (same code on main at ccfe85b), Pi 0.87.1, macOS.
Bug Description
In Pi,
createPiHooks().beforeAgentStartreturns{ systemPrompt: event.systemPrompt + injection }. Pi treats a returnedsystemPromptas a full replacement of the prompt for that run, and from then on it ignoresevent.systemPromptOptions.sections. So a section added by any extension whosebefore_agent_starthandler runs after Hindsight's is dropped, on every turn where Hindsight injects memory.I hit this with two mode extensions that add a prompt section while the mode is on. With Hindsight loaded, the modes showed as on, but their text never reached the model. With
HINDSIGHT_DISABLE_HOOKS=1it came back.Code:
hindsight/hindsight-integrations/coding-agents/src/harness/pi-extension.ts
Line 142 in ccfe85b
Steps to Reproduce
No Hindsight server needed. Two stub extensions:
pi --no-extensions -e ./force.ts -e ./section.ts -p "Reply OK", with a third extension that writes thebefore_provider_requestpayload to a file.SECTION-MARKERin the system message.-e ./section.ts -e ./force.ts.Expected Behavior
Memory and
SECTION-MARKERboth reach the model, whatever the load order.Actual Behavior
force.tsfirst: memory present,SECTION-MARKERmissing.section.tsfirst: both present.Suggested fix
Add the injection as a section and keep the old path for hosts without
systemPromptOptions:I checked this with the same stubs: memory and
SECTION-MARKERboth arrive, in either order. Pi's extension docs say the same: "ReturningsystemPrompt, or settingforceSystemPrompt, replaces the whole prompt for that run."Version
@vectorize-io/hindsight-coding-agents0.7.0 (same code onmainatccfe85b), Pi 0.87.1, macOS.