Fix runtime skill injection across adapters

This commit is contained in:
Dotta 2026-03-15 07:05:01 -05:00
parent 82f253c310
commit 7675fd0856
27 changed files with 506 additions and 222 deletions

View file

@ -12,7 +12,7 @@ import {
parseObject,
parseJson,
buildPaperclipEnv,
listPaperclipSkillEntries,
readPaperclipRuntimeSkillEntries,
joinPromptSections,
redactEnvForLogs,
ensureAbsoluteDirectory,
@ -41,11 +41,11 @@ async function buildSkillsDir(config: Record<string, unknown>): Promise<string>
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "paperclip-skills-"));
const target = path.join(tmp, ".claude", "skills");
await fs.mkdir(target, { recursive: true });
const availableEntries = await listPaperclipSkillEntries(__moduleDir);
const availableEntries = await readPaperclipRuntimeSkillEntries(config, __moduleDir);
const desiredNames = new Set(
resolveClaudeDesiredSkillNames(
config,
availableEntries.map((entry) => entry.name),
availableEntries,
),
);
for (const entry of availableEntries) {

View file

@ -6,24 +6,16 @@ import type {
AdapterSkillSnapshot,
} from "@paperclipai/adapter-utils";
import {
listPaperclipSkillEntries,
readPaperclipSkillSyncPreference,
readPaperclipRuntimeSkillEntries,
resolvePaperclipDesiredSkillNames,
} from "@paperclipai/adapter-utils/server-utils";
const __moduleDir = path.dirname(fileURLToPath(import.meta.url));
function resolveDesiredSkillNames(config: Record<string, unknown>, availableSkillNames: string[]) {
const preference = readPaperclipSkillSyncPreference(config);
return preference.explicit ? preference.desiredSkills : availableSkillNames;
}
async function buildClaudeSkillSnapshot(config: Record<string, unknown>): Promise<AdapterSkillSnapshot> {
const availableEntries = await listPaperclipSkillEntries(__moduleDir);
const availableEntries = await readPaperclipRuntimeSkillEntries(config, __moduleDir);
const availableByName = new Map(availableEntries.map((entry) => [entry.name, entry]));
const desiredSkills = resolveDesiredSkillNames(
config,
availableEntries.map((entry) => entry.name),
);
const desiredSkills = resolvePaperclipDesiredSkillNames(config, availableEntries);
const desiredSet = new Set(desiredSkills);
const entries: AdapterSkillEntry[] = availableEntries.map((entry) => ({
name: entry.name,
@ -35,6 +27,8 @@ async function buildClaudeSkillSnapshot(config: Record<string, unknown>): Promis
detail: desiredSet.has(entry.name)
? "Will be mounted into the ephemeral Claude skill directory on the next run."
: null,
required: Boolean(entry.required),
requiredReason: entry.requiredReason ?? null,
}));
const warnings: string[] = [];
@ -77,7 +71,7 @@ export async function syncClaudeSkills(
export function resolveClaudeDesiredSkillNames(
config: Record<string, unknown>,
availableSkillNames: string[],
availableEntries: Array<{ name: string; required?: boolean }>,
) {
return resolveDesiredSkillNames(config, availableSkillNames);
return resolvePaperclipDesiredSkillNames(config, availableEntries);
}