fix(pi-local): ensure skills directory exists before passing --skill flag

- Hoist PI_AGENT_SKILLS_DIR to module-level constant to avoid duplicate path computation
- Always create ~/.pi/agent/skills directory before early return in ensurePiSkillsInjected, so the path is valid when --skill flag is passed
This commit is contained in:
Richard Anaya
2026-03-18 20:40:55 -07:00
parent f37e0aa7b3
commit 5536e6b91e

View File

@@ -26,6 +26,7 @@ import { ensurePiModelConfiguredAndAvailable } from "./models.js";
const __moduleDir = path.dirname(fileURLToPath(import.meta.url));
const PAPERCLIP_SESSIONS_DIR = path.join(os.homedir(), ".pi", "paperclips");
const PI_AGENT_SKILLS_DIR = path.join(os.homedir(), ".pi", "agent", "skills");
function firstNonEmptyLine(text: string): string {
return (
@@ -56,35 +57,35 @@ function resolvePiBiller(env: Record<string, string>, provider: string | null):
async function ensurePiSkillsInjected(onLog: AdapterExecutionContext["onLog"]) {
const skillsEntries = await listPaperclipSkillEntries(__moduleDir);
await fs.mkdir(PI_AGENT_SKILLS_DIR, { recursive: true });
if (skillsEntries.length === 0) return;
const piSkillsHome = path.join(os.homedir(), ".pi", "agent", "skills");
await fs.mkdir(piSkillsHome, { recursive: true });
const removedSkills = await removeMaintainerOnlySkillSymlinks(
piSkillsHome,
PI_AGENT_SKILLS_DIR,
skillsEntries.map((entry) => entry.name),
);
for (const skillName of removedSkills) {
await onLog(
"stderr",
`[paperclip] Removed maintainer-only Pi skill "${skillName}" from ${piSkillsHome}\n`,
`[paperclip] Removed maintainer-only Pi skill "${skillName}" from ${PI_AGENT_SKILLS_DIR}\n`,
);
}
for (const entry of skillsEntries) {
const target = path.join(piSkillsHome, entry.name);
const target = path.join(PI_AGENT_SKILLS_DIR, entry.name);
try {
const result = await ensurePaperclipSkillSymlink(entry.source, target);
if (result === "skipped") continue;
await onLog(
"stderr",
`[paperclip] ${result === "repaired" ? "Repaired" : "Injected"} Pi skill "${entry.name}" into ${piSkillsHome}\n`,
`[paperclip] ${result === "repaired" ? "Repaired" : "Injected"} Pi skill "${entry.name}" into ${PI_AGENT_SKILLS_DIR}\n`,
);
} catch (err) {
await onLog(
"stderr",
`[paperclip] Failed to inject Pi skill "${entry.name}" into ${piSkillsHome}: ${err instanceof Error ? err.message : String(err)}\n`,
`[paperclip] Failed to inject Pi skill "${entry.name}" into ${PI_AGENT_SKILLS_DIR}: ${err instanceof Error ? err.message : String(err)}\n`,
);
}
}
@@ -337,8 +338,7 @@ export async function execute(ctx: AdapterExecutionContext): Promise<AdapterExec
args.push("--session", sessionFile);
// Add Paperclip skills directory so Pi can load the paperclip skill
const piSkillsHome = path.join(os.homedir(), ".pi", "agent", "skills");
args.push("--skill", piSkillsHome);
args.push("--skill", PI_AGENT_SKILLS_DIR);
if (extraArgs.length > 0) args.push(...extraArgs);