import { parseSkill } from './registry'; /** * Account-authored skills, as stored. * * A custom skill is its Markdown source and nothing else — the same artefact a * file in `src/skills/` is, read back by the same parser. These helpers exist so * the Add Skill dialog and the Skills page write that list identically; two * writers with two shapes would be a second skill system by accident. */ /** The starting definition offered to an author, in the existing format. */ export const skillTemplate = ({ id = '', name = '', description = '', pages = [] } = {}) => `--- id: ${id || 'my-skill'} name: ${name || 'My Skill'} description: ${description || 'What this skill helps Owliver do.'} pages: ${(pages?.length ? pages : ['positions']).map((p) => ` - ${p}`).join('\n')} status: active triggers: - ${(name || 'my skill').toLowerCase()} --- # ${name || 'My Skill'} ## Purpose Describe what Owliver should help with on these pages. ## Capabilities - Describe one thing the skill can do. - Add more as needed. `; /** Parses a stored entry, tolerating the bare-string form. */ const sourceOf = (entry) => (typeof entry === 'string' ? entry : entry?.raw ?? ''); /** * The stored list with `source` added or replaced. * * Matching is by skill id, so editing a skill overwrites its own entry rather * than adding a near-duplicate beside it. */ export function upsertCustomSkill(existing = [], source) { const skill = parseSkill(source, { custom: true }); const rest = existing.filter((entry) => { try { return parseSkill(sourceOf(entry), { custom: true }).id !== skill.id; } catch { return true; } }); return { skill, next: [...rest, { path: `custom/${skill.id}.md`, raw: source }] }; } /** The stored list without the skill of this id. */ export function removeCustomSkill(existing = [], id) { return existing.filter((entry) => { try { return parseSkill(sourceOf(entry), { custom: true }).id !== id; } catch { return true; } }); } /** The stored Markdown for one custom skill, or null if the account has none. */ export function customSkillSource(existing = [], id) { for (const entry of existing) { try { if (parseSkill(sourceOf(entry), { custom: true }).id === id) return sourceOf(entry); } catch { /* An unparseable entry cannot be the one being edited. */ } } return null; }