feat: surface base + persona system prompts in observer feed (#1103)

Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
This commit is contained in:
Will Pfleger
2026-06-17 19:41:03 -04:00
committed by GitHub
parent 466bb993ca
commit 5004758fbf
4 changed files with 162 additions and 6 deletions

View File

@@ -49,6 +49,46 @@ export function parsePromptText(text: string): {
};
}
/**
* Split the framed `session/new` `systemPrompt` into its `Base`/`System`
* sub-sections deterministically.
*
* The harness frames the value as `[Base]\n{base}\n\n[System]\n{persona}`, with
* either prompt omitted when absent: base-only is `[Base]\n{base}`, persona-only
* is `[System]\n{persona}`. We partition on the FIRST `\n[System]\n` boundary and
* read each labeled body literally. Unlike the generic `parsePromptSections`,
* embedded `[...]` lines inside a body never start a new section — so a persona
* containing a bracketed line, or a mid-string-elided header on an oversize
* prompt, can never drop a label or inflate the section count.
*/
export function parseSystemPromptSections(
systemPrompt: string,
): PromptSection[] {
const sections: PromptSection[] = [];
// Persona-only frame: no [Base], starts directly with [System].
if (systemPrompt.startsWith("[System]\n")) {
const body = systemPrompt.slice("[System]\n".length).trim();
if (body) sections.push({ title: "System", body });
return sections;
}
// Otherwise the head (up to the first [System] boundary, or the whole string)
// is the [Base] body.
const marker = "\n[System]\n";
const at = systemPrompt.indexOf(marker);
const head = at === -1 ? systemPrompt : systemPrompt.slice(0, at);
const baseBody = head.replace(/^\[Base]\n/, "").trim();
if (baseBody) sections.push({ title: "Base", body: baseBody });
if (at !== -1) {
const systemBody = systemPrompt.slice(at + marker.length).trim();
sections.push({ title: "System", body: systemBody });
}
return sections;
}
function parsePromptSections(text: string): PromptSection[] {
const sections: PromptSection[] = [];
let current: PromptSection | null = null;