Skip to main content
The core package provides the framework-agnostic widget engine. It exports all the TypeScript types used across widget implementations.

Installation

npm install @opencx/widget-core

Configuration Types

WidgetConfig

The main configuration object for initializing the widget.
interface WidgetConfig {
  token: string;
  language?: Language;
  bot?: { name?: string; avatarUrl?: string };
  isOpen?: boolean;
  openAfterNSeconds?: number;
  theme?: ThemeOptions;
  initialMessages?: string[];
  initialQuestions?: string[];
  collectUserData?: boolean;
  user?: UserConfig;
  headerButtons?: { sessionsScreen?: HeaderButtonU[]; chatScreen?: HeaderButtonU[] };
  modesComponents?: ModeComponent[];
  customComponents?: { onSessionResolved?: CustomComponent; headerTitle?: CustomComponent };
  router?: { goToChatIfNoSessions?: boolean; chatScreenOnly?: boolean };
  oneOpenSessionAllowed?: boolean;
  headers?: Record<string, string>;
  queryParams?: Record<string, string>;
  context?: Record<string, unknown>;
  inline?: boolean;
}
PropertyTypeDescription
tokenstringYour organization’s widget token
languageLanguageWidget language (default: 'en')
bot{ name?, avatarUrl? }Bot display name and avatar
isOpenbooleanControl open state externally
themeThemeOptionsVisual customization
initialMessagesstring[]Messages shown before first user message
initialQuestionsstring[]Clickable suggested questions
collectUserDatabooleanShow welcome screen to collect name/email
userUserConfigVerified or non-verified contact data
routerobjectRouting behavior customization
oneOpenSessionAllowedbooleanLimit to one open session
headersRecord<string, string>Headers for AI action HTTP requests
contextRecord<string, unknown>Dynamic context sent with messages
inlinebooleanEmbed widget inline (always open, no trigger)

ExternalStorage

Custom storage implementation for persisting contact tokens.
interface ExternalStorage {
  get(key: string): Promise<string | null>;
  set(key: string, value: string): Promise<void>;
  remove(key: string): Promise<void>;
}
Useful for React Native or custom persistence layers instead of localStorage.

WidgetComponentType

Type for custom component overrides passed to the provider.
type WidgetComponentType = {
  key: WidgetComponentKey;
  component: (props: ComponentContext) => React.ReactNode;
};

type WidgetComponentKey =
  | 'bot_message'
  | 'agent_message'
  | 'loading'
  | 'fallback'
  | string;

ModeComponent

Custom component for conversation modes.
type ModeComponent = {
  key: string;
  component: (props: ModeComponentProps) => React.ReactNode;
};

type ModeComponentProps = ComponentContext & {
  mode: ModeDto;
  createStateCheckpoint: (payload: unknown) => Promise<{ success: boolean }>;
  sendMessage: (input: { content: string }) => Promise<void>;
  isSendingMessage: boolean;
};

ComponentContext

Context passed to all custom components.
type ComponentContext = {
  react: typeof React;
  org: { id: string; name: string };
  config: WidgetConfig;
  session: SessionDto | null;
  messages: WidgetMessageU[];
  currentScreen: ScreenU;
};

Contexts

The core package exports context classes that manage widget state. Access these via WidgetCtx after initialization.
import { WidgetCtx } from '@opencx/widget-core';

const widgetCtx = await WidgetCtx.initialize({ config });

// Access sub-contexts
widgetCtx.sessionCtx;
widgetCtx.messageCtx;
widgetCtx.contactCtx;
widgetCtx.routerCtx;
widgetCtx.csatCtx;

WidgetCtx

The root context that orchestrates all sub-contexts.
class WidgetCtx {
  static initialize(opts: { config: WidgetConfig; storage?: ExternalStorage }): Promise<WidgetCtx>;

  sessionCtx: SessionCtx;
  messageCtx: MessageCtx;
  contactCtx: ContactCtx;
  routerCtx: RouterCtx;
  csatCtx: CsatCtx;
  api: ApiCaller;
  modes: ModeDto[];

  resetChat(): void;
}

SessionCtx

Manages chat sessions.
class SessionCtx {
  sessionState: PrimitiveState<SessionState>;
  sessionsState: PrimitiveState<SessionsState>;

  createSession(): Promise<SessionDto | null>;
  loadMoreSessions(): Promise<void>;
  resolveSession(): Promise<{ success: boolean }>;
  createStateCheckpoint(payload: unknown): Promise<{ success: boolean }>;
}
SessionState
PropertyTypeDescription
sessionSessionDto | nullCurrently selected session
isCreatingSessionbooleanSession creation in progress
isResolvingSessionbooleanSession resolution in progress
SessionsState
PropertyTypeDescription
dataSessionDto[]All user sessions
cursorstring | undefinedPagination cursor
isLastPagebooleanNo more pages
isInitialFetchLoadingbooleanInitial fetch in progress

MessageCtx

Manages chat messages.
class MessageCtx {
  state: PrimitiveState<MessageCtxState>;

  sendMessage(input: {
    content: string;
    attachments?: MessageAttachmentType[];
    customData?: Record<string, unknown>;
  }): Promise<void>;

  reset(): void;
}
MessageCtxState
PropertyTypeDescription
messagesWidgetMessageU[]All messages
isSendingMessagebooleanMessage send in progress
isSendingMessageToAIbooleanWaiting for AI response
lastAIResMightSolveUserIssuebooleanAI thinks issue may be resolved
isInitialFetchLoadingbooleanInitial fetch in progress

