/** * Webhook payload transforms for OpenClaw skill deployment. * * Pure functions — no auth, no network calls, no external dependencies. */ export type Command = 'skill-install'; interface SkillEntry { skill_id?: string; skill_slug?: string; skill_name?: string; repo_url?: string; repo_subpath?: string; git_ref?: string; commit_sha?: string; } export function run(command: Command, args: string[]) { if (command === 'skill-install') { const payload = args[0] ? JSON.parse(args[0]) : {}; const result = transformSkillInstall(payload); console.log(result.message); return result; } } export function transformSkillInstall(payload: Record) { const body = (payload.payload ?? payload) as Record; const skills = body.skills as SkillEntry[] | undefined; if (!skills || skills.length === 0) { return { message: "skill-update webhook received but no `skills` array in payload. Nothing to install.", }; } const lines: string[] = [ `Install/update ${skills.length} skill(s) from git. Execute all steps directly — do not ask questions.`, ``, ]; for (const skill of skills) { const { repo_url, skill_slug, skill_name, git_ref, repo_subpath } = skill; if (!repo_url) { lines.push(`⚠️ Skipping skill "${skill_slug ?? "unknown"}" — missing repo_url.`, ``); continue; } const dirName = skill_slug ?? repo_url.split("/").pop()?.replace(/\.git$/, "") ?? "unknown-skill"; const installPath = `~/clawd/skills/${dirName}`; const subpath = repo_subpath ? `/${repo_subpath}` : ""; const skillDir = repo_subpath ? `${installPath}/${repo_subpath}` : installPath; lines.push( `── Skill: ${skill_name ?? dirName} (${git_ref ?? "default branch"})`, ` Repo: ${repo_url}`, ` Target: ${skillDir}`, ``, ` Steps:`, ` 1. If ${installPath} exists: cd ${installPath} && git fetch --tags && git checkout ${git_ref ?? "HEAD"}`, ` Otherwise: git clone ${repo_url} ${installPath} && cd ${installPath} && git checkout ${git_ref ?? "HEAD"}`, ` 2. cd ${skillDir}`, ` 3. If install.sh exists: bash install.sh`, ` Otherwise: npm install (if package.json exists) or skip`, ` 4. Reply with one line: installed/updated + skill name + version.`, ``, ); } return { message: lines.join("\n") }; }