feat(11-03): add skill groups frontend API client and query keys
- Create ui/src/api/skillGroups.ts with skillGroupsApi object - All 14 methods covering group CRUD, members, export/import, agent assignments - removeGroup uses raw fetch for DELETE-with-body (api.delete has no body support) - Add skillGroups namespace to ui/src/lib/queryKeys.ts with 6 key factories
This commit is contained in:
parent
ed87cc721f
commit
37476870a2
2 changed files with 101 additions and 0 deletions
93
ui/src/api/skillGroups.ts
Normal file
93
ui/src/api/skillGroups.ts
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
import { api, ApiError } from "./client";
|
||||||
|
|
||||||
|
export type SkillGroupRow = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
description: string | null;
|
||||||
|
isBuiltin: number;
|
||||||
|
createdAt: number;
|
||||||
|
updatedAt: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GroupMemberRow = {
|
||||||
|
groupId: string;
|
||||||
|
skillId: string;
|
||||||
|
addedAt: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AssignResult = {
|
||||||
|
installed: string[];
|
||||||
|
skipped: string[];
|
||||||
|
pendingPlugin: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GroupExport = {
|
||||||
|
version: "1";
|
||||||
|
group: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
description: string | null;
|
||||||
|
members: string[];
|
||||||
|
parents: string[];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const skillGroupsApi = {
|
||||||
|
listGroups: () => api.get<SkillGroupRow[]>("/skill-registry/groups"),
|
||||||
|
|
||||||
|
getGroup: (groupId: string) =>
|
||||||
|
api.get<SkillGroupRow>(`/skill-registry/groups/${groupId}`),
|
||||||
|
|
||||||
|
createGroup: (input: { name: string; description?: string }) =>
|
||||||
|
api.post<SkillGroupRow>("/skill-registry/groups", input),
|
||||||
|
|
||||||
|
updateGroup: (groupId: string, patch: { name?: string; description?: string }) =>
|
||||||
|
api.patch<SkillGroupRow>(`/skill-registry/groups/${groupId}`, patch),
|
||||||
|
|
||||||
|
deleteGroup: (groupId: string) =>
|
||||||
|
api.delete<void>(`/skill-registry/groups/${groupId}`),
|
||||||
|
|
||||||
|
listMembers: (groupId: string) =>
|
||||||
|
api.get<GroupMemberRow[]>(`/skill-registry/groups/${groupId}/members`),
|
||||||
|
|
||||||
|
addMember: (groupId: string, skillId: string) =>
|
||||||
|
api.post<{ ok: boolean }>(`/skill-registry/groups/${groupId}/members`, { skillId }),
|
||||||
|
|
||||||
|
removeMember: (groupId: string, skillId: string) =>
|
||||||
|
api.delete<void>(`/skill-registry/groups/${groupId}/members/${skillId}`),
|
||||||
|
|
||||||
|
exportGroup: (groupId: string) =>
|
||||||
|
api.get<GroupExport>(`/skill-registry/groups/${groupId}/export`),
|
||||||
|
|
||||||
|
importGroup: (data: GroupExport) =>
|
||||||
|
api.post<SkillGroupRow>("/skill-registry/groups/import", data),
|
||||||
|
|
||||||
|
listAgentGroups: (agentId: string) =>
|
||||||
|
api.get<SkillGroupRow[]>(`/skill-registry/agents/${agentId}/groups`),
|
||||||
|
|
||||||
|
assignGroup: (agentId: string, groupId: string, agentSkillsDir: string) =>
|
||||||
|
api.post<AssignResult>(`/skill-registry/agents/${agentId}/groups`, {
|
||||||
|
groupId,
|
||||||
|
agentSkillsDir,
|
||||||
|
}),
|
||||||
|
|
||||||
|
removeGroup: async (agentId: string, groupId: string, agentSkillsDir: string): Promise<void> => {
|
||||||
|
const res = await fetch(`/api/skill-registry/agents/${agentId}/groups/${groupId}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
credentials: "include",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({ agentSkillsDir }),
|
||||||
|
});
|
||||||
|
if (!res.ok && res.status !== 204) {
|
||||||
|
const errorBody = await res.json().catch(() => null);
|
||||||
|
throw new ApiError(
|
||||||
|
(errorBody as { error?: string } | null)?.error ?? `Request failed: ${res.status}`,
|
||||||
|
res.status,
|
||||||
|
errorBody,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
listAgentSkills: (agentId: string) =>
|
||||||
|
api.get<string[]>(`/skill-registry/agents/${agentId}/skills`),
|
||||||
|
};
|
||||||
|
|
@ -138,6 +138,14 @@ export const queryKeys = {
|
||||||
detail: (skillId: string) => ["skill-registry", "skills", skillId] as const,
|
detail: (skillId: string) => ["skill-registry", "skills", skillId] as const,
|
||||||
versions: (skillId: string) => ["skill-registry", "skills", skillId, "versions"] as const,
|
versions: (skillId: string) => ["skill-registry", "skills", skillId, "versions"] as const,
|
||||||
},
|
},
|
||||||
|
skillGroups: {
|
||||||
|
list: ["skill-groups"] as const,
|
||||||
|
detail: (groupId: string) => ["skill-groups", groupId] as const,
|
||||||
|
members: (groupId: string) => ["skill-groups", groupId, "members"] as const,
|
||||||
|
agentGroups: (agentId: string) => ["skill-groups", "agent", agentId] as const,
|
||||||
|
agentSkills: (agentId: string) => ["skill-groups", "agent", agentId, "skills"] as const,
|
||||||
|
agentEffective: (agentId: string) => ["skill-groups", "agent", agentId, "effective"] as const,
|
||||||
|
},
|
||||||
plugins: {
|
plugins: {
|
||||||
all: ["plugins"] as const,
|
all: ["plugins"] as const,
|
||||||
examples: ["plugins", "examples"] as const,
|
examples: ["plugins", "examples"] as const,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue