From 0e32a498eea11b37cf5490a5c38a6a83f9da9a99 Mon Sep 17 00:00:00 2001 From: GRayHook Date: Wed, 17 Jun 2026 12:35:01 +0700 Subject: [PATCH] =?UTF-8?q?Phase=209:=20wire=20session=5Fcompact=20to=20de?= =?UTF-8?q?fer=20and=20immediate=20reinject=20=E2=80=94=20SPEC=20=C2=A75.2?= =?UTF-8?q?,=20=C2=A78.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Connect compaction source gate with plan/enqueue/send paths and consume deferred queue on before_agent_start for end-to-end auto compaction trigger. Co-authored-by: Cursor --- src/index.ts | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index ad2dc7e..7ec42f5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,31 @@ import { dirname } from "node:path"; -import { isToolCallEventType, type ExtensionAPI, type ExtensionContext, type Skill } from "@earendil-works/pi-coding-agent"; +import { + isToolCallEventType, + type ExtensionAPI, + type ExtensionContext, + type SessionCompactEvent, + type Skill, +} from "@earendil-works/pi-coding-agent"; +import { detectAndCachePiAutoCompact, resolveDeliveryMode } from "./auto-compact.js"; +import { + consumeCompactionOnSessionCompact, + createCompactionRuntime, + markAutoCompactionBeforeCompact, + markManualCompactionFromInput, +} from "./compaction.js"; import { detectSlashSkill, matchReadPathToSkillWhenEnabled, parseSkillBlocksFromText, userMessageText } from "./detect.js"; +import { + enqueueDeferredReinjectFromCompact, + planReinject, + sendImmediateReinjectAllFollowUp, + sendImmediateReinjectIdle, + tryConsumeDeferredReinject, +} from "./reinject.js"; import { readSettings } from "./settings.js"; import { findRegisteredSkillByName, resolveRegisteredSkills } from "./skills-registry.js"; import { createInitialState, + createRuntimeFlags, saveState, trackSkill, type TrackSkillInput, @@ -12,6 +33,8 @@ import { export default function skillReinject(pi: ExtensionAPI): void { const state = createInitialState(); + const runtime = createRuntimeFlags(); + const compactionRuntime = createCompactionRuntime(); let registeredSkills: Skill[] = []; function persistState(): void { @@ -38,8 +61,64 @@ export default function skillReinject(pi: ExtensionAPI): void { }); } - pi.on("before_agent_start", async (event) => { + function handleSessionCompact(event: SessionCompactEvent, ctx: ExtensionContext): void { + const settings = readSettings(ctx); + const shouldReinject = consumeCompactionOnSessionCompact( + compactionRuntime, + state, + state.sessionOverride, + settings, + ); + if (!shouldReinject) { + persistState(); + return; + } + + const skills = resolveRegisteredSkills(ctx.cwd, registeredSkills); + const deliveryMode = resolveDeliveryMode(settings, runtime); + if (deliveryMode === "defer") { + enqueueDeferredReinjectFromCompact(state, settings, ctx, event, skills); + persistState(); + return; + } + + const skillNames = planReinject(state, settings, ctx, event, skills); + if (skillNames.length === 0) { + persistState(); + return; + } + if (ctx.isIdle()) { + sendImmediateReinjectIdle(pi, skillNames, state, settings, skills, ctx); + } else { + sendImmediateReinjectAllFollowUp(pi, skillNames, state, settings, skills, ctx); + } + persistState(); + } + + pi.on("session_start", async () => { + detectAndCachePiAutoCompact(pi, runtime); + }); + + pi.on("session_before_compact", async () => { + markAutoCompactionBeforeCompact(compactionRuntime); + }); + + pi.on("session_compact", async (event, ctx) => { + handleSessionCompact(event, ctx); + }); + + pi.on("before_agent_start", async (event, ctx) => { registeredSkills = event.systemPromptOptions.skills ?? registeredSkills; + + const settings = readSettings(ctx); + const pendingBefore = state.pendingReinject.length; + const deferred = tryConsumeDeferredReinject(state, settings, registeredSkills, ctx); + if (pendingBefore > 0) { + persistState(); + } + if (deferred) { + return deferred; + } }); pi.on("input", async (event, ctx) => { @@ -47,6 +126,8 @@ export default function skillReinject(pi: ExtensionAPI): void { return { action: "continue" }; } + markManualCompactionFromInput(event.text, compactionRuntime); + const skillName = detectSlashSkill(event.text); if (skillName) { const skills = resolveRegisteredSkills(ctx.cwd, registeredSkills);