import type { ConnectionId, ConversationId, MessageId, ProfileId, SubjectId, UserId } from './ids.js'; import type { Channel, Conversation, Message, MessageContent, Subject } from './entities.js'; import type { ManifestAction } from './actions.js'; /** Dashboard-configured pre-chat qualification form, delivered in the manifest. */ export interface PreChatConfig { enabled: boolean; showWhen?: 'always' | 'offline'; fields?: ('name' | 'email' | 'phone')[]; topics?: string[]; callbackOption?: boolean; title?: string; } export type ErrorCode = 'UNAUTHORIZED' | 'FORBIDDEN' | 'NOT_FOUND' | 'BAD_REQUEST' | 'RATE_LIMITED' | 'PAYLOAD_TOO_LARGE' | 'CONFLICT' | 'INTERNAL'; export type ClientFrame = { type: 'auth'; token: string; } | { type: 'open'; conversationId?: ConversationId; subjectId?: SubjectId; profileId?: ProfileId; pageUrl?: string; pageTitle?: string; subjectTitle?: string; subjectMeta?: string; linkFrom?: UserId; /** Host-supplied display info for the guest — persisted onto the * conversation server-side so agents see who they're talking to. * Display metadata only, never used for authorization. */ userInfo?: { name?: string; email?: string; avatar?: string; meta?: Record; }; } | { type: 'send'; conversationId: ConversationId; clientMsgId: string; content: MessageContent; replyToId?: MessageId; via?: Channel[]; } | { type: 'sync'; conversationId: ConversationId; sinceSeq: number; } | { type: 'history'; conversationId: ConversationId; beforeSeq: number; limit?: number; } | { type: 'read'; conversationId: ConversationId; seq: number; } | { type: 'typing'; conversationId: ConversationId; isTyping: boolean; preview?: string; } | { type: 'react'; conversationId: ConversationId; messageId: MessageId; emoji: string; remove?: boolean; } | { type: 'edit'; conversationId: ConversationId; messageId: MessageId; content: MessageContent; } | { type: 'delete'; conversationId: ConversationId; messageId: MessageId; } | { type: 'invoke'; conversationId: ConversationId; actionId: string; clientInvokeId: string; inputs?: Record; } | { type: 'assign'; conversationId: ConversationId; agentId: UserId | null; } | { type: 'tag'; conversationId: ConversationId; tag: string; remove?: boolean; } | { type: 'note'; conversationId: ConversationId; clientMsgId: string; text: string; } | { type: 'agent_status'; status: 'online' | 'away' | 'offline'; } | { type: 'pubkey'; conversationId: ConversationId; key: string; } | { type: 'uploadPrekeys'; identityKey: string; signedPrekey: string; signedPrekeyId: string; signature: string; oneTimePrekeys: string[]; } | { type: 'fetchPrekey'; targetUserId: UserId; } | { type: 'subscribe_inbox'; } | { type: 'unsubscribe_inbox'; } | { type: 'ping'; }; export type ServerFrame = { type: 'authed'; userId: UserId; connectionId: ConnectionId; } | { type: 'opened'; conversation: Conversation; subject?: Subject; } | { type: 'manifest'; conversationId: ConversationId; actions: ManifestAction[]; version: number; name?: string; theme?: { accent: string; }; e2e?: boolean; offline?: boolean; offlineMessage?: string; whiteLabel?: boolean; launcherMessage?: { title: string; subtitle?: string; }; suggestedQuestions?: string[]; preChat?: PreChatConfig; } | { type: 'message'; message: Message; } | { type: 'ack'; clientMsgId: string; messageId: MessageId; seq: number; ts: number; } | { type: 'delivered'; conversationId: ConversationId; seq: number; to: UserId; } | { type: 'read'; conversationId: ConversationId; seq: number; by: UserId; } | { type: 'sync'; conversationId: ConversationId; messages: Message[]; } | { type: 'history'; conversationId: ConversationId; messages: Message[]; hasMore: boolean; } | { type: 'typing'; conversationId: ConversationId; userId: UserId; isTyping: boolean; preview?: string; } | { type: 'reaction'; conversationId: ConversationId; messageId: MessageId; emoji: string; by: UserId; removed: boolean; } | { type: 'edited'; conversationId: ConversationId; messageId: MessageId; content: MessageContent; editedAt: number; } | { type: 'deleted'; conversationId: ConversationId; messageId: MessageId; ts: number; } | { type: 'state'; conversationId: ConversationId; state: string; } | { type: 'assigned'; conversationId: ConversationId; agentId: UserId | null; } | { type: 'tagged'; conversationId: ConversationId; tag: string; removed: boolean; } | { type: 'visitor_count'; count: number; } | { type: 'agent_status_changed'; agentId: UserId; status: 'online' | 'away' | 'offline'; } | { type: 'sentiment'; conversationId: ConversationId; label: 'positive' | 'neutral' | 'frustrated'; score: number; } | { type: 'subjectState'; subjectId: SubjectId; state: string; } | { type: 'presence'; conversationId: ConversationId; userId: UserId; status: 'online' | 'offline'; lastSeen?: number; } | { type: 'invoked'; clientInvokeId: string; ok: boolean; error?: string; } | { type: 'error'; code: ErrorCode; message: string; } | { type: 'peerkey'; conversationId: ConversationId; userId: UserId; key: string; } | { type: 'prekeyBundle'; targetUserId: UserId; bundle: { identityKey: string; signedPrekey: string; signedPrekeyId: string; signature: string; oneTimePrekey?: string; } | null; } | { type: 'pong'; } | { type: 'inbox_event'; kind: 'new' | 'update'; conversationId: ConversationId; patch?: Record; }; /** Limits referenced by both ends so validation stays consistent. */ export declare const LIMITS: { readonly MAX_TEXT_LEN: 8000; readonly MAX_HISTORY_LIMIT: 100; readonly DEFAULT_HISTORY: 50; };