Phase 7: add defer inject on before_agent_start — combined skill blocks, clear queue.
Builds one injected custom message from pendingReinject via expandSkill, clears the queue only after content is built successfully. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
import type {
|
||||
BeforeAgentStartEventResult,
|
||||
ExtensionContext,
|
||||
SessionCompactEvent,
|
||||
Skill,
|
||||
} from "@earendil-works/pi-coding-agent";
|
||||
import { expandSkill } from "./expand.js";
|
||||
import {
|
||||
filterSkillsNeedingReinject,
|
||||
getKeptEntries,
|
||||
@@ -11,6 +13,8 @@ import {
|
||||
import type { SkillReinjectSettings } from "./settings.js";
|
||||
import type { ExtensionState } from "./state.js";
|
||||
|
||||
export const DEFERRED_REINJECT_CUSTOM_TYPE = "skill-reinject:inject";
|
||||
|
||||
/** Names still registered in resourceLoader (SPEC §5.2). */
|
||||
export function registeredSkillNames(skills: readonly Pick<Skill, "name">[]): ReadonlySet<string> {
|
||||
return new Set(skills.map((skill) => skill.name));
|
||||
@@ -54,3 +58,60 @@ export function enqueueDeferredReinjectFromCompact(
|
||||
registeredSkills,
|
||||
);
|
||||
}
|
||||
|
||||
/** Combined skill-block user text for pending names in queue order (SPEC §5.3). */
|
||||
export function buildDeferredReinjectContent(
|
||||
pendingNames: readonly string[],
|
||||
state: ExtensionState,
|
||||
settings: SkillReinjectSettings,
|
||||
registeredSkills: readonly Pick<Skill, "name" | "filePath" | "baseDir">[],
|
||||
): string {
|
||||
const registeredByName = new Map(registeredSkills.map((skill) => [skill.name, skill]));
|
||||
const blocks: string[] = [];
|
||||
for (const name of pendingNames) {
|
||||
const tracked = state.skills.find((skill) => skill.name === name);
|
||||
const registered = registeredByName.get(name);
|
||||
if (!tracked || !registered) {
|
||||
continue;
|
||||
}
|
||||
blocks.push(
|
||||
expandSkill(
|
||||
{
|
||||
name: tracked.name,
|
||||
filePath: registered.filePath,
|
||||
baseDir: registered.baseDir,
|
||||
},
|
||||
settings.suffix,
|
||||
),
|
||||
);
|
||||
}
|
||||
return blocks.join("\n\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Defer path on before_agent_start: inject one combined message, then clear queue (SPEC §6.5.1).
|
||||
* Returns undefined when pendingReinject is empty.
|
||||
*/
|
||||
export function tryConsumeDeferredReinject(
|
||||
state: ExtensionState,
|
||||
settings: SkillReinjectSettings,
|
||||
registeredSkills: readonly Pick<Skill, "name" | "filePath" | "baseDir">[],
|
||||
): BeforeAgentStartEventResult | undefined {
|
||||
if (state.pendingReinject.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
const pendingNames = [...state.pendingReinject];
|
||||
const content = buildDeferredReinjectContent(pendingNames, state, settings, registeredSkills);
|
||||
if (!content) {
|
||||
state.pendingReinject = [];
|
||||
return undefined;
|
||||
}
|
||||
state.pendingReinject = [];
|
||||
return {
|
||||
message: {
|
||||
customType: DEFERRED_REINJECT_CUSTOM_TYPE,
|
||||
content,
|
||||
display: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user