position ui and owliver update
This commit is contained in:
78
src/lib/skills/customSkills.js
Normal file
78
src/lib/skills/customSkills.js
Normal file
@@ -0,0 +1,78 @@
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user