UNPKG

@xapp/chat-widget

Version:
214 lines (213 loc) 7.52 kB
import 'rollup-plugin-inject-process-env'; import { ActionType } from "../store/ChatAction"; import { ChatServer, ChatServerOptions, OfflineMessage, VisitorInfoMessage } from "./ChatServer"; import { ChatMessageRequest, ChatServerMessage } from "./ChatServerMessage"; /** * Page context to provide information about the user's current page. * Enables more relevant AI responses based on context. */ interface PageContext { url?: string; path?: string; title?: string; referrer?: string; localTime?: string; } /** * Returns the current local time as an ISO 8601 string with the local timezone offset. * Unlike toISOString(), this preserves the user's local time zone (e.g. "2024-01-15T14:30:00-04:00") * so the agent server can correctly determine time-of-day context (morning greetings, etc.). */ export declare function getLocalISOString(date?: Date): string; export interface MCPChatConfig { /** * Server URL for MCP connections. * * For homeowner mode: Include the appId in the URL * e.g., "https://agent.xapp.ai/abc123" * * For business_owner mode: Just the base URL * e.g., "https://agent.xapp.ai" */ readonly serverUrl: string; /** * Mode determines endpoint path and authentication requirements. * - homeowner: appends /chat/stream to serverUrl (unauthenticated) * - business_owner: appends /api/chat/stream to serverUrl (requires authToken) * * @default "homeowner" */ readonly mode?: "homeowner" | "business_owner"; /** * Optional session ID for conversation continuity */ readonly sessionId?: string; /** * Auth token required for business_owner mode. * Will throw an error if mode is "business_owner" and authToken is not provided. */ readonly authToken?: string; /** * Enable debug mode to show tool calls in the chat */ readonly debugMode?: boolean; /** * Override the automatically detected page context. * Useful for testing in Storybook or simulating different pages. */ readonly pageContextOverride?: PageContext; /** * Show an "AI" badge on the avatar for AI-generated messages. */ readonly showAiBadge?: boolean; /** * Disable device fingerprinting for privacy-conscious deployments. * When true, no fingerprint data is sent to the server. * Note: This may reduce the server's ability to identify returning users. */ readonly disableFingerprinting?: boolean; } export declare class MCPChat implements ChatServer { private visitorInfo; private _userId; private _sessionId; private _accessToken; private _debugMode; private _attributes; private dispatch; private isNewSession; private readonly configurableMessages; private readonly config; private readonly options; private readonly hooks?; private abortController?; private currentMessageId?; private streamBuffer; private streamThrottleTimer?; private streamingMessageIdForThrottle?; private visibilityHandler?; private isInitializingSession; private sessionInitPromise?; private resolveSessionInit?; private isValidatingSession; private currentToolCalls; private lastSeq; private isReplaying; private isSleeping; private isRequestingReplay; private needsReplayOnWakeup; private userIdIsServerAssigned; private sessionStartTime; private sentMessageCount; constructor(config: MCPChatConfig, options?: ChatServerOptions); init(dispatch: (action: ActionType) => void): void; /** * Validates an existing session with the server ("Silent Handshake"). * Called when widget reopens with a stored sessionId. * * The server will respond with: * - "connected" event if session is valid * - "session_expired" event if session is gone (triggers initializeNewSession) * * This is lightweight - no LLM call, just a quick DB check to: * - Validate session before user tries to send a message * - Update lastActivityAt in persistent session * - Confirm userId is still valid */ private validateSession; /** * Builds the common request payload with identity and context. */ private buildRequestPayload; /** * Initializes a new session by calling the endpoint with { newSession: true }. * This returns a greeting message and session ID without making an LLM call. */ private initializeNewSession; private setConnectionStatus; private setAccountStatus; private getEndpoint; private getCloseEndpoint; private sendNewMessage; private userJoined; private typing; private stopTyping; private sendFailureMessage; /** * Gets the retry configuration, using custom config if provided or defaults. */ private getRetryConfig; /** * Delays execution for the specified number of seconds. */ private delay; /** * Determines a user-friendly error message based on the error type. */ private getErrorMessage; private dispatchStreamStart; private dispatchStreamChunk; private dispatchStreamEnd; private dispatchStreamAbort; private dispatchStreamResume; private dispatchToolStart; private dispatchToolEnd; /** * Starts the throttled streaming for a message. * Text will be dispatched at a readable pace. */ private startStreamThrottle; /** * Adds text to the stream buffer for throttled dispatch. */ private bufferStreamText; /** * Flushes any remaining buffered text and stops the throttle timer. * Returns a promise that resolves when all buffered text has been dispatched. */ private flushStreamBuffer; /** * Immediately stops throttling and clears the buffer (used on abort/error). */ private stopStreamThrottle; sendOfflineMsg(_: OfflineMessage, cb: (error?: Error) => void): void; sendChatMsg(message: ChatServerMessage, cb: (err?: Error) => void): Promise<void>; bargeOut(_: (err?: Error) => void): Promise<void>; bargeIn(_agentName: string, __: (err?: Error) => void): Promise<void>; /** * Ensures a nick has the "agent:" prefix required for agent message detection. */ private ensureAgentNick; private getBot; sendChatMsgRequest(serviceRequest: ChatMessageRequest, cb: (err?: Error) => void): Promise<void>; private postMessage; /** * Attempts a single SSE request. Throws on failure. */ private attemptSSERequest; /** * Performs an SSE request with the given body. * Used for both new session initialization and regular messages. */ private performSSERequest; sendTyping(): void; setVisitorInfo(visitorInfo: VisitorInfoMessage, sessionId: string, cb: (error?: Error) => void): void; sendChatRating(): void; sendFile(_: File, cb: (err?: Error) => void): void; markAsRead(): void; flush(): void; dispose(): void; sleep(): void; wakeup(): void; private requestReplay; /** * Sends a best-effort close notification to the agent server. * Uses navigator.sendBeacon() so the request survives page unload. * Called from the beforeunload event handler and the widget close button. */ notifyDisconnecting(reason?: "close_tab" | "widget_close"): void; private startSession; get userId(): string; get sessionId(): string; } export {};