200 lines
5.6 KiB
TypeScript
200 lines
5.6 KiB
TypeScript
|
|
/**
|
||
|
|
* 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<string, any>;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface MessageBlock {
|
||
|
|
id: string;
|
||
|
|
block_type: string;
|
||
|
|
block_data: Record<string, any>;
|
||
|
|
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<string, any>;
|
||
|
|
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<string, any>;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface MiniApp {
|
||
|
|
id: string;
|
||
|
|
name: string;
|
||
|
|
description: string;
|
||
|
|
config_schema: Record<string, any>;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ─── Conversations ───
|
||
|
|
|
||
|
|
export const listConversations = (archived?: boolean) =>
|
||
|
|
apiGet<ConversationListResponse>('/comm/conversations', {
|
||
|
|
params: archived !== undefined ? { archived } : {},
|
||
|
|
});
|
||
|
|
|
||
|
|
export const createConversation = (data: {
|
||
|
|
title?: string;
|
||
|
|
participant_ids?: string[];
|
||
|
|
is_direct?: boolean;
|
||
|
|
initial_message?: string;
|
||
|
|
}) => apiPost<Conversation>('/comm/conversations', data);
|
||
|
|
|
||
|
|
export const getConversation = (id: string) =>
|
||
|
|
apiGet<Conversation>(`/comm/conversations/${id}`);
|
||
|
|
|
||
|
|
export const updateConversation = (id: string, data: { title?: string; is_archived?: boolean }) =>
|
||
|
|
apiPatch<Conversation>(`/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<Participant>(`/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<Participant>(`/comm/conversations/${convId}/participants/${pid}`, { role });
|
||
|
|
|
||
|
|
// ─── Messages ───
|
||
|
|
|
||
|
|
export const getMessages = (convId: string, page = 1, pageSize = 50, before?: string) =>
|
||
|
|
apiGet<MessageListResponse>(`/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<string, any> }>;
|
||
|
|
reply_to_id?: string;
|
||
|
|
attachments?: Array<Record<string, any>>;
|
||
|
|
},
|
||
|
|
) => apiPost<Message>(`/comm/conversations/${convId}/messages`, data);
|
||
|
|
|
||
|
|
export const editMessage = (id: string, data: { content?: string }) =>
|
||
|
|
apiPatch<Message>(`/comm/messages/${id}`, data);
|
||
|
|
|
||
|
|
export const deleteMessage = (id: string) =>
|
||
|
|
apiDelete<{ success: boolean }>(`/comm/messages/${id}`);
|
||
|
|
|
||
|
|
// ─── Reactions ───
|
||
|
|
|
||
|
|
export const addReaction = (msgId: string, emoji: string) =>
|
||
|
|
apiPost<any>(`/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<string, any>) =>
|
||
|
|
apiPost<Message>(`/comm/conversations/${convId}/miniapps`, {
|
||
|
|
app_id: appId,
|
||
|
|
config: config || {},
|
||
|
|
});
|
||
|
|
|
||
|
|
// ─── Block Types ───
|
||
|
|
|
||
|
|
export const getBlockTypes = () =>
|
||
|
|
apiGet<{ items: BlockType[] }>('/comm/block-types');
|