Phase 9: wire session_compact to defer and immediate reinject — SPEC §5.2, §8.
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 <cursoragent@cursor.com>
This commit is contained in:
+83
-2
@@ -1,10 +1,31 @@
|
|||||||
import { dirname } from "node:path";
|
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 { detectSlashSkill, matchReadPathToSkillWhenEnabled, parseSkillBlocksFromText, userMessageText } from "./detect.js";
|
||||||
|
import {
|
||||||
|
enqueueDeferredReinjectFromCompact,
|
||||||
|
planReinject,
|
||||||
|
sendImmediateReinjectAllFollowUp,
|
||||||
|
sendImmediateReinjectIdle,
|
||||||
|
tryConsumeDeferredReinject,
|
||||||
|
} from "./reinject.js";
|
||||||
import { readSettings } from "./settings.js";
|
import { readSettings } from "./settings.js";
|
||||||
import { findRegisteredSkillByName, resolveRegisteredSkills } from "./skills-registry.js";
|
import { findRegisteredSkillByName, resolveRegisteredSkills } from "./skills-registry.js";
|
||||||
import {
|
import {
|
||||||
createInitialState,
|
createInitialState,
|
||||||
|
createRuntimeFlags,
|
||||||
saveState,
|
saveState,
|
||||||
trackSkill,
|
trackSkill,
|
||||||
type TrackSkillInput,
|
type TrackSkillInput,
|
||||||
@@ -12,6 +33,8 @@ import {
|
|||||||
|
|
||||||
export default function skillReinject(pi: ExtensionAPI): void {
|
export default function skillReinject(pi: ExtensionAPI): void {
|
||||||
const state = createInitialState();
|
const state = createInitialState();
|
||||||
|
const runtime = createRuntimeFlags();
|
||||||
|
const compactionRuntime = createCompactionRuntime();
|
||||||
let registeredSkills: Skill[] = [];
|
let registeredSkills: Skill[] = [];
|
||||||
|
|
||||||
function persistState(): void {
|
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;
|
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) => {
|
pi.on("input", async (event, ctx) => {
|
||||||
@@ -47,6 +126,8 @@ export default function skillReinject(pi: ExtensionAPI): void {
|
|||||||
return { action: "continue" };
|
return { action: "continue" };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
markManualCompactionFromInput(event.text, compactionRuntime);
|
||||||
|
|
||||||
const skillName = detectSlashSkill(event.text);
|
const skillName = detectSlashSkill(event.text);
|
||||||
if (skillName) {
|
if (skillName) {
|
||||||
const skills = resolveRegisteredSkills(ctx.cwd, registeredSkills);
|
const skills = resolveRegisteredSkills(ctx.cwd, registeredSkills);
|
||||||
|
|||||||
Reference in New Issue
Block a user