forked from EduCraft/curriculum-project-hub
feat(admin): web-based skill management with file editor
Add full skill lifecycle to the org-admin web surface: create, read, edit, disable. Skills are directories (SKILL.md manifest + supporting files), content-addressed by SHA-256 in an immutable store. Backend: - skillStore: extract commitSkillContent (shared populate→inspect→ dedup→atomic rename); add importSkillFromFiles (in-memory file list ingestion) and readSkillFiles (read stored version back as UTF-8) - configuration: add installSkillFromFiles, readSkillFiles, disableSkill (soft-delete + archive bound role sessions), updateSkillDescription (label-only, no archival); refactor installSkill to share commitInstalledSkill - agentConfigRoutes: wire skillStoreRoot; add GET /agent-skills/:name/files, PUT /agent-skills/:name (create/replace), PATCH /agent-skills/:name (description/disable) - orgRoutes: pass readSkillStoreRoot() to agent config routes Frontend: - api.ts: agentSkillFiles, installAgentSkill, patchAgentSkill methods - SkillEditor.svelte: file tree + text editor + version/description form - skills/+page.svelte: skill list, create form (generates SKILL.md template), per-skill editor - layout: add 技能 nav item ADR-0018: update Decision to reflect web surface joining host-console CLI in the shared content-addressed ingestion pipeline. Spec (AgentRole.lean): unchanged — storage mechanism is OPEN, web installation is one implementation of it.
This commit is contained in:
@@ -253,6 +253,17 @@ export interface AgentSkillRow {
|
||||
boundRoleIds: readonly string[];
|
||||
}
|
||||
|
||||
export interface SkillFileEntry {
|
||||
path: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
export interface InstalledSkillResult {
|
||||
id: string;
|
||||
name: string;
|
||||
contentDigest: string;
|
||||
}
|
||||
|
||||
export interface AgentModelRow {
|
||||
id: string;
|
||||
label: string;
|
||||
@@ -392,5 +403,11 @@ export const api = {
|
||||
skillNames: string[];
|
||||
}>,
|
||||
agentSkills: (slug: string) => get(`${orgBase(slug)}/agent-skills`) as Promise<{ skills: AgentSkillRow[] }>,
|
||||
agentSkillFiles: (slug: string, name: string) =>
|
||||
get(`${orgBase(slug)}/agent-skills/${encodeURIComponent(name)}/files`) as Promise<{ files: SkillFileEntry[] }>,
|
||||
installAgentSkill: (slug: string, name: string, body: { version: string; files: readonly SkillFileEntry[] }) =>
|
||||
put(`${orgBase(slug)}/agent-skills/${encodeURIComponent(name)}`, body) as Promise<InstalledSkillResult>,
|
||||
patchAgentSkill: (slug: string, name: string, body: { description?: string; disabled?: boolean }) =>
|
||||
patch(`${orgBase(slug)}/agent-skills/${encodeURIComponent(name)}`, body) as Promise<{ disabled?: boolean; updated?: boolean }>,
|
||||
agentModels: (slug: string) => get(`${orgBase(slug)}/agent-models`) as Promise<{ models: AgentModelRow[] }>,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user