ContactCtx

Manages contact/user state.
class ContactCtx {
  state: PrimitiveState<ContactState>;

  shouldCollectData(): boolean;
  createUnverifiedContact(payload: CreateUnverifiedContactDto): Promise<void>;
  setUnverifiedContact(token: string): Promise<void>;
}
ContactState
PropertyTypeDescription
contact{ token: string; externalId?: string } | nullCurrent contact
extraCollectedDataRecord<string, string>Extra collected fields
isCreatingUnverifiedContactbooleanContact creation in progress

RouterCtx

Manages screen navigation.
class RouterCtx {
  state: PrimitiveState<{ screen: ScreenU }>;

  toSessionsScreen(): void;
  toChatScreen(sessionId?: string): void;
}

type ScreenU = 'welcome' | 'sessions' | 'chat';
ScreenDescription
welcomeCollect user data before starting
sessionsList of previous sessions
chatActive chat screen

CsatCtx

Manages CSAT submissions.
class CsatCtx {
  submitCsat(body: { score: number; feedback?: string }): Promise<{ data: unknown; error?: string }>;
}

PrimitiveState

A simple reactive state container used by all contexts.
class PrimitiveState<T> {
  get(): T;
  set(value: T): void;
  setPartial(partial: Partial<T>): void;
  reset(): void;
  subscribe(callback: (value: T) => void): () => void;
}

Message Types

Messages are typed as a union. Use the type field to discriminate between message kinds.
type WidgetMessageU =
  | WidgetUserMessage
  | WidgetAiMessage
  | WidgetAgentMessage
  | WidgetSystemMessageU;

WidgetUserMessage

Messages sent by the end user.
interface WidgetUserMessage {
  id: string;
  type: 'USER';
  content: string;
  deliveredAt: string | null;
  attachments?: MessageAttachmentType[] | null;
  timestamp: string | null;
  user?: {
    name?: string;
    email?: string;
    phone?: string;
    customData?: Record<string, unknown>;
    avatarUrl?: string;
  };
}
FieldTypeDescription
idstringUnique message identifier
type'USER'Discriminator literal
contentstringMessage text content
deliveredAtstring | nullDelivery timestamp
attachmentsMessageAttachmentType[]File attachments
timestampstring | nullMessage timestamp
userobjectUser metadata

WidgetAiMessage

Messages from the AI assistant.
interface WidgetAiMessage<TActionData = unknown> {
  id: string;
  type: 'AI';
  component: string;
  data: {
    message: string;
    variant?: 'default' | 'error';
    action?: { name: string; data: TActionData } | null;
  };
  timestamp: string | null;
  agent?: Agent;
  attachments?: MessageAttachmentType[];
}
FieldTypeDescription
idstringUnique message identifier
type'AI'Discriminator literal
componentstringComponent key ('bot_message' or custom)
data.messagestringMessage text content
data.variant'default' | 'error'Display variant
data.actionobject | nullAction call result
agentAgentAgent metadata
attachmentsMessageAttachmentType[]File attachments

WidgetAgentMessage

Messages from human agents.
interface WidgetAgentMessage {
  id: string;
  type: 'AGENT';
  component: 'agent_message';
  data: {
    message: string;
    variant?: 'default' | 'error';
  };
  timestamp: string | null;
  agent?: Agent;
  attachments?: MessageAttachmentType[];
}
FieldTypeDescription
idstringUnique message identifier
type'AGENT'Discriminator literal
component'agent_message'Component key
data.messagestringMessage text content
agentAgentAgent metadata (name, avatar)
attachmentsMessageAttachmentType[]File attachments

System Messages

System messages represent events like CSAT prompts and state checkpoints.
type WidgetSystemMessageU =
  | WidgetSystemMessage__CsatRequested
  | WidgetSystemMessage__CsatSubmitted
  | WidgetSystemMessage__StateCheckpoint;

WidgetSystemMessage__CsatRequested

Triggered when a CSAT prompt should be displayed.
interface WidgetSystemMessage__CsatRequested {
  id: string;
  type: 'SYSTEM';
  subtype: 'csat_requested';
  timestamp: string | null;
  data: { payload?: undefined };
}

WidgetSystemMessage__CsatSubmitted

Contains the submitted CSAT rating.
interface WidgetSystemMessage__CsatSubmitted {
  id: string;
  type: 'SYSTEM';
  subtype: 'csat_submitted';
  timestamp: string | null;
  data: {
    payload: {
      score: number | null | undefined;
      feedback: string | null | undefined;
    };
  };
}
FieldTypeDescription
data.payload.scorenumber | nullRating score (typically 1-5)
data.payload.feedbackstring | nullOptional text feedback

WidgetSystemMessage__StateCheckpoint

Used for resuming sessions with preserved state.
interface WidgetSystemMessage__StateCheckpoint {
  id: string;
  type: 'SYSTEM';
  subtype: 'state_checkpoint';
  timestamp: string | null;
  data: { payload: unknown };
}

Agent Type

interface Agent {
  name?: string;
  avatarUrl?: string;
}

Attachment Types

interface MessageAttachmentType {
  type: 'image' | 'file';
  url: string;
  name?: string;
  size?: number;
  mimeType?: string;
}

Additional Resources