import { type D1, newId, queryDb } from "./db"; export interface Skill { id: string; name: string; description: string | null; content: string; created_at: string; updated_at: string; } export async function listSkills(db: D1): Promise { const res = await queryDb<{ id: string; name: string; description: string | null; content: string; created_at: string; updated_at: string }>( db, "SELECT id, name, description, content, created_at, updated_at FROM skills ORDER BY name ASC", ); return res.rows; } export async function getSkill(db: D1, id: string): Promise { const res = await queryDb(db, "SELECT id, name, description, content, created_at, updated_at FROM skills WHERE id = $1", [id]); return res.rows[0] || null; } export async function createSkill(db: D1, input: { name: string; description?: string | null; content: string }): Promise { const id = newId(); const now = new Date().toISOString(); await queryDb(db, "INSERT INTO skills (id, name, description, content, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6)", [ id, input.name, input.description || null, input.content, now, now, ]); return { id, name: input.name, description: input.description || null, content: input.content, created_at: now, updated_at: now, }; } export async function updateSkill(db: D1, id: string, input: { name?: string; description?: string | null; content?: string }): Promise { const now = new Date().toISOString(); const current = await getSkill(db, id); if (!current) throw new Error("Skill not found"); const name = input.name !== undefined ? input.name : current.name; const description = input.description !== undefined ? input.description : current.description; const content = input.content !== undefined ? input.content : current.content; await queryDb(db, "UPDATE skills SET name = $1, description = $2, content = $3, updated_at = $4 WHERE id = $5", [ name, description, content, now, id, ]); return { id, name, description, content, created_at: current.created_at, updated_at: now, }; } export async function deleteSkill(db: D1, id: string): Promise { await queryDb(db, "DELETE FROM skills WHERE id = $1", [id]); } export async function importSkillFromGithub(db: D1, ref: string): Promise { const parts = ref.split("@"); const branch = parts[1] || "main"; const pathParts = parts[0].split("/"); if (pathParts.length < 3) { throw new Error("Invalid GitHub ref format. Expected owner/repo/path[@branch]"); } const owner = pathParts[0]; const repo = pathParts[1]; const skillPath = pathParts.slice(2).join("/"); const skillName = pathParts[pathParts.length - 1]; const url = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/${skillPath}/SKILL.md`; try { const response = await fetch(url); if (!response.ok) { throw new Error(`Failed to fetch SKILL.md from GitHub: HTTP ${response.status}`); } const content = await response.text(); let description = `Imported skill ${skillName} from ${ref}`; const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/); if (match) { const yaml = match[1]; const descMatch = yaml.match(/description:\s*["']?([^"'\r\n]+)["']?/); if (descMatch) { description = descMatch[1]; } } return await createSkill(db, { name: skillName, description, content, }); } catch (err: any) { throw new Error(`Failed to import skill: ${err.message}`); } }