Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | 1x 9x 9x 9x 9x 9x 9x 9x 9x 5x 1x 1x 9x 2x 1x 9x 9x 8x 1x | import type {
AdapterSkillContext,
AdapterSkillSnapshot,
AdapterSkillEntry,
} from "@paperclipai/adapter-utils";
import {
readPaperclipRuntimeSkillEntries,
resolvePaperclipDesiredSkillNames,
readInstalledSkillTargets,
} from "@paperclipai/adapter-utils/server-utils";
import path from "node:path";
const SKILLS_HOME = "/paperclip/.claude/skills";
async function buildK8sSkillSnapshot(
config: Record<string, unknown>,
): Promise<AdapterSkillSnapshot> {
const availableEntries = await readPaperclipRuntimeSkillEntries(config, import.meta.dirname ?? __dirname);
const availableByKey = new Map(availableEntries.map((e) => [e.key, e]));
const desiredSkills = resolvePaperclipDesiredSkillNames(config, availableEntries);
const desiredSet = new Set(desiredSkills);
const installed = await readInstalledSkillTargets(SKILLS_HOME);
const entries: AdapterSkillEntry[] = availableEntries.map((entry) => ({
key: entry.key,
runtimeName: entry.runtimeName,
desired: desiredSet.has(entry.key),
managed: true,
state: desiredSet.has(entry.key) ? "configured" : "available",
origin: entry.required ? "paperclip_required" : "company_managed",
originLabel: entry.required ? "Required by Paperclip" : "Managed by Paperclip",
readOnly: false,
sourcePath: entry.source,
targetPath: null,
detail: desiredSet.has(entry.key)
? "Materialized into the PVC-backed Claude prompt bundle before each K8s Job run."
: null,
required: Boolean(entry.required),
requiredReason: entry.requiredReason ?? null,
}));
const warnings: string[] = [];
for (const desiredSkill of desiredSkills) {
if (availableByKey.has(desiredSkill)) continue;
warnings.push(`Desired skill "${desiredSkill}" is not available from the Paperclip skills directory.`);
entries.push({
key: desiredSkill,
runtimeName: null,
desired: true,
managed: true,
state: "missing",
origin: "external_unknown",
originLabel: "External or unavailable",
readOnly: false,
sourcePath: undefined,
targetPath: undefined,
detail: "Paperclip cannot find this skill in the runtime skills directory.",
});
}
for (const [name, installedEntry] of installed.entries()) {
if (availableEntries.some((e) => e.runtimeName === name)) continue;
entries.push({
key: name,
runtimeName: name,
desired: false,
managed: false,
state: "external",
origin: "user_installed",
originLabel: "User-installed",
locationLabel: "~/.claude/skills",
readOnly: true,
sourcePath: null,
targetPath: installedEntry.targetPath ?? path.join(SKILLS_HOME, name),
detail: "Installed outside Paperclip management in the Claude skills home.",
});
}
entries.sort((a, b) => a.key.localeCompare(b.key));
return {
adapterType: "claude_k8s",
supported: true,
mode: "ephemeral",
desiredSkills,
entries,
warnings,
};
}
export async function listK8sSkills(ctx: AdapterSkillContext): Promise<AdapterSkillSnapshot> {
return buildK8sSkillSnapshot(ctx.config);
}
export async function syncK8sSkills(
ctx: AdapterSkillContext,
_desiredSkills: string[],
): Promise<AdapterSkillSnapshot> {
return buildK8sSkillSnapshot(ctx.config);
}
|