Phase 9: track slash /skill:name on input hook — SPEC §6.2 #1.
Wire input handler to detect slash skills and upsert into session state using registered skill metadata from before_agent_start cache or loadSkills fallback. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+31
-3
@@ -1,7 +1,35 @@
|
||||
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
||||
import type { ExtensionAPI, Skill } from "@earendil-works/pi-coding-agent";
|
||||
import { detectSlashSkill } from "./detect.js";
|
||||
import { findRegisteredSkillByName, resolveRegisteredSkills } from "./skills-registry.js";
|
||||
import { createInitialState, trackSkill } from "./state.js";
|
||||
|
||||
export default function skillReinject(pi: ExtensionAPI): void {
|
||||
pi.on("session_start", () => {
|
||||
// Phase 0 shell — hooks wired in later phases
|
||||
const state = createInitialState();
|
||||
let registeredSkills: Skill[] = [];
|
||||
|
||||
pi.on("before_agent_start", async (event) => {
|
||||
registeredSkills = event.systemPromptOptions.skills ?? registeredSkills;
|
||||
});
|
||||
|
||||
pi.on("input", async (event, ctx) => {
|
||||
if (event.source === "extension") {
|
||||
return { action: "continue" };
|
||||
}
|
||||
|
||||
const skillName = detectSlashSkill(event.text);
|
||||
if (skillName) {
|
||||
const skills = resolveRegisteredSkills(ctx.cwd, registeredSkills);
|
||||
const skill = findRegisteredSkillByName(skills, skillName);
|
||||
if (skill) {
|
||||
trackSkill(state, {
|
||||
name: skill.name,
|
||||
filePath: skill.filePath,
|
||||
baseDir: skill.baseDir,
|
||||
source: "slash",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return { action: "continue" };
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { getAgentDir, loadSkills, type Skill } from "@earendil-works/pi-coding-agent";
|
||||
|
||||
/** First match on name collision (SPEC §11). */
|
||||
export function findRegisteredSkillByName(
|
||||
skills: readonly Skill[],
|
||||
name: string,
|
||||
): Skill | undefined {
|
||||
return skills.find((skill) => skill.name === name);
|
||||
}
|
||||
|
||||
/** Mirror resourceLoader skill list when cache is empty (e.g. first user input). */
|
||||
export function loadRegisteredSkills(cwd: string): Skill[] {
|
||||
return loadSkills({
|
||||
cwd,
|
||||
agentDir: getAgentDir(),
|
||||
skillPaths: [],
|
||||
includeDefaults: true,
|
||||
}).skills;
|
||||
}
|
||||
|
||||
/** Prefer live skills from before_agent_start; fall back to loadSkills (SPEC §6.2). */
|
||||
export function resolveRegisteredSkills(cwd: string, cached: readonly Skill[]): Skill[] {
|
||||
if (cached.length > 0) {
|
||||
return [...cached];
|
||||
}
|
||||
return loadRegisteredSkills(cwd);
|
||||
}
|
||||
Reference in New Issue
Block a user