From bf0a61a9db88dfff9dac5886971253c8f4d27c14 Mon Sep 17 00:00:00 2001 From: Mikkel Georgsen Date: Wed, 1 Apr 2026 02:30:29 +0200 Subject: [PATCH] feat(10-01): add skillRegistry API client and query keys - Create ui/src/api/skillRegistry.ts with typed methods for all 7 endpoints - Use two-segment URL paths (/sourceId/slug) for Express 5 compatibility - Add skillRegistry namespace to queryKeys.ts (list/detail/versions) --- ui/src/api/skillRegistry.ts | 46 +++++++++++++++++++++++++++++++++++++ ui/src/lib/queryKeys.ts | 5 ++++ 2 files changed, 51 insertions(+) create mode 100644 ui/src/api/skillRegistry.ts diff --git a/ui/src/api/skillRegistry.ts b/ui/src/api/skillRegistry.ts new file mode 100644 index 00000000..b8b0a422 --- /dev/null +++ b/ui/src/api/skillRegistry.ts @@ -0,0 +1,46 @@ +import { api } from "./client"; + +export type SkillListItem = { + id: string; + name: string; + description: string | null; + sourceId: string; + category: string | null; + activeVersionId: string | null; + removedAt: number | null; + averageRating: number | null; + ratingCount: number | null; +}; + +export type SkillVersion = { + id: string; + skillId: string; + version: string; + fetchedAt: number; + cacheDir: string | null; +}; + +function skillPath(skillId: string): string { + const [sourceId, ...slugParts] = skillId.split("/"); + const slug = slugParts.join("/"); + return `/skill-registry/skills/${sourceId}/${slug}`; +} + +export const skillRegistryApi = { + list: (opts?: { includeRemoved?: boolean }) => + api.get( + `/skill-registry/skills${opts?.includeRemoved ? "?includeRemoved=true" : ""}`, + ), + getById: (skillId: string) => + api.get(skillPath(skillId)), + getVersions: (skillId: string) => + api.get(`${skillPath(skillId)}/versions`), + fetch: () => + api.post<{ fetched: number; errors: string[] }>("/skill-registry/fetch", {}), + install: (skillId: string, agentSkillsDir: string) => + api.post(`${skillPath(skillId)}/install`, { agentSkillsDir }), + rollback: (skillId: string, versionId: string, agentSkillsDir: string) => + api.post(`${skillPath(skillId)}/rollback`, { versionId, agentSkillsDir }), + remove: (skillId: string) => + api.delete(skillPath(skillId)), +}; diff --git a/ui/src/lib/queryKeys.ts b/ui/src/lib/queryKeys.ts index 0acbc1f5..24d5fe18 100644 --- a/ui/src/lib/queryKeys.ts +++ b/ui/src/lib/queryKeys.ts @@ -134,6 +134,11 @@ export const queryKeys = { skills: { available: ["skills", "available"] as const, }, + skillRegistry: { + list: ["skill-registry", "skills"] as const, + detail: (skillId: string) => ["skill-registry", "skills", skillId] as const, + versions: (skillId: string) => ["skill-registry", "skills", skillId, "versions"] as const, + }, plugins: { all: ["plugins"] as const, examples: ["plugins", "examples"] as const,