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
155b973e03
commit
bd38700876
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`),
|
||||
};
|
||||
|
|
@ -139,6 +139,14 @@ export const queryKeys = {
|
|||
detail: (skillId: string) => ["skill-registry", "skills", skillId] 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: {
|
||||
all: ["plugins"] as const,
|
||||
examples: ["plugins", "examples"] as const,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue