import { SmrtObject, SmrtObjectOptions } from '@happyvertical/smrt-core'; import { SupportCase } from '../models/support-case.js'; import { SupportChannelBinding, SupportChannelBindingCollection } from '../models/support-channel-binding.js'; import { SupportInteraction } from '../models/support-interaction.js'; import { SupportCaseService } from './support-case-service.js'; /** Qualified source types intake understands. */ export declare const CHAT_MESSAGE_SOURCE_TYPE = "@happyvertical/smrt-chat:ChatMessage"; export declare const CHAT_ROOM_TARGET_TYPE = "@happyvertical/smrt-chat:ChatRoom"; export declare const EMAIL_SOURCE_TYPE = "@happyvertical/smrt-messages:Email"; export declare const EMAIL_ACCOUNT_TARGET_TYPE = "@happyvertical/smrt-messages:EmailAccount"; export interface InboundChatMessage { messageId: string; roomId: string; threadId?: string | null; senderProfileId: string; /** Chat role; only `user` messages are client inbound. */ role?: string; content: string; tenantId?: string | null; occurredAt?: Date; } export interface InboundEmail { emailId: string; accountId: string; fromAddress: string; fromName?: string; subject?: string; body: string; /** RFC 822 Message-ID of this email. */ rfcMessageId?: string | null; /** RFC 822 Message-ID this email replies to. */ inReplyTo?: string | null; tenantId?: string | null; occurredAt?: Date; } export interface IntakeResult { outcome: 'created' | 'joined' | 'reopened' | 'skipped'; reason?: string; supportCase?: SupportCase; interaction?: SupportInteraction; binding?: SupportChannelBinding; } export interface SupportIntakeOptions extends SmrtObjectOptions { /** * Resolve the Client profile for an inbound email sender. When omitted and * the binding has no default client, the case is parked with * `metadata.unresolvedClient = true` for operator triage. */ resolveClientProfileId?: (input: { email: string; name?: string; tenantId?: string | null; }) => Promise; /** * Called after intake creates or updates a case — the AI workflow and the * target engine attach here without a hard dependency cycle. */ onCaseIntake?: (result: IntakeResult) => Promise; } export declare class SupportIntakeService { readonly caseService: SupportCaseService; readonly bindings: SupportChannelBindingCollection; private readonly options; private readonly conversationMutex; protected constructor(caseService: SupportCaseService, bindings: SupportChannelBindingCollection, options: SupportIntakeOptions); static create(options: SupportIntakeOptions): Promise; /** Conversation key for a chat room/thread. */ static chatThreadKey(roomId: string, threadId?: string | null): string; /** Idempotency key for a chat message. */ static chatSourceKey(messageId: string): string; /** Idempotency key for an email. */ static emailSourceKey(emailId: string): string; /** * Ingest one inbound chat message from a bound room: create-or-join the * conversation's case and record the interaction. */ ingestChatMessage(input: InboundChatMessage): Promise; /** * Ingest one inbound email from a bound account: joins the RFC thread's * case when `inReplyTo` references a known interaction, else creates a new * case keyed by the message id. Mail sent FROM the binding's own addresses * is skipped (our outbound side of the conversation). */ ingestEmail(input: InboundEmail): Promise; /** The shared create-or-join core (deterministic per conversation key). */ private createOrJoin; private createOrJoinExclusive; private findResolvedByThreadKey; private findInteractionByRfcMessageId; } /** Interceptor name used for registration/unregistration. */ export declare const SUPPORT_INTAKE_INTERCEPTOR = "smrt-support:intake"; /** * Opt-in ambient intake: observe saves of `ChatMessage` and `Email` rows via * core `GlobalInterceptors` and feed them through the intake service. Only * containers with an enabled {@link SupportChannelBinding} produce cases; * everything else passes through untouched. Errors are logged, never thrown — * intake must not break the source package's save path. * * @returns An unregister function. */ export declare function registerSupportIntake(intake: SupportIntakeService, options?: { onError?: (error: unknown, instance: SmrtObject) => void; }): () => void; export default SupportIntakeService; //# sourceMappingURL=support-intake-service.d.ts.map