79 lines
2.3 KiB
JavaScript
79 lines
2.3 KiB
JavaScript
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;
|
|
}
|