diff --git a/src/kept.ts b/src/kept.ts index be72a9f..4fc50b5 100644 --- a/src/kept.ts +++ b/src/kept.ts @@ -2,6 +2,9 @@ import type { SessionEntry } from "@earendil-works/pi-coding-agent"; import { parseSkillBlocksFromText } from "./detect.js"; import type { TrackedSkill } from "./state.js"; +/** custom_message type for deferred re-inject delivery (SPEC §6.5.1). */ +const SKILL_REINJECT_INJECT_CUSTOM_TYPE = "skill-reinject:inject"; + /** Branch slice from firstKeptEntryId through tail (SPEC §6.4). */ export function getKeptEntries(branch: SessionEntry[], firstKeptEntryId: string): SessionEntry[] { const startIndex = branch.findIndex((entry) => entry.id === firstKeptEntryId); @@ -31,7 +34,7 @@ function extractUserMessageText(content: unknown): string { return parts.join("\n"); } -/** Skill names already present as blocks in kept user messages (SPEC §6.4). */ +/** Skill names already present as blocks in kept user messages and reinject custom messages (SPEC §6.4). */ export function skillsPresentInKeptWindow( keptEntries: SessionEntry[], skillNames: readonly string[], @@ -43,10 +46,18 @@ export function skillsPresentInKeptWindow( } for (const entry of keptEntries) { - if (entry.type !== "message" || entry.message.role !== "user") { + let text = ""; + if (entry.type === "message" && entry.message.role === "user") { + text = extractUserMessageText(entry.message.content); + } else if ( + entry.type === "custom_message" && + entry.customType === SKILL_REINJECT_INJECT_CUSTOM_TYPE && + typeof entry.content === "string" + ) { + text = entry.content; + } else { continue; } - const text = extractUserMessageText(entry.message.content); for (const block of parseSkillBlocksFromText(text)) { if (namesToCheck.has(block.name)) { present.add(block.name);