/** * Communication plugin API client. * * All requests use the shared `apiClient` (`baseURL: '/api/v1'`) and target the * kommunikation plugin routes under `/comm/...`. */ import { apiDelete, apiGet, apiPatch, apiPost } from './client'; // ─── Types ─── export interface Participant { id: string; conversation_id: string; participant_id: string | null; participant_type: string; display_name: string | null; role: string; } export interface Conversation { id: string; title: string | null; is_locked: boolean; locked_by: string | null; is_direct: boolean; is_archived: boolean; is_pinned: boolean; created_by: string | null; created_by_type: string; last_msg_at: string | null; last_msg_preview: string | null; last_msg_sender_type: string | null; participants: Participant[]; unread_count: number; metadata: Record; } export interface MessageBlock { id: string; block_type: string; block_data: Record; sort_order: number; } export interface MessageAttachment { id: string; file_id: string | null; file_source: string; file_name: string; file_type: string; file_size: number | null; thumbnail_path: string | null; } export interface Message { id: string; conversation_id: string; sender_id: string | null; sender_type: string; content: string; content_format: string; metadata: Record; reply_to_id: string | null; is_pinned: boolean; created_at: string | null; edited_at: string | null; blocks: MessageBlock[]; attachments: MessageAttachment[]; reactions: any[]; } export interface ConversationListResponse { items: Conversation[]; total: number; } export interface MessageListResponse { items: Message[]; total: number; page: number; page_size: number; } export interface BlockType { type: string; label: string; schema: Record; } export interface MiniApp { id: string; name: string; description: string; config_schema: Record; } // ─── Conversations ─── export const listConversations = (archived?: boolean) => apiGet('/comm/conversations', { params: archived !== undefined ? { archived } : {}, }); export const createConversation = (data: { title?: string; participant_ids?: string[]; is_direct?: boolean; initial_message?: string; }) => apiPost('/comm/conversations', data); export const getConversation = (id: string) => apiGet(`/comm/conversations/${id}`); export const updateConversation = (id: string, data: { title?: string; is_archived?: boolean }) => apiPatch(`/comm/conversations/${id}`, data); export const leaveConversation = (id: string) => apiDelete<{ success: boolean }>(`/comm/conversations/${id}`); export const pinConversation = (id: string) => apiPost<{ success: boolean }>(`/comm/conversations/${id}/pin`); export const unpinConversation = (id: string) => apiDelete<{ success: boolean }>(`/comm/conversations/${id}/pin`); export const muteConversation = (id: string) => apiPost<{ success: boolean }>(`/comm/conversations/${id}/mute`); export const unmuteConversation = (id: string) => apiDelete<{ success: boolean }>(`/comm/conversations/${id}/mute`); // ─── Participants ─── export const addParticipant = ( convId: string, data: { participant_id: string; participant_type: string; role?: string }, ) => apiPost(`/comm/conversations/${convId}/participants`, data); export const removeParticipant = (convId: string, pid: string) => apiDelete<{ success: boolean }>(`/comm/conversations/${convId}/participants/${pid}`); export const changeParticipantRole = (convId: string, pid: string, role: string) => apiPatch(`/comm/conversations/${convId}/participants/${pid}`, { role }); // ─── Messages ─── export const getMessages = (convId: string, page = 1, pageSize = 50, before?: string) => apiGet(`/comm/conversations/${convId}/messages`, { params: { page, page_size: pageSize, ...(before ? { before } : {}) }, }); export const sendMessage = ( convId: string, data: { content: string; content_format?: string; blocks?: Array<{ block_type: string; block_data: Record }>; reply_to_id?: string; attachments?: Array>; }, ) => apiPost(`/comm/conversations/${convId}/messages`, data); export const editMessage = (id: string, data: { content?: string }) => apiPatch(`/comm/messages/${id}`, data); export const deleteMessage = (id: string) => apiDelete<{ success: boolean }>(`/comm/messages/${id}`); // ─── Reactions ─── export const addReaction = (msgId: string, emoji: string) => apiPost(`/comm/messages/${msgId}/reactions`, { emoji }); export const removeReaction = (msgId: string, emoji: string) => apiDelete<{ success: boolean }>(`/comm/messages/${msgId}/reactions/${encodeURIComponent(emoji)}`); // ─── Read State ─── export const markRead = (convId: string, lastReadMsgId?: string) => apiPost<{ success: boolean }>(`/comm/conversations/${convId}/read`, { last_read_msg_id: lastReadMsgId, }); // ─── Mini-Apps ─── export const listMiniApps = () => apiGet<{ items: MiniApp[] }>('/comm/miniapps'); export const startMiniApp = (convId: string, appId: string, config?: Record) => apiPost(`/comm/conversations/${convId}/miniapps`, { app_id: appId, config: config || {}, }); // ─── Block Types ─── export const getBlockTypes = () => apiGet<{ items: BlockType[] }>('/comm/block-types');