Embed Facts in the PI narrative prompt and teach the bind-mounted runner to write assistant text into missing reasoning targets, matching pi-native.
79 lines
1.9 KiB
JavaScript
79 lines
1.9 KiB
JavaScript
/**
|
|
* Reasoning / --no-tools runs cannot write deliverables via tools.
|
|
* Mirror pi-native: when targets are missing, materialize assistant text.
|
|
*/
|
|
|
|
export function stripThinkBlocks(text) {
|
|
return String(text || "")
|
|
.replace(/<think>[\s\S]*?<\/think>/gi, "")
|
|
.replace(/```(?:json)?\s*/gi, "")
|
|
.replace(/```/g, "")
|
|
.trim();
|
|
}
|
|
|
|
export function extractAssistantText(ev) {
|
|
if (!ev || typeof ev !== "object") {
|
|
return "";
|
|
}
|
|
const t = ev.type || "";
|
|
if (t !== "message_end" && t !== "turn_end") {
|
|
return "";
|
|
}
|
|
const msg = ev.message;
|
|
if (!msg || typeof msg !== "object" || msg.role !== "assistant") {
|
|
return "";
|
|
}
|
|
const parts = Array.isArray(msg.content) ? msg.content : [];
|
|
const chunks = [];
|
|
for (const part of parts) {
|
|
if (part && typeof part === "object" && part.type === "text" && typeof part.text === "string") {
|
|
chunks.push(part.text);
|
|
}
|
|
}
|
|
return chunks.join("");
|
|
}
|
|
|
|
/**
|
|
* Write assistant text into missing/empty targets. Returns list of paths written.
|
|
*/
|
|
export function materializeReasoningTargets({
|
|
workspace,
|
|
targets,
|
|
assistantText,
|
|
existsSync,
|
|
readFileSync,
|
|
writeFileSync,
|
|
mkdirSync,
|
|
resolve,
|
|
dirname,
|
|
}) {
|
|
const cleaned = stripThinkBlocks(assistantText);
|
|
if (!cleaned || !workspace) {
|
|
return [];
|
|
}
|
|
const written = [];
|
|
for (const rel of Array.isArray(targets) ? targets : []) {
|
|
if (!rel || typeof rel !== "string") {
|
|
continue;
|
|
}
|
|
const abs = resolve(workspace, rel);
|
|
if (existsSync(abs)) {
|
|
try {
|
|
if (String(readFileSync(abs, "utf8")).trim()) {
|
|
continue;
|
|
}
|
|
} catch {
|
|
// fall through and overwrite empty/unreadable
|
|
}
|
|
}
|
|
try {
|
|
mkdirSync(dirname(abs), { recursive: true });
|
|
writeFileSync(abs, cleaned, "utf8");
|
|
written.push(rel);
|
|
} catch {
|
|
// leave missing; caller will classify
|
|
}
|
|
}
|
|
return written;
|
|
}
|