import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { cursorPage, type PreferenceKind, type PreferenceStatus, PreferenceSuppression, PreferenceTag, type PreferenceTagCreate, PreferenceTagRevisionList, type PreferenceTagUpdate, } from "@umt/contracts"; import { api } from "~/lib/api.ts"; import { getParsed, parseOrThrow } from "./library.ts"; // 偏好标签与抑制记录(REQ §6.7):停用/删除/语义变更都会留抑制记录,Agent 不得据旧证据自动加回。 export const preferenceKeys = { all: ["preferences"] as const, tags: (f: TagFilters) => ["preferences", "tags", f] as const, suppressions: (active?: boolean) => ["preferences", "suppressions", active ?? "all"] as const, }; export type TagFilters = { status?: PreferenceStatus; kind?: PreferenceKind }; const TagPage = cursorPage(PreferenceTag); const SupPage = cursorPage(PreferenceSuppression); /** 缺省不含已删除;status=deleted 单独取(历史) */ export function usePreferenceTags(filters: TagFilters = {}) { return useQuery({ queryKey: preferenceKeys.tags(filters), queryFn: ({ signal }) => getParsed(TagPage, "/preference-tags", { ...filters, limit: 200 }, signal), }); } export function useSuppressions(active?: boolean) { return useQuery({ queryKey: preferenceKeys.suppressions(active), queryFn: ({ signal }) => getParsed( SupPage, "/preference-suppressions", { active: active === undefined ? undefined : String(active), limit: 200 }, signal, ), }); } /** 修订历史(审计事件回放,新→旧) */ export function useTagRevisions(id: string | null | undefined) { return useQuery({ queryKey: ["preferences", "revisions", id ?? ""], enabled: !!id, queryFn: async ({ signal }) => (await getParsed(PreferenceTagRevisionList, `/preference-tags/${id}/revisions`, undefined, signal)).items, }); } function useInvalidate() { const qc = useQueryClient(); return () => void qc.invalidateQueries({ queryKey: preferenceKeys.all }); } const parseTag = (d: unknown) => parseOrThrow(PreferenceTag, d, "/preference-tags"); export function useCreateTag() { const done = useInvalidate(); return useMutation({ mutationFn: (body: PreferenceTagCreate) => api.post("/preference-tags", body).then(parseTag), onSuccess: done, }); } /** 编辑 / 停用(status=disabled)/ 重新启用(status=active,同时解除同语义抑制) */ export function useUpdateTag() { const done = useInvalidate(); return useMutation({ mutationFn: ({ id, ...body }: PreferenceTagUpdate & { id: string }) => api.patch(`/preference-tags/${id}`, body).then(parseTag), onSuccess: done, }); } /** 删除:标记 deleted 并留抑制记录 */ export function useDeleteTag() { const done = useInvalidate(); return useMutation({ mutationFn: (id: string) => api.del(`/preference-tags/${id}`), onSuccess: done, }); } /** 解除抑制(明确授权后 Agent 才能再次提出同一偏好) */ export function useLiftSuppression() { const done = useInvalidate(); return useMutation({ mutationFn: (v: { id: string; reason?: string }) => api .patch(`/preference-suppressions/${v.id}`, { active: false, reason: v.reason }) .then((d) => parseOrThrow(PreferenceSuppression, d, "/preference-suppressions")), onSuccess: done, }); }