Files
PaperClipAI/ui/src/api/museInvitations.ts
T
DottaandPaperclip 896f3c7f3b Add personal Muse operator setup and composer controls (#16450)
Add Muse invitation, connection readiness and scoped operator controls.

Keep connection state tied to the current company, person, agent and binding. Surface failed reads and invalidate stale cleanup observations; require current authority and exact readback. Preserve Dot/Grok setup, source-trust limits and existing design tokens.

Carry actual merged backend e6dcc6b095 through a normal forward merge. Preserve its project-write authority fix, existing migration bytes and upstream idle-serving behavior; no new UI behavior is authored by this source carry. Current-head CI and substantive review remain merge gates; final canonical and deployed-provider qualification remain separate.

Refs #16450.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-17 23:01:42 -05:00

24 lines
1.9 KiB
TypeScript

import { api, detachInflightGet } from "./client";
import type {
MuseInvitation, MuseInvitationInput, MuseConnection, MusePairing, MusePairingInput,
MuseVerifyInput, MuseVerifyResult, MuseRevokeInput, MuseDetectorCleanupAttestationInput, MuseAttestStopInput,
} from "@paperclipai/shared";
const path = (companyId: string, agentId: string) => `/companies/${companyId}/agents/${agentId}/muse-binding`;
function accountScopedRead<T>(path: string, signal?: AbortSignal) {
// Query keys carry the operator. Path-only GET coalescing must not join a
// request issued under the previous account; React Query handles same-key reads.
detachInflightGet(path);
return api.get<T>(path, { signal, cache: "no-store" });
}
export const museInvitationsApi = {
resume: (companyId: string, signal?: AbortSignal) => accountScopedRead<MuseInvitation | null>(`/companies/${companyId}/muse-invitations`, signal),
create: (companyId: string, input: MuseInvitationInput) => api.post<MuseInvitation>(`/companies/${companyId}/muse-invitations`, input),
connection: (companyId: string, agentId: string, signal?: AbortSignal) => accountScopedRead<MuseConnection>(path(companyId, agentId), signal),
pair: (companyId: string, agentId: string, input: MusePairingInput) => api.post<MusePairing>(path(companyId, agentId), input),
verify: (companyId: string, agentId: string, input: MuseVerifyInput) => api.post<MuseVerifyResult>(path(companyId, agentId) + "/verify", input),
revoke: (companyId: string, agentId: string, input: MuseRevokeInput) => api.post<void>(path(companyId, agentId) + "/revoke", input),
attestDetectorCleanup: (companyId: string, agentId: string, input: MuseDetectorCleanupAttestationInput) => api.post<void>(path(companyId, agentId) + "/attest-detector-cleanup", input),
attestStop: (companyId: string, agentId: string, input: MuseAttestStopInput) => api.post<void>(path(companyId, agentId) + "/attest-stop", input),
};