@helpai/elements 1.9.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -38,7 +38,7 @@ interface ClientStorage {
38
38
  * populated {@link Strings} map. UI components then read `strings.send` as a
39
39
  * normal property access — no per-render lookup, no per-render allocation.
40
40
  */
41
- type StringKey = 'launcherOpen' | 'launcherLabel' | 'panelTitle' | 'composerPlaceholder' | 'send' | 'stop' | 'queueMessage' | 'removeQueuedMessage' | 'compactingContext' | 'attach' | 'micStart' | 'micStop' | 'micUnsupported' | 'expand' | 'collapse' | 'fullscreen' | 'exitFullscreen' | 'popOut' | 'resizeHandle' | 'scrollToBottom' | 'close' | 'moreActions' | 'soundOn' | 'soundOff' | 'language' | 'theme' | 'themeAuto' | 'themeLight' | 'themeDark' | 'textSize' | 'textSizeSmall' | 'textSizeNormal' | 'textSizeLarge' | 'history' | 'historyTitle' | 'historyEmpty' | 'historyLoading' | 'historyBack' | 'historyContinue' | 'loadMoreConversations' | 'conversationLoading' | 'loadPreviousMessages' | 'conversationClosed' | 'startNewConversation' | 'talkToOperator' | 'connectingOperator' | 'noOperatorAvailable' | 'chattingWithOperator' | 'cancelOperatorRequest' | 'dateToday' | 'dateYesterday' | 'dateLastWeek' | 'dateOlder' | 'newConversation' | 'dropZone' | 'attachmentTooLarge' | 'attachmentTooMany' | 'attachmentMimeRejected' | 'errorRetry' | 'errorGeneric' | 'errorRateLimited' | 'loading' | 'visualPreparing' | 'visualError' | 'visualPartial' | 'thinking' | 'thoughts' | 'toolResult' | 'sources' | 'feedbackUp' | 'feedbackDown' | 'feedbackThanks' | 'copy' | 'copied' | 'collapseSidebar' | 'expandSidebar' | 'formSubmit' | 'formSkip' | 'formSubmitted' | 'formSkipped' | 'formFillOut' | 'formRequired' | 'formInvalidEmail' | 'formInvalidTel' | 'formInvalidUrl' | 'formInvalidNumber' | 'formTooShort' | 'formTooLong' | 'formNumberTooSmall' | 'formNumberTooLarge' | 'formPatternMismatch' | 'formChooseAtLeast' | 'formChooseAtMost' | 'formOther' | 'formOtherPlaceholder' | 'inputRequired' | 'inputBadge' | 'inputAnswered' | 'inputSkipped' | 'inputSubmit' | 'inputSubmitHint' | 'inputSkip' | 'showOptions' | 'hideOptions' | 'qtypeText' | 'qtypeEmail' | 'qtypePhone' | 'qtypeNumber' | 'qtypeDate' | 'qtypeChooseOne' | 'qtypeChooseAny' | 'qtypeBoolean' | 'confirmYes' | 'confirmNo' | 'approve' | 'reject' | 'approvalPrompt' | 'approvalBody' | 'approvalYourResponse' | 'approvalEditHint' | 'approvalSubmitting' | 'edit' | 'toolParameters' | 'statusAwaiting' | 'statusResponded' | 'statusCompleted' | 'statusDenied' | 'statusError' | 'statusRunning' | 'statusSuperseded' | 'tabHome' | 'tabConversations' | 'tabHelp' | 'tabNews' | 'modulesEmpty' | 'moduleBack' | 'contentLoading' | 'contentHelpful' | 'homeGreeting' | 'homeGreetingNamed' | 'homeGreetingLead' | 'homeSearchPlaceholder' | 'homeAskPlaceholder' | 'homeWhatsNew' | 'homeContentTitle' | 'homeStatus' | 'helpTitle' | 'helpSearchPlaceholder' | 'helpEmpty' | 'helpLoading' | 'helpSearchEmpty' | 'helpShowMore' | 'newsTitle' | 'newsEmpty' | 'newsLoading' | 'newsBack' | 'newsPublishedAt' | 'newsShowMore' | 'newsUnseen';
41
+ type StringKey = 'launcherOpen' | 'launcherLabel' | 'panelTitle' | 'composerPlaceholder' | 'send' | 'stop' | 'queueMessage' | 'removeQueuedMessage' | 'compactingContext' | 'attach' | 'micStart' | 'micStop' | 'micUnsupported' | 'expand' | 'collapse' | 'fullscreen' | 'exitFullscreen' | 'popOut' | 'resizeHandle' | 'scrollToBottom' | 'close' | 'moreActions' | 'soundOn' | 'soundOff' | 'language' | 'theme' | 'themeAuto' | 'themeLight' | 'themeDark' | 'textSize' | 'textSizeSmall' | 'textSizeNormal' | 'textSizeLarge' | 'history' | 'historyTitle' | 'historyEmpty' | 'historyLoading' | 'historyBack' | 'historyContinue' | 'loadMoreConversations' | 'conversationLoading' | 'loadPreviousMessages' | 'conversationClosed' | 'startNewConversation' | 'talkToOperator' | 'connectingOperator' | 'noOperatorAvailable' | 'chattingWithOperator' | 'cancelOperatorRequest' | 'dateToday' | 'dateYesterday' | 'dateLastWeek' | 'dateOlder' | 'newConversation' | 'dropZone' | 'attachmentTooLarge' | 'attachmentTooMany' | 'attachmentMimeRejected' | 'errorRetry' | 'errorGeneric' | 'errorRateLimited' | 'loading' | 'visualPreparing' | 'visualError' | 'visualPartial' | 'thinking' | 'thoughts' | 'toolResult' | 'sources' | 'feedbackUp' | 'feedbackDown' | 'feedbackThanks' | 'copy' | 'copied' | 'collapseSidebar' | 'expandSidebar' | 'formSubmit' | 'formSkip' | 'formSubmitted' | 'formSkipped' | 'formFillOut' | 'formRequired' | 'formInvalidEmail' | 'formInvalidTel' | 'formInvalidUrl' | 'formInvalidNumber' | 'formTooShort' | 'formTooLong' | 'formNumberTooSmall' | 'formNumberTooLarge' | 'formPatternMismatch' | 'formChooseAtLeast' | 'formChooseAtMost' | 'formOther' | 'formOtherPlaceholder' | 'inputRequired' | 'inputBadge' | 'inputAnswered' | 'inputSkipped' | 'inputSubmit' | 'inputSubmitHint' | 'inputSkip' | 'showOptions' | 'hideOptions' | 'qtypeText' | 'qtypeEmail' | 'qtypePhone' | 'qtypeNumber' | 'qtypeDate' | 'qtypeChooseOne' | 'qtypeChooseAny' | 'qtypeBoolean' | 'confirmYes' | 'confirmNo' | 'approve' | 'reject' | 'approvalPrompt' | 'approvalBody' | 'approvalYourResponse' | 'approvalEditHint' | 'approvalSubmitting' | 'edit' | 'toolParameters' | 'statusAwaiting' | 'statusResponded' | 'statusCompleted' | 'statusDenied' | 'statusError' | 'statusRunning' | 'statusSuperseded' | 'statusIncomplete' | 'tabHome' | 'tabConversations' | 'tabHelp' | 'tabNews' | 'modulesEmpty' | 'moduleBack' | 'contentLoading' | 'contentHelpful' | 'homeGreeting' | 'homeGreetingNamed' | 'homeGreetingLead' | 'homeSearchPlaceholder' | 'homeAskPlaceholder' | 'homeWhatsNew' | 'homeContentTitle' | 'homeStatus' | 'helpTitle' | 'helpSearchPlaceholder' | 'helpEmpty' | 'helpLoading' | 'helpSearchEmpty' | 'helpShowMore' | 'newsTitle' | 'newsEmpty' | 'newsLoading' | 'newsBack' | 'newsPublishedAt' | 'newsShowMore' | 'newsUnseen';
42
42
  /** A partial map for one locale — what overrides look like on the wire. */
43
43
  type LocaleStrings = Partial<Record<StringKey, string>>;
44
44
  /**
@@ -898,6 +898,38 @@ interface ResolvedTracking {
898
898
  * alongside at the top level — they're function / DOM types that can't be
899
899
  * serialised on the wire.
900
900
  */
901
+ /** A signed user token, or a function that returns a fresh one (see {@link ChatWidgetOptions.userToken}). */
902
+ type UserTokenSource = string | (() => string | Promise<string>);
903
+ /** WebMCP `ToolAnnotations`: hints about what a tool does. */
904
+ interface ToolAnnotations {
905
+ /** It only reads; it changes nothing. */
906
+ readOnlyHint?: boolean;
907
+ /** Its result holds content the site doesn't vouch for, such as reviews. */
908
+ untrustedContentHint?: boolean;
909
+ /** A significant or irreversible action (booking, paying, deleting): the visitor approves each call first. */
910
+ consequentialHint?: boolean;
911
+ /** Built for developers, not visitors. */
912
+ debugging?: boolean;
913
+ }
914
+ /**
915
+ * A tool the AI agent can use on your page, in the WebMCP `ModelContextTool` shape: the same object works with
916
+ * `document.modelContext.registerTool()`. The agent sees `name`, `description` and `inputSchema`; `execute` runs here,
917
+ * in the visitor's browser, and what it returns goes back to the agent.
918
+ */
919
+ interface ModelContextTool<TInput = unknown> {
920
+ /** Letters, digits, `_` and `-` (58 at most; others become `_`). A name registered again replaces the earlier tool. */
921
+ name: string;
922
+ title?: string;
923
+ /** When the agent should use it and what it does (1024 characters at most). */
924
+ description: string;
925
+ /** JSON Schema of the input (`type: "object"`); none means the tool takes no input. */
926
+ inputSchema?: Record<string, unknown>;
927
+ annotations?: ToolAnnotations;
928
+ /** Runs the tool: return a JSON value (or a promise of one) for the agent; throw to report a failure. `signal` aborts when the visitor moves on first. */
929
+ execute(input: TInput, options: {
930
+ signal: AbortSignal;
931
+ }): unknown;
932
+ }
901
933
  interface ChatWidgetOptions {
902
934
  /**
903
935
  * Stable identifier for this widget instance. Use when mounting more
@@ -973,6 +1005,20 @@ interface ChatWidgetOptions {
973
1005
  * interface (`get` / `set` / `remove` / `clear`).
974
1006
  */
975
1007
  storage?: ClientStorage;
1008
+ /**
1009
+ * Proves who the logged-in visitor is: a JWT your server signs (HS256) with the deployment's secret key, carrying
1010
+ * `sub` (your user id) and `exp`, optionally `name` and `email`. A function is called when a token is first
1011
+ * needed and again when the server rejects the current one as expired, so return a fresh token from it. Their
1012
+ * conversations then follow them to any device; `chat.login(token)` sets it after sign-in, `chat.reset()` on
1013
+ * sign-out. Sent only to the agent API, as `x-user-token`.
1014
+ */
1015
+ userToken?: UserTokenSource;
1016
+ /**
1017
+ * Tools the AI agent can use on your page (open a booking form, read the cart, jump to a section), WebMCP
1018
+ * `ModelContextTool`s. Sent with each message as definitions only; the agent's call runs `execute` here, in the
1019
+ * visitor's browser. `registerTool()` adds one from anywhere, for example a single-page app's route.
1020
+ */
1021
+ tools?: readonly ModelContextTool[];
976
1022
  onMessage?: (msg: {
977
1023
  role: string;
978
1024
  text: string;
@@ -1083,12 +1129,16 @@ interface ResolvedOptions {
1083
1129
  tracking: ResolvedTracking;
1084
1130
  /** Resolved storage adapter — defaults to `LocalStorageAdapter`. */
1085
1131
  storage: ClientStorage;
1132
+ userToken?: UserTokenSource;
1133
+ tools?: readonly ModelContextTool[];
1086
1134
  onMessage?: ChatWidgetOptions['onMessage'];
1087
1135
  onOpen?: ChatWidgetOptions['onOpen'];
1088
1136
  onClose?: ChatWidgetOptions['onClose'];
1089
1137
  onError?: ChatWidgetOptions['onError'];
1090
1138
  }
1091
1139
  type HostMode = 'page' | 'standalone' | 'inline' | 'modal' | 'drawer' | 'fullscreen' | 'expanded' | 'open' | 'closed';
1140
+ /** How a call this page ran (or found cut short) ended, for the `toolResult` event. */
1141
+ type PageToolCallStatus = 'completed' | 'failed' | 'interrupted';
1092
1142
  /** A single image asset (logo, hero, icon). */
1093
1143
  declare const assetSchema: z.ZodObject<{
1094
1144
  url: z.ZodString;
@@ -3134,15 +3184,27 @@ interface EventMap {
3134
3184
  values: Record<string, string>;
3135
3185
  skipped: boolean;
3136
3186
  };
3137
- /** User answered an ask-questions tool request (re-POST follows). */
3187
+ /**
3188
+ * A tool call settled on the page: the visitor answered an ask-questions request (`toolCallId` only), or a page
3189
+ * tool's call ended — `completed`, `failed`, `declined` or `stopped` by the visitor, or `interrupted` by a reload —
3190
+ * after `durationMs`. Never its input or result.
3191
+ */
3138
3192
  toolResult: {
3139
3193
  toolCallId: string;
3194
+ name?: string;
3195
+ status?: PageToolCallStatus | 'declined' | 'stopped';
3196
+ durationMs?: number;
3140
3197
  };
3141
3198
  /** User approved / rejected a gated tool call (re-POST follows). */
3142
3199
  toolDecision: {
3143
3200
  toolCallId: string;
3144
3201
  approved: boolean;
3145
3202
  };
3203
+ /** Your page reported its own event with `track(name, data)`: sent to analytics, and to the agent with the next message. */
3204
+ hostEvent: {
3205
+ name: string;
3206
+ data?: Record<string, string | number | boolean>;
3207
+ };
3146
3208
  /**
3147
3209
  * User gave feedback on a rateable reply (AI or operator). `value` is `"up"` / `"down"`, or
3148
3210
  * `null` when they cleared a prior choice. `messageId` is the backend message
@@ -3289,6 +3351,8 @@ interface AskOptions {
3289
3351
  /** Send the text as the visitor's message instead of filling the composer with it. Default `false`. */
3290
3352
  send?: boolean;
3291
3353
  }
3354
+ /** Flat data about a host event: strings, numbers and booleans only. */
3355
+ type HostEventData = Record<string, string | number | boolean>;
3292
3356
  /**
3293
3357
  * Comprehensive logger for the widget runtime.
3294
3358
  *
@@ -3383,6 +3447,47 @@ export interface ChatWidgetInstance {
3383
3447
  * Listeners added with `on()` stay.
3384
3448
  */
3385
3449
  reset: () => void;
3450
+ /**
3451
+ * Sign the visitor in as your logged-in user, after they log in to your site: `userToken` is a JWT your server
3452
+ * signs with the deployment's secret key (`sub`, `exp`; optional `name`, `email`), or a function that returns a
3453
+ * fresh one. The widget reconnects as that user: their earlier chats on this browser move to them, and their
3454
+ * conversations follow them to any device. Call `reset()` when they log out.
3455
+ *
3456
+ * @example
3457
+ * ```ts
3458
+ * chat.login(async () => (await fetch('/api/help-ai-token')).text());
3459
+ * ```
3460
+ */
3461
+ login: (userToken: UserTokenSource) => void;
3462
+ /**
3463
+ * Report something the visitor did on your site, outside the chat. Sends a `hostEvent` hit to analytics (not when
3464
+ * tracking is off), and the agent reads your last 10 events with the visitor's next message. `name` is 1–64
3465
+ * characters; `data` is flat (strings, numbers, booleans), 256 characters of JSON at most.
3466
+ *
3467
+ * @example
3468
+ * ```ts
3469
+ * chat.track('plan_viewed', { plan: 'pro' });
3470
+ * ```
3471
+ */
3472
+ track: (name: string, data?: HostEventData) => void;
3473
+ /**
3474
+ * Add a tool the agent can use on this page, in the WebMCP tool shape — for every widget on the page, not only this
3475
+ * one. The latest registration of a name wins; aborting `options.signal` removes it. `annotations.consequentialHint`
3476
+ * asks the visitor before each call. See `docs/sdk/page-tools.md`.
3477
+ *
3478
+ * @example
3479
+ * ```ts
3480
+ * chat.registerTool({
3481
+ * name: 'open_booking',
3482
+ * description: 'Open the booking form for a meeting type.',
3483
+ * inputSchema: { type: 'object', properties: { meetingType: { type: 'string', enum: ['sales', 'support'] } }, required: ['meetingType'] },
3484
+ * execute: ({ meetingType }) => booking.open(meetingType),
3485
+ * });
3486
+ * ```
3487
+ */
3488
+ registerTool: (tool: ModelContextTool, options?: {
3489
+ signal?: AbortSignal;
3490
+ }) => void;
3386
3491
  /**
3387
3492
  * Subscribe to a lifecycle event. Returns an `off` function. See
3388
3493
  * {@link EventMap} for the full set + payload shapes — currently
@@ -3526,4 +3631,4 @@ export declare const brand: {
3526
3631
  readonly domain: string;
3527
3632
  readonly siteUrl: string;
3528
3633
  };
3529
- export type { AskOptions, Asset, BlocksConfig, ChatWidgetOptions, ConnectionConfig, ConnectionConfigPartial, EventMap, EventName, HandshakeResponse, HookListener, Link, LogEntry, LogLevel, OpenTarget, ResolvedOptions, ServerConfig, SiteConfig, WidgetConfig, WidgetConfigPartial, WidgetSettings, WidgetSettingsPartial, WidgetState };
3634
+ export type { AskOptions, Asset, BlocksConfig, ChatWidgetOptions, ConnectionConfig, ConnectionConfigPartial, EventMap, EventName, HandshakeResponse, HookListener, HostEventData, Link, LogEntry, LogLevel, ModelContextTool, OpenTarget, ResolvedOptions, ServerConfig, SiteConfig, ToolAnnotations, UserTokenSource, WidgetConfig, WidgetConfigPartial, WidgetSettings, WidgetSettingsPartial, WidgetState };