Phase 15: add mid-turn defer reinject via sendMessage steer
Deliver pending skills on session_compact when agent is not idle, and skip before_agent_start consume when steer already ran for compaction. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -8,6 +8,10 @@ export interface CompactionRuntime {
|
|||||||
clearPendingReinjectOnNextUserInput: boolean;
|
clearPendingReinjectOnNextUserInput: boolean;
|
||||||
/** Last compact firstKeptEntryId for debug kept-window snapshots (Phase 14). */
|
/** Last compact firstKeptEntryId for debug kept-window snapshots (Phase 14). */
|
||||||
lastCompactionFirstKeptEntryId: string | null;
|
lastCompactionFirstKeptEntryId: string | null;
|
||||||
|
/** Last compaction entry id on session_compact (Phase 15 / B-003 dedup). */
|
||||||
|
lastCompactionEntryId: string | null;
|
||||||
|
/** Compaction id when mid-turn steer already delivered reinject (Phase 15 / §6.5.1). */
|
||||||
|
deferredDeliveredForCompactionId: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createCompactionRuntime(): CompactionRuntime {
|
export function createCompactionRuntime(): CompactionRuntime {
|
||||||
@@ -15,6 +19,8 @@ export function createCompactionRuntime(): CompactionRuntime {
|
|||||||
pendingCompactionSource: null,
|
pendingCompactionSource: null,
|
||||||
clearPendingReinjectOnNextUserInput: false,
|
clearPendingReinjectOnNextUserInput: false,
|
||||||
lastCompactionFirstKeptEntryId: null,
|
lastCompactionFirstKeptEntryId: null,
|
||||||
|
lastCompactionEntryId: null,
|
||||||
|
deferredDeliveredForCompactionId: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -352,6 +352,46 @@ export function filterPendingReinjectForConsume(
|
|||||||
return resolved;
|
return resolved;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mid-turn defer delivery via sendMessage/steer (SPEC §6.5.1, Phase 15 / B-003).
|
||||||
|
* Clears pendingReinject and records compaction id so before_agent_start does not duplicate.
|
||||||
|
*/
|
||||||
|
export function deliverDeferredReinjectSteer(
|
||||||
|
pi: ExtensionAPI,
|
||||||
|
state: ExtensionState,
|
||||||
|
settings: SkillReinjectSettings,
|
||||||
|
registeredSkills: readonly Pick<Skill, "name" | "filePath" | "baseDir">[],
|
||||||
|
compactionRuntime: CompactionRuntime,
|
||||||
|
compactionEntryId: string,
|
||||||
|
ctx?: ExtensionContext,
|
||||||
|
): boolean {
|
||||||
|
if (state.pendingReinject.length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const pendingNames = filterPendingReinjectForConsume(
|
||||||
|
state.pendingReinject,
|
||||||
|
state,
|
||||||
|
settings,
|
||||||
|
registeredSkills,
|
||||||
|
ctx,
|
||||||
|
);
|
||||||
|
const content = buildDeferredReinjectContent(pendingNames, state, settings, registeredSkills, ctx);
|
||||||
|
state.pendingReinject = [];
|
||||||
|
if (!content) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pi.sendMessage(
|
||||||
|
{
|
||||||
|
customType: DEFERRED_REINJECT_CUSTOM_TYPE,
|
||||||
|
content,
|
||||||
|
display: true,
|
||||||
|
},
|
||||||
|
{ deliverAs: "steer" },
|
||||||
|
);
|
||||||
|
compactionRuntime.deferredDeliveredForCompactionId = compactionEntryId;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defer path on before_agent_start: inject one combined message, then clear queue (SPEC §6.5.1).
|
* Defer path on before_agent_start: inject one combined message, then clear queue (SPEC §6.5.1).
|
||||||
* Returns undefined when pendingReinject is empty or manual compaction scheduled a clear (SPEC §16.5).
|
* Returns undefined when pendingReinject is empty or manual compaction scheduled a clear (SPEC §16.5).
|
||||||
@@ -366,6 +406,12 @@ export function tryConsumeDeferredReinject(
|
|||||||
if (compactionRuntime?.clearPendingReinjectOnNextUserInput) {
|
if (compactionRuntime?.clearPendingReinjectOnNextUserInput) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
compactionRuntime?.deferredDeliveredForCompactionId &&
|
||||||
|
compactionRuntime.deferredDeliveredForCompactionId === compactionRuntime.lastCompactionEntryId
|
||||||
|
) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
if (state.pendingReinject.length === 0) {
|
if (state.pendingReinject.length === 0) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user