@bitpalm/ai-agents 0.6.0 → 0.8.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/README.md CHANGED
@@ -70,6 +70,18 @@ widget.on("trigger_hidden", () => (dot.hidden = true));
70
70
 
71
71
  `triggers: false` switches proactive messages off, `widget.disableTriggers()` and `enableTriggers()` do it at runtime. The widget's elements carry `data-bitpalm-launcher`, `data-bitpalm-trigger` and `data-bitpalm-chat`. In React, `<BitPalmAgent onReady={(widget) => …} />` hands you the instance.
72
72
 
73
+ ## Your own chat UI
74
+
75
+ Design the chat yourself and let BitPalm answer behind it, in a website or an app (Capacitor, Ionic, React Native). Needs an app key (`bp_pk_…`) from the dashboard and the Pro plan.
76
+
77
+ ```tsx
78
+ import { useBitPalmChat } from "@bitpalm/ai-agents/react";
79
+
80
+ const { messages, send, status, agent } = useBitPalmChat({ key: "bp_pk_…" });
81
+ ```
82
+
83
+ Without React: `createChatClient` from `@bitpalm/ai-agents/headless`.
84
+
73
85
  ## Full documentation
74
86
 
75
87
  📚 **[agents.bitpalm.ai/docs](https://agents.bitpalm.ai/docs)**
@@ -83,6 +95,7 @@ widget.on("trigger_hidden", () => (dot.hidden = true));
83
95
  - [Custom Context (cart, listings, account data)](https://agents.bitpalm.ai/docs/context)
84
96
  - [Events (lead capture, conversation start)](https://agents.bitpalm.ai/docs/events)
85
97
  - [Own chat button (apps, PWAs)](https://agents.bitpalm.ai/docs/own-chat-button)
98
+ - [Own chat UI (headless)](https://agents.bitpalm.ai/docs/headless)
86
99
  - [API Reference](https://agents.bitpalm.ai/docs/api-reference)
87
100
  - [Common Errors](https://agents.bitpalm.ai/docs/common-errors)
88
101
 
@@ -0,0 +1,13 @@
1
+ "use strict";var C=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var T=Object.getOwnPropertyNames;var A=Object.prototype.hasOwnProperty;var j=(n,a)=>{for(var r in a)C(n,r,{get:a[r],enumerable:!0})},D=(n,a,r,o)=>{if(a&&typeof a=="object"||typeof a=="function")for(let l of T(a))!A.call(n,l)&&l!==r&&C(n,l,{get:()=>a[l],enumerable:!(o=R(a,l))||o.enumerable});return n};var O=n=>D(C({},"__esModule",{value:!0}),n);var J={};j(J,{BitPalmApiError:()=>p,createChatClient:()=>N});module.exports=O(J);function _(n){let a=n.split(`
2
+ `).filter(r=>r.startsWith("data:")).map(r=>r.slice(5).trimStart()).join(`
3
+ `);if(!a)return null;try{let r=JSON.parse(a);return r&&typeof r.type=="string"?r:null}catch{return null}}function h(n){let a=[],r=n.replace(/\r\n/g,`
4
+ `),o=r.indexOf(`
5
+
6
+ `);for(;o>=0;){let l=_(r.slice(0,o));l&&a.push(l),r=r.slice(o+2),o=r.indexOf(`
7
+
8
+ `)}return{events:a,rest:r}}function k(n){return h(`${n}
9
+
10
+ `).events}var p=class extends Error{constructor(r,o,l){super(o);this.code=r;this.status=l;this.name="BitPalmApiError"}},L="https://agents.bitpalm.ai";function M(){try{return typeof localStorage>"u"?null:localStorage}catch{return null}}function B(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`v-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,12)}`}async function q(n){let a=await n.json().catch(()=>null);return new p(a?.error?.code??"server_error",a?.error?.message??`Request failed (${n.status})`,n.status)}function N(n){if(!n?.key?.startsWith("bp_pk_"))throw new Error("createChatClient needs an app key (bp_pk_\u2026) from the BitPalm dashboard.");let a=(n.baseUrl??L).replace(/\/+$/,""),r=n.storage===void 0?M():n.storage,o=`bitpalm:${n.key.slice(0,14)}`,l=t=>{try{return r?.getItem(`${o}:${t}`)??null}catch{return null}},x=(t,e)=>{try{e===null?r?.removeItem(`${o}:${t}`):r?.setItem(`${o}:${t}`,e)}catch{}},c=n.visitorId??l("visitor")??B();n.visitorId||x("visitor",c);let d=l("conversation"),f=!1,g=null,I=t=>{for(let e of t)e.fromHuman&&e.createdAt&&(!g||e.createdAt>g)&&(g=e.createdAt)},P={Authorization:`Bearer ${n.key}`},u=async(t,e)=>{let i=await fetch(`${a}${t}`,{...e,headers:{...P,...e?.headers??{}}});if(!i.ok)throw await q(i);return i},y=t=>{d=t,x("conversation",t)},v=(t,e,i)=>{for(let s of t)if(s.type==="delta")e.text+=s.text,i?.(s.text,e.text);else if(s.type==="replace")e.text=s.text,i?.("",e.text);else if(s.type==="done")e.result={text:e.text,conversationId:s.conversationId,...s.cards?{cards:s.cards}:{},...s.handoff?{handoff:!0}:{}};else if(s.type==="error")throw new p("server_error",s.message,500)};return{visitorId:c,get conversationId(){return d},get handoff(){return f},async agent(t){let e=new URLSearchParams({locale:n.locale??"en"});return t?.url&&e.set("url",t.url),(await u(`/api/v1/agent?${e.toString()}`)).json()},async send(t,e={}){let i=await u("/api/v1/chat",{method:"POST",headers:{"Content-Type":"application/json"},signal:e.signal,body:JSON.stringify({message:t,visitorId:c,conversationId:d??void 0,context:e.context,fileIds:e.fileIds})}),s={text:"",result:null},S=i.body&&typeof i.body.getReader=="function"?i.body.getReader():null;if(S){let $=new TextDecoder,b="";for(;;){let{done:E,value:U}=await S.read();if(E)break;let w=h(b+$.decode(U,{stream:!0}));b=w.rest,v(w.events,s,e.onDelta)}v(h(`${b}
11
+
12
+ `).events,s,e.onDelta)}else v(k(await i.text()),s,e.onDelta);let m=s.result??{text:s.text,conversationId:d??""};return m.conversationId&&y(m.conversationId),f=m.handoff===!0,m},async history(){let t=new URLSearchParams({visitorId:c});d&&t.set("conversationId",d);let e=await(await u(`/api/v1/chat/history?${t.toString()}`)).json();return e.conversationId&&y(e.conversationId),f=e.handoff===!0,g=null,I(e.messages),e.messages},async updates(){if(!d)return{handoff:!1,teamTyping:!1,messages:[]};let t=new URLSearchParams({visitorId:c,conversationId:d});g&&t.set("after",g);let e=await(await u(`/api/v1/chat/updates?${t.toString()}`)).json(),i=e.messages??[];return I(i),f=e.handoff===!0,{handoff:f,teamTyping:e.teamTyping===!0,messages:i}},async identify(t){await u("/api/v1/identify",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({...t,visitorId:c})})},async upload(t,e="photo.jpg"){let i=new FormData;i.append("file",t,e),i.append("visitorId",c),d&&i.append("conversationId",d);let s=await(await u("/api/v1/chat/upload",{method:"POST",body:i})).json();return{id:s.id,url:s.url}},async feedback(t,e){if(!d)throw new p("bad_request","There is no conversation yet.",400);await u("/api/v1/chat/feedback",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({visitorId:c,conversationId:d,messageIndex:t,feedback:e})})},reset(){y(null),f=!1,g=null}}}0&&(module.exports={BitPalmApiError,createChatClient});
13
+ //# sourceMappingURL=headless.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/headless.ts","../src/sse.ts"],"sourcesContent":["import { parseAllEvents, takeEvents, type ChatStreamEvent } from \"./sse\";\n\n/*\n * Your own chat UI on top of BitPalm: this client talks to /api/v1 with an\n * app key and handles the visitor id, the conversation and the stream.\n * No UI in here. Works in browsers, Capacitor and Ionic apps, and in React\n * Native (without streaming, the answer then arrives at once).\n */\n\nexport interface ChatCard {\n kind?: string;\n title: string;\n image?: string;\n subtitle?: string;\n fields?: { label: string; value: string }[];\n cta?: { label: string; url: string };\n}\n\nexport interface ChatMessage {\n /** Set on messages from history() and updates(). */\n id?: string;\n role: \"user\" | \"assistant\";\n text: string;\n createdAt?: string;\n cards?: ChatCard[];\n /** Photos the user sent, as links. */\n images?: string[];\n /** Written by a person of the team, not by the agent. */\n fromHuman?: boolean;\n}\n\nexport interface QuickLink {\n id: string;\n label: string;\n /** Send this as the user's message. */\n message?: string;\n /** Or open this address. */\n url?: string;\n}\n\nexport interface AgentConfig {\n name: string;\n logoUrl: string | null;\n primaryColor: string;\n welcomeMessage: string;\n inputPlaceholder: string;\n quickLinks: QuickLink[];\n photoUploads: boolean;\n /** When required is true, show text linked to url in your chat UI. */\n branding: { required: boolean; text: string; url: string };\n}\n\nexport interface ChatClientOptions {\n /** App key from the dashboard, starts with bp_pk_. */\n key: string;\n /** Defaults to https://agents.bitpalm.ai. */\n baseUrl?: string;\n /**\n * Id that holds the conversation together. Leave it out: the client\n * creates a random one and remembers it. If you set it, make it\n * unguessable. Never use a plain user id, anyone with the app key could\n * read that user's chats.\n */\n visitorId?: string;\n /** Language for greeting, placeholder and quick links, like \"de\". */\n locale?: string;\n /** Where visitor and conversation are remembered. Defaults to localStorage when there is one. */\n storage?: Pick<Storage, \"getItem\" | \"setItem\" | \"removeItem\"> | null;\n}\n\nexport interface SendOptions {\n /** Facts for this answer, like the cart or the user's plan. At most 4 KB. */\n context?: Record<string, unknown>;\n /** Ids of photos from upload(). */\n fileIds?: string[];\n /** Called as the answer grows: the new piece and the whole answer so far. */\n onDelta?: (piece: string, answer: string) => void;\n signal?: AbortSignal;\n}\n\nexport interface SendResult {\n text: string;\n conversationId: string;\n cards?: ChatCard[];\n /**\n * Your team has the conversation now. The agent stays silent in it until\n * the team closes it, the team's replies come with history().\n */\n handoff?: boolean;\n}\n\n/** What happened while your team has the conversation. */\nexport interface ChatUpdates {\n /** False once your team gave the conversation back to the agent. */\n handoff: boolean;\n /** Someone of your team is typing right now. */\n teamTyping: boolean;\n /** Replies of your team since the last call, oldest first. */\n messages: ChatMessage[];\n}\n\nexport interface Identity {\n name?: string;\n email?: string;\n phone?: string;\n company?: string;\n externalUserId?: string;\n}\n\n/** An error of the API, with its code, like \"invalid_key\" or \"rate_limited\". */\nexport class BitPalmApiError extends Error {\n constructor(\n readonly code: string,\n message: string,\n readonly status: number,\n ) {\n super(message);\n this.name = \"BitPalmApiError\";\n }\n}\n\nexport interface ChatClient {\n readonly visitorId: string;\n readonly conversationId: string | null;\n /** True while your team has the conversation. Updated by send() and history(). */\n readonly handoff: boolean;\n /** Name, greeting, quick links and whether \"Powered by BitPalm\" has to show. */\n agent(options?: { url?: string }): Promise<AgentConfig>;\n send(message: string, options?: SendOptions): Promise<SendResult>;\n /** The messages of the current conversation, or of the latest one of this visitor. */\n history(): Promise<ChatMessage[]>;\n /** New replies of your team and whether someone is typing. Call it every few seconds while handoff is true. */\n updates(): Promise<ChatUpdates>;\n /** Tells BitPalm who the logged-in user is. */\n identify(identity: Identity): Promise<void>;\n /** A photo for the next message, when the agent takes photos. */\n upload(file: Blob, fileName?: string): Promise<{ id: string; url: string }>;\n /** Thumbs up or down for the agent's answer number index (0 is the first answer). */\n feedback(index: number, value: \"up\" | \"down\"): Promise<void>;\n /** Starts a new conversation. */\n reset(): void;\n}\n\nconst DEFAULT_BASE_URL = \"https://agents.bitpalm.ai\";\n\nfunction defaultStorage(): ChatClientOptions[\"storage\"] {\n try {\n return typeof localStorage === \"undefined\" ? null : localStorage;\n } catch {\n return null;\n }\n}\n\nfunction newVisitorId(): string {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") return crypto.randomUUID();\n return `v-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`;\n}\n\nasync function failure(response: Response): Promise<BitPalmApiError> {\n const body = (await response.json().catch(() => null)) as { error?: { code?: string; message?: string } } | null;\n return new BitPalmApiError(body?.error?.code ?? \"server_error\", body?.error?.message ?? `Request failed (${response.status})`, response.status);\n}\n\nexport function createChatClient(options: ChatClientOptions): ChatClient {\n if (!options?.key?.startsWith(\"bp_pk_\")) throw new Error(\"createChatClient needs an app key (bp_pk_…) from the BitPalm dashboard.\");\n const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n const storage = options.storage === undefined ? defaultStorage() : options.storage;\n const space = `bitpalm:${options.key.slice(0, 14)}`;\n const read = (name: string) => {\n try {\n return storage?.getItem(`${space}:${name}`) ?? null;\n } catch {\n return null;\n }\n };\n const write = (name: string, value: string | null) => {\n try {\n if (value === null) storage?.removeItem(`${space}:${name}`);\n else storage?.setItem(`${space}:${name}`, value);\n } catch {\n // Private mode or full storage, the client still works for this session.\n }\n };\n\n const visitorId = options.visitorId ?? read(\"visitor\") ?? newVisitorId();\n if (!options.visitorId) write(\"visitor\", visitorId);\n let conversationId = read(\"conversation\");\n let handoff = false;\n // The newest reply of the team we know of, so updates() only brings newer ones.\n let teamCursor: string | null = null;\n const noteTeamReplies = (messages: ChatMessage[]) => {\n for (const message of messages) {\n if (message.fromHuman && message.createdAt && (!teamCursor || message.createdAt > teamCursor)) teamCursor = message.createdAt;\n }\n };\n\n const headers = { Authorization: `Bearer ${options.key}` };\n const call = async (path: string, init?: RequestInit) => {\n const response = await fetch(`${baseUrl}${path}`, { ...init, headers: { ...headers, ...(init?.headers ?? {}) } });\n if (!response.ok) throw await failure(response);\n return response;\n };\n const remember = (id: string | null) => {\n conversationId = id;\n write(\"conversation\", id);\n };\n\n const applyEvents = (events: ChatStreamEvent[], state: { text: string; result: SendResult | null }, onDelta?: SendOptions[\"onDelta\"]) => {\n for (const event of events) {\n if (event.type === \"delta\") {\n state.text += event.text;\n onDelta?.(event.text, state.text);\n } else if (event.type === \"replace\") {\n state.text = event.text;\n onDelta?.(\"\", state.text);\n } else if (event.type === \"done\") {\n state.result = {\n text: state.text,\n conversationId: event.conversationId,\n ...(event.cards ? { cards: event.cards as ChatCard[] } : {}),\n ...(event.handoff ? { handoff: true } : {}),\n };\n } else if (event.type === \"error\") {\n throw new BitPalmApiError(\"server_error\", event.message, 500);\n }\n }\n };\n\n return {\n visitorId,\n get conversationId() {\n return conversationId;\n },\n get handoff() {\n return handoff;\n },\n\n async agent(agentOptions) {\n const params = new URLSearchParams({ locale: options.locale ?? \"en\" });\n if (agentOptions?.url) params.set(\"url\", agentOptions.url);\n return (await call(`/api/v1/agent?${params.toString()}`)).json() as Promise<AgentConfig>;\n },\n\n async send(message, sendOptions = {}) {\n const response = await call(\"/api/v1/chat\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n signal: sendOptions.signal,\n body: JSON.stringify({\n message,\n visitorId,\n conversationId: conversationId ?? undefined,\n context: sendOptions.context,\n fileIds: sendOptions.fileIds,\n }),\n });\n\n const state: { text: string; result: SendResult | null } = { text: \"\", result: null };\n const reader = response.body && typeof response.body.getReader === \"function\" ? response.body.getReader() : null;\n if (reader) {\n const decoder = new TextDecoder();\n let buffer = \"\";\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n const taken = takeEvents(buffer + decoder.decode(value, { stream: true }));\n buffer = taken.rest;\n applyEvents(taken.events, state, sendOptions.onDelta);\n }\n applyEvents(takeEvents(`${buffer}\\n\\n`).events, state, sendOptions.onDelta);\n } else {\n applyEvents(parseAllEvents(await response.text()), state, sendOptions.onDelta);\n }\n\n const result = state.result ?? { text: state.text, conversationId: conversationId ?? \"\" };\n if (result.conversationId) remember(result.conversationId);\n handoff = result.handoff === true;\n return result;\n },\n\n async history() {\n const params = new URLSearchParams({ visitorId });\n if (conversationId) params.set(\"conversationId\", conversationId);\n const body = (await (await call(`/api/v1/chat/history?${params.toString()}`)).json()) as {\n conversationId: string | null;\n handoff?: boolean;\n messages: ChatMessage[];\n };\n if (body.conversationId) remember(body.conversationId);\n handoff = body.handoff === true;\n teamCursor = null;\n noteTeamReplies(body.messages);\n return body.messages;\n },\n\n async updates() {\n if (!conversationId) return { handoff: false, teamTyping: false, messages: [] };\n const params = new URLSearchParams({ visitorId, conversationId });\n if (teamCursor) params.set(\"after\", teamCursor);\n const body = (await (await call(`/api/v1/chat/updates?${params.toString()}`)).json()) as Partial<ChatUpdates>;\n const messages = body.messages ?? [];\n noteTeamReplies(messages);\n handoff = body.handoff === true;\n return { handoff, teamTyping: body.teamTyping === true, messages };\n },\n\n async identify(identity) {\n await call(\"/api/v1/identify\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ ...identity, visitorId }),\n });\n },\n\n async upload(file, fileName = \"photo.jpg\") {\n const form = new FormData();\n form.append(\"file\", file, fileName);\n form.append(\"visitorId\", visitorId);\n if (conversationId) form.append(\"conversationId\", conversationId);\n const body = (await (await call(\"/api/v1/chat/upload\", { method: \"POST\", body: form })).json()) as { id: string; url: string };\n return { id: body.id, url: body.url };\n },\n\n async feedback(index, value) {\n if (!conversationId) throw new BitPalmApiError(\"bad_request\", \"There is no conversation yet.\", 400);\n await call(\"/api/v1/chat/feedback\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ visitorId, conversationId, messageIndex: index, feedback: value }),\n });\n },\n\n reset() {\n remember(null);\n handoff = false;\n teamCursor = null;\n },\n };\n}\n","/*\n * Reading the event stream of /api/v1/chat: blocks separated by a blank\n * line, \"data: {json}\" lines inside, \": ping\" to keep the line open.\n */\n\nexport type ChatStreamEvent =\n | { type: \"delta\"; text: string }\n | { type: \"replace\"; text: string }\n | { type: \"done\"; conversationId: string; cards?: unknown[]; handoff?: boolean }\n | { type: \"error\"; message: string };\n\nfunction parseBlock(block: string): ChatStreamEvent | null {\n const data = block\n .split(\"\\n\")\n .filter((line) => line.startsWith(\"data:\"))\n .map((line) => line.slice(5).trimStart())\n .join(\"\\n\");\n if (!data) return null;\n try {\n const event = JSON.parse(data) as ChatStreamEvent;\n return event && typeof event.type === \"string\" ? event : null;\n } catch {\n return null;\n }\n}\n\n/** Takes what arrived so far, returns the complete events and what is still open. */\nexport function takeEvents(buffer: string): { events: ChatStreamEvent[]; rest: string } {\n const events: ChatStreamEvent[] = [];\n let rest = buffer.replace(/\\r\\n/g, \"\\n\");\n let boundary = rest.indexOf(\"\\n\\n\");\n while (boundary >= 0) {\n const event = parseBlock(rest.slice(0, boundary));\n if (event) events.push(event);\n rest = rest.slice(boundary + 2);\n boundary = rest.indexOf(\"\\n\\n\");\n }\n return { events, rest };\n}\n\n/** The whole body at once, for runtimes whose fetch can't stream (React Native). */\nexport function parseAllEvents(body: string): ChatStreamEvent[] {\n return takeEvents(`${body}\\n\\n`).events;\n}\n"],"mappings":"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","names":["headless_exports","__export","BitPalmApiError","createChatClient","__toCommonJS","parseBlock","block","data","line","event","takeEvents","buffer","events","rest","boundary","parseAllEvents","body","BitPalmApiError","code","message","status","DEFAULT_BASE_URL","defaultStorage","newVisitorId","failure","response","body","createChatClient","options","baseUrl","storage","space","read","name","write","value","visitorId","conversationId","handoff","teamCursor","noteTeamReplies","messages","headers","call","path","init","remember","id","applyEvents","events","state","onDelta","event","agentOptions","params","sendOptions","reader","decoder","buffer","done","taken","takeEvents","parseAllEvents","result","identity","file","fileName","form","index"]}
@@ -0,0 +1,136 @@
1
+ interface ChatCard {
2
+ kind?: string;
3
+ title: string;
4
+ image?: string;
5
+ subtitle?: string;
6
+ fields?: {
7
+ label: string;
8
+ value: string;
9
+ }[];
10
+ cta?: {
11
+ label: string;
12
+ url: string;
13
+ };
14
+ }
15
+ interface ChatMessage {
16
+ /** Set on messages from history() and updates(). */
17
+ id?: string;
18
+ role: "user" | "assistant";
19
+ text: string;
20
+ createdAt?: string;
21
+ cards?: ChatCard[];
22
+ /** Photos the user sent, as links. */
23
+ images?: string[];
24
+ /** Written by a person of the team, not by the agent. */
25
+ fromHuman?: boolean;
26
+ }
27
+ interface QuickLink {
28
+ id: string;
29
+ label: string;
30
+ /** Send this as the user's message. */
31
+ message?: string;
32
+ /** Or open this address. */
33
+ url?: string;
34
+ }
35
+ interface AgentConfig {
36
+ name: string;
37
+ logoUrl: string | null;
38
+ primaryColor: string;
39
+ welcomeMessage: string;
40
+ inputPlaceholder: string;
41
+ quickLinks: QuickLink[];
42
+ photoUploads: boolean;
43
+ /** When required is true, show text linked to url in your chat UI. */
44
+ branding: {
45
+ required: boolean;
46
+ text: string;
47
+ url: string;
48
+ };
49
+ }
50
+ interface ChatClientOptions {
51
+ /** App key from the dashboard, starts with bp_pk_. */
52
+ key: string;
53
+ /** Defaults to https://agents.bitpalm.ai. */
54
+ baseUrl?: string;
55
+ /**
56
+ * Id that holds the conversation together. Leave it out: the client
57
+ * creates a random one and remembers it. If you set it, make it
58
+ * unguessable. Never use a plain user id, anyone with the app key could
59
+ * read that user's chats.
60
+ */
61
+ visitorId?: string;
62
+ /** Language for greeting, placeholder and quick links, like "de". */
63
+ locale?: string;
64
+ /** Where visitor and conversation are remembered. Defaults to localStorage when there is one. */
65
+ storage?: Pick<Storage, "getItem" | "setItem" | "removeItem"> | null;
66
+ }
67
+ interface SendOptions {
68
+ /** Facts for this answer, like the cart or the user's plan. At most 4 KB. */
69
+ context?: Record<string, unknown>;
70
+ /** Ids of photos from upload(). */
71
+ fileIds?: string[];
72
+ /** Called as the answer grows: the new piece and the whole answer so far. */
73
+ onDelta?: (piece: string, answer: string) => void;
74
+ signal?: AbortSignal;
75
+ }
76
+ interface SendResult {
77
+ text: string;
78
+ conversationId: string;
79
+ cards?: ChatCard[];
80
+ /**
81
+ * Your team has the conversation now. The agent stays silent in it until
82
+ * the team closes it, the team's replies come with history().
83
+ */
84
+ handoff?: boolean;
85
+ }
86
+ /** What happened while your team has the conversation. */
87
+ interface ChatUpdates {
88
+ /** False once your team gave the conversation back to the agent. */
89
+ handoff: boolean;
90
+ /** Someone of your team is typing right now. */
91
+ teamTyping: boolean;
92
+ /** Replies of your team since the last call, oldest first. */
93
+ messages: ChatMessage[];
94
+ }
95
+ interface Identity {
96
+ name?: string;
97
+ email?: string;
98
+ phone?: string;
99
+ company?: string;
100
+ externalUserId?: string;
101
+ }
102
+ /** An error of the API, with its code, like "invalid_key" or "rate_limited". */
103
+ declare class BitPalmApiError extends Error {
104
+ readonly code: string;
105
+ readonly status: number;
106
+ constructor(code: string, message: string, status: number);
107
+ }
108
+ interface ChatClient {
109
+ readonly visitorId: string;
110
+ readonly conversationId: string | null;
111
+ /** True while your team has the conversation. Updated by send() and history(). */
112
+ readonly handoff: boolean;
113
+ /** Name, greeting, quick links and whether "Powered by BitPalm" has to show. */
114
+ agent(options?: {
115
+ url?: string;
116
+ }): Promise<AgentConfig>;
117
+ send(message: string, options?: SendOptions): Promise<SendResult>;
118
+ /** The messages of the current conversation, or of the latest one of this visitor. */
119
+ history(): Promise<ChatMessage[]>;
120
+ /** New replies of your team and whether someone is typing. Call it every few seconds while handoff is true. */
121
+ updates(): Promise<ChatUpdates>;
122
+ /** Tells BitPalm who the logged-in user is. */
123
+ identify(identity: Identity): Promise<void>;
124
+ /** A photo for the next message, when the agent takes photos. */
125
+ upload(file: Blob, fileName?: string): Promise<{
126
+ id: string;
127
+ url: string;
128
+ }>;
129
+ /** Thumbs up or down for the agent's answer number index (0 is the first answer). */
130
+ feedback(index: number, value: "up" | "down"): Promise<void>;
131
+ /** Starts a new conversation. */
132
+ reset(): void;
133
+ }
134
+ declare function createChatClient(options: ChatClientOptions): ChatClient;
135
+
136
+ export { type AgentConfig, BitPalmApiError, type ChatCard, type ChatClient, type ChatClientOptions, type ChatMessage, type ChatUpdates, type Identity, type QuickLink, type SendOptions, type SendResult, createChatClient };
@@ -0,0 +1,136 @@
1
+ interface ChatCard {
2
+ kind?: string;
3
+ title: string;
4
+ image?: string;
5
+ subtitle?: string;
6
+ fields?: {
7
+ label: string;
8
+ value: string;
9
+ }[];
10
+ cta?: {
11
+ label: string;
12
+ url: string;
13
+ };
14
+ }
15
+ interface ChatMessage {
16
+ /** Set on messages from history() and updates(). */
17
+ id?: string;
18
+ role: "user" | "assistant";
19
+ text: string;
20
+ createdAt?: string;
21
+ cards?: ChatCard[];
22
+ /** Photos the user sent, as links. */
23
+ images?: string[];
24
+ /** Written by a person of the team, not by the agent. */
25
+ fromHuman?: boolean;
26
+ }
27
+ interface QuickLink {
28
+ id: string;
29
+ label: string;
30
+ /** Send this as the user's message. */
31
+ message?: string;
32
+ /** Or open this address. */
33
+ url?: string;
34
+ }
35
+ interface AgentConfig {
36
+ name: string;
37
+ logoUrl: string | null;
38
+ primaryColor: string;
39
+ welcomeMessage: string;
40
+ inputPlaceholder: string;
41
+ quickLinks: QuickLink[];
42
+ photoUploads: boolean;
43
+ /** When required is true, show text linked to url in your chat UI. */
44
+ branding: {
45
+ required: boolean;
46
+ text: string;
47
+ url: string;
48
+ };
49
+ }
50
+ interface ChatClientOptions {
51
+ /** App key from the dashboard, starts with bp_pk_. */
52
+ key: string;
53
+ /** Defaults to https://agents.bitpalm.ai. */
54
+ baseUrl?: string;
55
+ /**
56
+ * Id that holds the conversation together. Leave it out: the client
57
+ * creates a random one and remembers it. If you set it, make it
58
+ * unguessable. Never use a plain user id, anyone with the app key could
59
+ * read that user's chats.
60
+ */
61
+ visitorId?: string;
62
+ /** Language for greeting, placeholder and quick links, like "de". */
63
+ locale?: string;
64
+ /** Where visitor and conversation are remembered. Defaults to localStorage when there is one. */
65
+ storage?: Pick<Storage, "getItem" | "setItem" | "removeItem"> | null;
66
+ }
67
+ interface SendOptions {
68
+ /** Facts for this answer, like the cart or the user's plan. At most 4 KB. */
69
+ context?: Record<string, unknown>;
70
+ /** Ids of photos from upload(). */
71
+ fileIds?: string[];
72
+ /** Called as the answer grows: the new piece and the whole answer so far. */
73
+ onDelta?: (piece: string, answer: string) => void;
74
+ signal?: AbortSignal;
75
+ }
76
+ interface SendResult {
77
+ text: string;
78
+ conversationId: string;
79
+ cards?: ChatCard[];
80
+ /**
81
+ * Your team has the conversation now. The agent stays silent in it until
82
+ * the team closes it, the team's replies come with history().
83
+ */
84
+ handoff?: boolean;
85
+ }
86
+ /** What happened while your team has the conversation. */
87
+ interface ChatUpdates {
88
+ /** False once your team gave the conversation back to the agent. */
89
+ handoff: boolean;
90
+ /** Someone of your team is typing right now. */
91
+ teamTyping: boolean;
92
+ /** Replies of your team since the last call, oldest first. */
93
+ messages: ChatMessage[];
94
+ }
95
+ interface Identity {
96
+ name?: string;
97
+ email?: string;
98
+ phone?: string;
99
+ company?: string;
100
+ externalUserId?: string;
101
+ }
102
+ /** An error of the API, with its code, like "invalid_key" or "rate_limited". */
103
+ declare class BitPalmApiError extends Error {
104
+ readonly code: string;
105
+ readonly status: number;
106
+ constructor(code: string, message: string, status: number);
107
+ }
108
+ interface ChatClient {
109
+ readonly visitorId: string;
110
+ readonly conversationId: string | null;
111
+ /** True while your team has the conversation. Updated by send() and history(). */
112
+ readonly handoff: boolean;
113
+ /** Name, greeting, quick links and whether "Powered by BitPalm" has to show. */
114
+ agent(options?: {
115
+ url?: string;
116
+ }): Promise<AgentConfig>;
117
+ send(message: string, options?: SendOptions): Promise<SendResult>;
118
+ /** The messages of the current conversation, or of the latest one of this visitor. */
119
+ history(): Promise<ChatMessage[]>;
120
+ /** New replies of your team and whether someone is typing. Call it every few seconds while handoff is true. */
121
+ updates(): Promise<ChatUpdates>;
122
+ /** Tells BitPalm who the logged-in user is. */
123
+ identify(identity: Identity): Promise<void>;
124
+ /** A photo for the next message, when the agent takes photos. */
125
+ upload(file: Blob, fileName?: string): Promise<{
126
+ id: string;
127
+ url: string;
128
+ }>;
129
+ /** Thumbs up or down for the agent's answer number index (0 is the first answer). */
130
+ feedback(index: number, value: "up" | "down"): Promise<void>;
131
+ /** Starts a new conversation. */
132
+ reset(): void;
133
+ }
134
+ declare function createChatClient(options: ChatClientOptions): ChatClient;
135
+
136
+ export { type AgentConfig, BitPalmApiError, type ChatCard, type ChatClient, type ChatClientOptions, type ChatMessage, type ChatUpdates, type Identity, type QuickLink, type SendOptions, type SendResult, createChatClient };
@@ -0,0 +1,13 @@
1
+ function U(r){let o=r.split(`
2
+ `).filter(a=>a.startsWith("data:")).map(a=>a.slice(5).trimStart()).join(`
3
+ `);if(!o)return null;try{let a=JSON.parse(o);return a&&typeof a.type=="string"?a:null}catch{return null}}function h(r){let o=[],a=r.replace(/\r\n/g,`
4
+ `),l=a.indexOf(`
5
+
6
+ `);for(;l>=0;){let u=U(a.slice(0,l));u&&o.push(u),a=a.slice(l+2),l=a.indexOf(`
7
+
8
+ `)}return{events:o,rest:a}}function w(r){return h(`${r}
9
+
10
+ `).events}var p=class extends Error{constructor(a,l,u){super(l);this.code=a;this.status=u;this.name="BitPalmApiError"}},R="https://agents.bitpalm.ai";function T(){try{return typeof localStorage>"u"?null:localStorage}catch{return null}}function A(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`v-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,12)}`}async function j(r){let o=await r.json().catch(()=>null);return new p(o?.error?.code??"server_error",o?.error?.message??`Request failed (${r.status})`,r.status)}function _(r){if(!r?.key?.startsWith("bp_pk_"))throw new Error("createChatClient needs an app key (bp_pk_\u2026) from the BitPalm dashboard.");let o=(r.baseUrl??R).replace(/\/+$/,""),a=r.storage===void 0?T():r.storage,l=`bitpalm:${r.key.slice(0,14)}`,u=t=>{try{return a?.getItem(`${l}:${t}`)??null}catch{return null}},C=(t,e)=>{try{e===null?a?.removeItem(`${l}:${t}`):a?.setItem(`${l}:${t}`,e)}catch{}},d=r.visitorId??u("visitor")??A();r.visitorId||C("visitor",d);let i=u("conversation"),f=!1,c=null,x=t=>{for(let e of t)e.fromHuman&&e.createdAt&&(!c||e.createdAt>c)&&(c=e.createdAt)},k={Authorization:`Bearer ${r.key}`},g=async(t,e)=>{let s=await fetch(`${o}${t}`,{...e,headers:{...k,...e?.headers??{}}});if(!s.ok)throw await j(s);return s},y=t=>{i=t,C("conversation",t)},v=(t,e,s)=>{for(let n of t)if(n.type==="delta")e.text+=n.text,s?.(n.text,e.text);else if(n.type==="replace")e.text=n.text,s?.("",e.text);else if(n.type==="done")e.result={text:e.text,conversationId:n.conversationId,...n.cards?{cards:n.cards}:{},...n.handoff?{handoff:!0}:{}};else if(n.type==="error")throw new p("server_error",n.message,500)};return{visitorId:d,get conversationId(){return i},get handoff(){return f},async agent(t){let e=new URLSearchParams({locale:r.locale??"en"});return t?.url&&e.set("url",t.url),(await g(`/api/v1/agent?${e.toString()}`)).json()},async send(t,e={}){let s=await g("/api/v1/chat",{method:"POST",headers:{"Content-Type":"application/json"},signal:e.signal,body:JSON.stringify({message:t,visitorId:d,conversationId:i??void 0,context:e.context,fileIds:e.fileIds})}),n={text:"",result:null},I=s.body&&typeof s.body.getReader=="function"?s.body.getReader():null;if(I){let P=new TextDecoder,b="";for(;;){let{done:$,value:E}=await I.read();if($)break;let S=h(b+P.decode(E,{stream:!0}));b=S.rest,v(S.events,n,e.onDelta)}v(h(`${b}
11
+
12
+ `).events,n,e.onDelta)}else v(w(await s.text()),n,e.onDelta);let m=n.result??{text:n.text,conversationId:i??""};return m.conversationId&&y(m.conversationId),f=m.handoff===!0,m},async history(){let t=new URLSearchParams({visitorId:d});i&&t.set("conversationId",i);let e=await(await g(`/api/v1/chat/history?${t.toString()}`)).json();return e.conversationId&&y(e.conversationId),f=e.handoff===!0,c=null,x(e.messages),e.messages},async updates(){if(!i)return{handoff:!1,teamTyping:!1,messages:[]};let t=new URLSearchParams({visitorId:d,conversationId:i});c&&t.set("after",c);let e=await(await g(`/api/v1/chat/updates?${t.toString()}`)).json(),s=e.messages??[];return x(s),f=e.handoff===!0,{handoff:f,teamTyping:e.teamTyping===!0,messages:s}},async identify(t){await g("/api/v1/identify",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({...t,visitorId:d})})},async upload(t,e="photo.jpg"){let s=new FormData;s.append("file",t,e),s.append("visitorId",d),i&&s.append("conversationId",i);let n=await(await g("/api/v1/chat/upload",{method:"POST",body:s})).json();return{id:n.id,url:n.url}},async feedback(t,e){if(!i)throw new p("bad_request","There is no conversation yet.",400);await g("/api/v1/chat/feedback",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({visitorId:d,conversationId:i,messageIndex:t,feedback:e})})},reset(){y(null),f=!1,c=null}}}export{p as BitPalmApiError,_ as createChatClient};
13
+ //# sourceMappingURL=headless.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sse.ts","../src/headless.ts"],"sourcesContent":["/*\n * Reading the event stream of /api/v1/chat: blocks separated by a blank\n * line, \"data: {json}\" lines inside, \": ping\" to keep the line open.\n */\n\nexport type ChatStreamEvent =\n | { type: \"delta\"; text: string }\n | { type: \"replace\"; text: string }\n | { type: \"done\"; conversationId: string; cards?: unknown[]; handoff?: boolean }\n | { type: \"error\"; message: string };\n\nfunction parseBlock(block: string): ChatStreamEvent | null {\n const data = block\n .split(\"\\n\")\n .filter((line) => line.startsWith(\"data:\"))\n .map((line) => line.slice(5).trimStart())\n .join(\"\\n\");\n if (!data) return null;\n try {\n const event = JSON.parse(data) as ChatStreamEvent;\n return event && typeof event.type === \"string\" ? event : null;\n } catch {\n return null;\n }\n}\n\n/** Takes what arrived so far, returns the complete events and what is still open. */\nexport function takeEvents(buffer: string): { events: ChatStreamEvent[]; rest: string } {\n const events: ChatStreamEvent[] = [];\n let rest = buffer.replace(/\\r\\n/g, \"\\n\");\n let boundary = rest.indexOf(\"\\n\\n\");\n while (boundary >= 0) {\n const event = parseBlock(rest.slice(0, boundary));\n if (event) events.push(event);\n rest = rest.slice(boundary + 2);\n boundary = rest.indexOf(\"\\n\\n\");\n }\n return { events, rest };\n}\n\n/** The whole body at once, for runtimes whose fetch can't stream (React Native). */\nexport function parseAllEvents(body: string): ChatStreamEvent[] {\n return takeEvents(`${body}\\n\\n`).events;\n}\n","import { parseAllEvents, takeEvents, type ChatStreamEvent } from \"./sse\";\n\n/*\n * Your own chat UI on top of BitPalm: this client talks to /api/v1 with an\n * app key and handles the visitor id, the conversation and the stream.\n * No UI in here. Works in browsers, Capacitor and Ionic apps, and in React\n * Native (without streaming, the answer then arrives at once).\n */\n\nexport interface ChatCard {\n kind?: string;\n title: string;\n image?: string;\n subtitle?: string;\n fields?: { label: string; value: string }[];\n cta?: { label: string; url: string };\n}\n\nexport interface ChatMessage {\n /** Set on messages from history() and updates(). */\n id?: string;\n role: \"user\" | \"assistant\";\n text: string;\n createdAt?: string;\n cards?: ChatCard[];\n /** Photos the user sent, as links. */\n images?: string[];\n /** Written by a person of the team, not by the agent. */\n fromHuman?: boolean;\n}\n\nexport interface QuickLink {\n id: string;\n label: string;\n /** Send this as the user's message. */\n message?: string;\n /** Or open this address. */\n url?: string;\n}\n\nexport interface AgentConfig {\n name: string;\n logoUrl: string | null;\n primaryColor: string;\n welcomeMessage: string;\n inputPlaceholder: string;\n quickLinks: QuickLink[];\n photoUploads: boolean;\n /** When required is true, show text linked to url in your chat UI. */\n branding: { required: boolean; text: string; url: string };\n}\n\nexport interface ChatClientOptions {\n /** App key from the dashboard, starts with bp_pk_. */\n key: string;\n /** Defaults to https://agents.bitpalm.ai. */\n baseUrl?: string;\n /**\n * Id that holds the conversation together. Leave it out: the client\n * creates a random one and remembers it. If you set it, make it\n * unguessable. Never use a plain user id, anyone with the app key could\n * read that user's chats.\n */\n visitorId?: string;\n /** Language for greeting, placeholder and quick links, like \"de\". */\n locale?: string;\n /** Where visitor and conversation are remembered. Defaults to localStorage when there is one. */\n storage?: Pick<Storage, \"getItem\" | \"setItem\" | \"removeItem\"> | null;\n}\n\nexport interface SendOptions {\n /** Facts for this answer, like the cart or the user's plan. At most 4 KB. */\n context?: Record<string, unknown>;\n /** Ids of photos from upload(). */\n fileIds?: string[];\n /** Called as the answer grows: the new piece and the whole answer so far. */\n onDelta?: (piece: string, answer: string) => void;\n signal?: AbortSignal;\n}\n\nexport interface SendResult {\n text: string;\n conversationId: string;\n cards?: ChatCard[];\n /**\n * Your team has the conversation now. The agent stays silent in it until\n * the team closes it, the team's replies come with history().\n */\n handoff?: boolean;\n}\n\n/** What happened while your team has the conversation. */\nexport interface ChatUpdates {\n /** False once your team gave the conversation back to the agent. */\n handoff: boolean;\n /** Someone of your team is typing right now. */\n teamTyping: boolean;\n /** Replies of your team since the last call, oldest first. */\n messages: ChatMessage[];\n}\n\nexport interface Identity {\n name?: string;\n email?: string;\n phone?: string;\n company?: string;\n externalUserId?: string;\n}\n\n/** An error of the API, with its code, like \"invalid_key\" or \"rate_limited\". */\nexport class BitPalmApiError extends Error {\n constructor(\n readonly code: string,\n message: string,\n readonly status: number,\n ) {\n super(message);\n this.name = \"BitPalmApiError\";\n }\n}\n\nexport interface ChatClient {\n readonly visitorId: string;\n readonly conversationId: string | null;\n /** True while your team has the conversation. Updated by send() and history(). */\n readonly handoff: boolean;\n /** Name, greeting, quick links and whether \"Powered by BitPalm\" has to show. */\n agent(options?: { url?: string }): Promise<AgentConfig>;\n send(message: string, options?: SendOptions): Promise<SendResult>;\n /** The messages of the current conversation, or of the latest one of this visitor. */\n history(): Promise<ChatMessage[]>;\n /** New replies of your team and whether someone is typing. Call it every few seconds while handoff is true. */\n updates(): Promise<ChatUpdates>;\n /** Tells BitPalm who the logged-in user is. */\n identify(identity: Identity): Promise<void>;\n /** A photo for the next message, when the agent takes photos. */\n upload(file: Blob, fileName?: string): Promise<{ id: string; url: string }>;\n /** Thumbs up or down for the agent's answer number index (0 is the first answer). */\n feedback(index: number, value: \"up\" | \"down\"): Promise<void>;\n /** Starts a new conversation. */\n reset(): void;\n}\n\nconst DEFAULT_BASE_URL = \"https://agents.bitpalm.ai\";\n\nfunction defaultStorage(): ChatClientOptions[\"storage\"] {\n try {\n return typeof localStorage === \"undefined\" ? null : localStorage;\n } catch {\n return null;\n }\n}\n\nfunction newVisitorId(): string {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") return crypto.randomUUID();\n return `v-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`;\n}\n\nasync function failure(response: Response): Promise<BitPalmApiError> {\n const body = (await response.json().catch(() => null)) as { error?: { code?: string; message?: string } } | null;\n return new BitPalmApiError(body?.error?.code ?? \"server_error\", body?.error?.message ?? `Request failed (${response.status})`, response.status);\n}\n\nexport function createChatClient(options: ChatClientOptions): ChatClient {\n if (!options?.key?.startsWith(\"bp_pk_\")) throw new Error(\"createChatClient needs an app key (bp_pk_…) from the BitPalm dashboard.\");\n const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n const storage = options.storage === undefined ? defaultStorage() : options.storage;\n const space = `bitpalm:${options.key.slice(0, 14)}`;\n const read = (name: string) => {\n try {\n return storage?.getItem(`${space}:${name}`) ?? null;\n } catch {\n return null;\n }\n };\n const write = (name: string, value: string | null) => {\n try {\n if (value === null) storage?.removeItem(`${space}:${name}`);\n else storage?.setItem(`${space}:${name}`, value);\n } catch {\n // Private mode or full storage, the client still works for this session.\n }\n };\n\n const visitorId = options.visitorId ?? read(\"visitor\") ?? newVisitorId();\n if (!options.visitorId) write(\"visitor\", visitorId);\n let conversationId = read(\"conversation\");\n let handoff = false;\n // The newest reply of the team we know of, so updates() only brings newer ones.\n let teamCursor: string | null = null;\n const noteTeamReplies = (messages: ChatMessage[]) => {\n for (const message of messages) {\n if (message.fromHuman && message.createdAt && (!teamCursor || message.createdAt > teamCursor)) teamCursor = message.createdAt;\n }\n };\n\n const headers = { Authorization: `Bearer ${options.key}` };\n const call = async (path: string, init?: RequestInit) => {\n const response = await fetch(`${baseUrl}${path}`, { ...init, headers: { ...headers, ...(init?.headers ?? {}) } });\n if (!response.ok) throw await failure(response);\n return response;\n };\n const remember = (id: string | null) => {\n conversationId = id;\n write(\"conversation\", id);\n };\n\n const applyEvents = (events: ChatStreamEvent[], state: { text: string; result: SendResult | null }, onDelta?: SendOptions[\"onDelta\"]) => {\n for (const event of events) {\n if (event.type === \"delta\") {\n state.text += event.text;\n onDelta?.(event.text, state.text);\n } else if (event.type === \"replace\") {\n state.text = event.text;\n onDelta?.(\"\", state.text);\n } else if (event.type === \"done\") {\n state.result = {\n text: state.text,\n conversationId: event.conversationId,\n ...(event.cards ? { cards: event.cards as ChatCard[] } : {}),\n ...(event.handoff ? { handoff: true } : {}),\n };\n } else if (event.type === \"error\") {\n throw new BitPalmApiError(\"server_error\", event.message, 500);\n }\n }\n };\n\n return {\n visitorId,\n get conversationId() {\n return conversationId;\n },\n get handoff() {\n return handoff;\n },\n\n async agent(agentOptions) {\n const params = new URLSearchParams({ locale: options.locale ?? \"en\" });\n if (agentOptions?.url) params.set(\"url\", agentOptions.url);\n return (await call(`/api/v1/agent?${params.toString()}`)).json() as Promise<AgentConfig>;\n },\n\n async send(message, sendOptions = {}) {\n const response = await call(\"/api/v1/chat\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n signal: sendOptions.signal,\n body: JSON.stringify({\n message,\n visitorId,\n conversationId: conversationId ?? undefined,\n context: sendOptions.context,\n fileIds: sendOptions.fileIds,\n }),\n });\n\n const state: { text: string; result: SendResult | null } = { text: \"\", result: null };\n const reader = response.body && typeof response.body.getReader === \"function\" ? response.body.getReader() : null;\n if (reader) {\n const decoder = new TextDecoder();\n let buffer = \"\";\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n const taken = takeEvents(buffer + decoder.decode(value, { stream: true }));\n buffer = taken.rest;\n applyEvents(taken.events, state, sendOptions.onDelta);\n }\n applyEvents(takeEvents(`${buffer}\\n\\n`).events, state, sendOptions.onDelta);\n } else {\n applyEvents(parseAllEvents(await response.text()), state, sendOptions.onDelta);\n }\n\n const result = state.result ?? { text: state.text, conversationId: conversationId ?? \"\" };\n if (result.conversationId) remember(result.conversationId);\n handoff = result.handoff === true;\n return result;\n },\n\n async history() {\n const params = new URLSearchParams({ visitorId });\n if (conversationId) params.set(\"conversationId\", conversationId);\n const body = (await (await call(`/api/v1/chat/history?${params.toString()}`)).json()) as {\n conversationId: string | null;\n handoff?: boolean;\n messages: ChatMessage[];\n };\n if (body.conversationId) remember(body.conversationId);\n handoff = body.handoff === true;\n teamCursor = null;\n noteTeamReplies(body.messages);\n return body.messages;\n },\n\n async updates() {\n if (!conversationId) return { handoff: false, teamTyping: false, messages: [] };\n const params = new URLSearchParams({ visitorId, conversationId });\n if (teamCursor) params.set(\"after\", teamCursor);\n const body = (await (await call(`/api/v1/chat/updates?${params.toString()}`)).json()) as Partial<ChatUpdates>;\n const messages = body.messages ?? [];\n noteTeamReplies(messages);\n handoff = body.handoff === true;\n return { handoff, teamTyping: body.teamTyping === true, messages };\n },\n\n async identify(identity) {\n await call(\"/api/v1/identify\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ ...identity, visitorId }),\n });\n },\n\n async upload(file, fileName = \"photo.jpg\") {\n const form = new FormData();\n form.append(\"file\", file, fileName);\n form.append(\"visitorId\", visitorId);\n if (conversationId) form.append(\"conversationId\", conversationId);\n const body = (await (await call(\"/api/v1/chat/upload\", { method: \"POST\", body: form })).json()) as { id: string; url: string };\n return { id: body.id, url: body.url };\n },\n\n async feedback(index, value) {\n if (!conversationId) throw new BitPalmApiError(\"bad_request\", \"There is no conversation yet.\", 400);\n await call(\"/api/v1/chat/feedback\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ visitorId, conversationId, messageIndex: index, feedback: value }),\n });\n },\n\n reset() {\n remember(null);\n handoff = false;\n teamCursor = null;\n },\n };\n}\n"],"mappings":"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","names":["parseBlock","block","data","line","event","takeEvents","buffer","events","rest","boundary","parseAllEvents","body","BitPalmApiError","code","message","status","DEFAULT_BASE_URL","defaultStorage","newVisitorId","failure","response","body","createChatClient","options","baseUrl","storage","space","read","name","write","value","visitorId","conversationId","handoff","teamCursor","noteTeamReplies","messages","headers","call","path","init","remember","id","applyEvents","events","state","onDelta","event","agentOptions","params","sendOptions","reader","decoder","buffer","done","taken","takeEvents","parseAllEvents","result","identity","file","fileName","form","index"]}
package/dist/react.cjs CHANGED
@@ -1,2 +1,13 @@
1
- "use strict";var xe=Object.defineProperty;var xt=Object.getOwnPropertyDescriptor;var St=Object.getOwnPropertyNames;var Lt=Object.prototype.hasOwnProperty;var At=(n,t)=>{for(var a in t)xe(n,a,{get:t[a],enumerable:!0})},It=(n,t,a,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let d of St(t))!Lt.call(n,d)&&d!==a&&xe(n,d,{get:()=>t[d],enumerable:!(r=xt(t,d))||r.enumerable});return n};var _t=n=>It(xe({},"__esModule",{value:!0}),n);var jt={};At(jt,{BitPalmAgent:()=>Ut});module.exports=_t(jt);var F=require("react");function st(n){if(n===!1)return"off";if(typeof n=="string"){let t=n.trim().toLowerCase();if(["false","off","0","no","none"].includes(t))return"off";if(t==="events")return"events"}return"bubble"}function rt(n,t){let a=n.createElement("div");a.setAttribute("data-bitpalm-trigger",""),a.style.cssText=`max-width:240px;background:#fff;border-radius:16px;padding:12px 32px 12px 12px;box-shadow:0 2px 20px rgba(0,0,0,0.08);cursor:pointer;z-index:${t.zIndex-1};font-family:system-ui,sans-serif;animation:_bp_fade .3s;`,a.style.position="fixed",a.style.right="24px",a.style.bottom=`${t.bottom}px`;let r=n.createElement("p");r.style.cssText="font-size:14px;color:#1f2937;margin:0;",r.textContent=t.message;let d=n.createElement("div");d.style.cssText="position:absolute;bottom:-8px;right:20px;width:0;height:0;border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid #fff;";let u=n.createElement("button");return u.type="button",u.setAttribute("aria-label","Close"),u.style.cssText="position:absolute;top:-8px;right:-8px;width:28px;height:28px;border-radius:50%;background:#fff;border:none;box-shadow:0 1px 4px rgba(0,0,0,0.1);cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:14px;color:#9ca3af;",u.textContent="\u2715",u.onclick=g=>{g.stopPropagation(),t.onDismiss()},a.onclick=()=>t.onEngage(),a.append(r,d,u),a}var Mt=["dark","dark-mode","dark-theme","theme-dark"],Ct=["light","light-mode","light-theme","theme-light"],ct=["data-theme","data-color-scheme","data-color-mode","data-mode","data-bs-theme"],dt="(prefers-color-scheme: dark)";function ae(n){return n==="light"||n==="dark"?n:"auto"}function at(n){if(!n)return null;if(Mt.some(t=>n.classList.contains(t)))return"dark";if(Ct.some(t=>n.classList.contains(t)))return"light";for(let t of ct){let a=(n.getAttribute(t)||"").toLowerCase();if(a.includes("dark"))return"dark";if(a.includes("light"))return"light"}return null}function Se(n){let t=n/255;return t<=.03928?t/12.92:((t+.055)/1.055)**2.4}function lt(n,t){if(!n)return null;let a=t.getComputedStyle(n).backgroundColor.match(/rgba?\(([^)]+)\)/);if(!a)return null;let[r,d,u,g=1]=a[1].split(/[\s,/]+/).filter(Boolean).map(Number);return[r,d,u,g].some(l=>Number.isNaN(l))||g<.5?null:.2126*Se(r)+.7152*Se(d)+.0722*Se(u)<.2?"dark":"light"}function Pt(n,t){let a=t.getComputedStyle(n.documentElement).colorScheme||"",r=n.querySelector('meta[name="color-scheme"]')?.getAttribute("content")||"",d=`${a} ${r}`.toLowerCase();return d.includes("dark")?d.includes("light")?t.matchMedia?.(dt).matches?"dark":"light":"dark":null}function G(n=document,t=window){return at(n.documentElement)??at(n.body)??lt(n.body,t)??lt(n.documentElement,t)??Pt(n,t)??"light"}function Le(n,t=document,a=window){let r=G(t,a),d=!1,u=()=>{d=!1;let c=G(t,a);c!==r&&(r=c,n(c))},g=()=>{d||(d=!0,typeof a.requestAnimationFrame=="function"?a.requestAnimationFrame(u):setTimeout(u,16))},T=typeof MutationObserver<"u"?new MutationObserver(g):null,l={attributes:!0,attributeFilter:["class","style",...ct]};T?.observe(t.documentElement,l),t.body&&T?.observe(t.body,l);let h=typeof a.matchMedia=="function"?a.matchMedia(dt):null;return h?.addEventListener?.("change",g),()=>{T?.disconnect(),h?.removeEventListener?.("change",g)}}var Bt="https://agents.bitpalm.ai",v="_bp_",kt=new Set(["password","file","checkbox","radio","submit","button","reset","image"]),Ht=8e3,mt=4096,ut=`${v}identify_signature`,ft=`${v}identify_fingerprint`,gt=`${v}identify_sent_at`,pt="0 4px 14px rgba(0,0,0,0.18)";function $t(n){return[n.external_user_id||"",n.email||"",n.phone||"",n.name||"",n.company||"",n.signature||"",n.signed_at!=null?String(n.signed_at):"",n.signature_version||"",n.identify_source||""].join("|").toLowerCase()}function m(n,t=180){return n?n.replace(/\s+/g," ").trim().slice(0,t):""}function Ot(n){return n?` ${n.toLowerCase().replace(/[_-]+/g," ").replace(/[^a-z0-9\s@.]/g," ").replace(/\s+/g," ").trim()} `:""}function N(n,t){for(let a of t)if(n.includes(a))return!0;return!1}function C(n){return/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/i.test(n)}function I(n){let t=m(n,50);if(!t)return"";let a=t.startsWith("+"),r=t.replace(/\D/g,"");return r.length<6?"":`${a?"+":""}${r.slice(0,20)}`}function ht(n){let t=m(n,140).toLowerCase();return!t||!C(t)?"":t}function W(n,t){for(let a of t){let r=n.querySelector(a),d=m(r?.value);if(d)return d}return""}function Rt(n){return m(n.getAttribute("data-bp-field")||n.getAttribute("data-bitpalm-field"),64).toLowerCase().replace(/[_\s]+/g,"-")}function Dt(n){return n.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Nt(n,t){let a=[],r=(l,h=140)=>{let c=m(l,h);c&&a.push(c)};r(t.name),r(t.id),r(t.getAttribute("autocomplete")),r(t.getAttribute("placeholder")),r(t.getAttribute("aria-label")),r(t.getAttribute("data-field")),r(t.getAttribute("data-name")),r(t.getAttribute("data-label")),r(t.getAttribute("data-bp-field")),r(t.getAttribute("data-bitpalm-field"));let d=new Set,u=l=>{let h=m(l,200);!h||d.has(h)||(d.add(h),a.push(h))};for(let l of Array.from(t.labels||[]))u(l.textContent);if(t.id){let l=n.querySelector(`label[for="${Dt(t.id)}"]`);u(l?.textContent)}let g=t.closest("label");u(g?.textContent);let T=t.getAttribute("aria-labelledby");if(T)for(let l of T.split(/\s+/)){if(!l)continue;let h=n.ownerDocument.getElementById(l);u(h?.textContent)}return a}function Wt(n){let t=m(W(n,["[data-bp-email]","[data-bitpalm-email]"]),140).toLowerCase(),a=I(W(n,["[data-bp-phone]","[data-bitpalm-phone]"])),r=m(W(n,["[data-bp-name]","[data-bitpalm-name]","[data-bp-full-name]","[data-bitpalm-full-name]"])),d=m(W(n,["[data-bp-first-name]","[data-bitpalm-first-name]"])),u=m(W(n,["[data-bp-last-name]","[data-bitpalm-last-name]"])),g=m(W(n,["[data-bp-company]","[data-bitpalm-company]"]));for(let c of Array.from(n.elements)){if(!(c instanceof HTMLInputElement||c instanceof HTMLTextAreaElement||c instanceof HTMLSelectElement)||c.disabled||c instanceof HTMLInputElement&&kt.has(c.type.toLowerCase()))continue;let y=Rt(c),U=c.hasAttribute("data-bp-email")||c.hasAttribute("data-bitpalm-email")||c.hasAttribute("data-bp-phone")||c.hasAttribute("data-bitpalm-phone")||c.hasAttribute("data-bp-name")||c.hasAttribute("data-bitpalm-name")||c.hasAttribute("data-bp-full-name")||c.hasAttribute("data-bitpalm-full-name")||c.hasAttribute("data-bp-first-name")||c.hasAttribute("data-bitpalm-first-name")||c.hasAttribute("data-bp-last-name")||c.hasAttribute("data-bitpalm-last-name")||c.hasAttribute("data-bp-company")||c.hasAttribute("data-bitpalm-company")||!!y;if(c instanceof HTMLInputElement&&c.type.toLowerCase()==="hidden"&&!U)continue;let f=m(c.value);if(!f)continue;let _=c instanceof HTMLInputElement?c.type.toLowerCase():"",s=Ot(Nt(n,c).join(" "));if(!t&&y==="email"&&C(f)){t=f.toLowerCase();continue}if(!a&&(y==="phone"||y==="tel"||y==="mobile"||y==="whatsapp")){let S=I(f);if(S){a=S;continue}}if(!g&&y==="company"){g=m(f,160);continue}if(!d&&(y==="first-name"||y==="firstname")){d=m(f,100);continue}if(!u&&(y==="last-name"||y==="lastname"||y==="surname")){u=m(f,100);continue}if(!r&&(y==="name"||y==="full-name"||y==="fullname")){!C(f)&&!I(f)&&(r=m(f,140));continue}let K=_==="email"||N(s,[" email "," e mail "," mail "," email adresse "," mailadresse "," correo "]),O=_==="tel"||N(s,[" phone "," phone number "," mobile "," tel "," telefon "," telefonnummer "," whatsapp "," handy "," kontakt "," nummer "]),le=N(s,[" company "," company name "," firma "," firmenname "," organization "," organisation "," business "," unternehmen "," agency "," brokerage "]),p=N(s,[" first name "," firstname "," given name "," givenname "," vorname "," fname "]),P=N(s,[" last name "," lastname "," family name "," familyname "," surname "," nachname "," lname "]),j=N(s,[" full name "," fullname "," contact name "," name "])&&!K&&!O;if(!t&&K&&C(f)){t=f.toLowerCase();continue}if(!a&&O){let S=I(f);if(S){a=S;continue}}if(!g&&le){g=m(f,160);continue}if(!d&&p){d=m(f,100);continue}if(!u&&P){u=m(f,100);continue}if(!r&&j&&!C(f)&&!I(f)){r=m(f,140);continue}!t&&C(f)&&(t=f.toLowerCase())}if(r&&(C(r)||I(r))&&(r=""),g&&(C(g)||I(g))&&(g=""),r||(r=m([d,u].filter(Boolean).join(" "),140)),r&&t&&r.toLowerCase()===t.toLowerCase()&&(r=""),!!!(t||a)&&!!!(r&&g))return null;let h={...r?{name:r}:{},...t?{email:t}:{},...a?{phone:a}:{},...g?{company:g}:{}};return Object.keys(h).length>0?h:null}function Ft(){if(typeof document<"u"){let n=document.documentElement.lang;if(n)return n.slice(0,2).toLowerCase()}return"en"}function Ae(n,t=1200){if(typeof window<"u"&&"requestIdleCallback"in window){window.requestIdleCallback(n,{timeout:t});return}setTimeout(n,Math.min(t,300))}function Ie(){if(typeof window>"u")return!1;let n=typeof navigator<"u"?navigator.userAgent:"";if(/Android|iPhone|iPad|iPod|IEMobile|Windows Phone|Mobile/i.test(n))return!0;let a=window.matchMedia("(pointer: coarse)").matches,r=window.matchMedia("(hover: none)").matches,d=Math.min(window.screen?.width||window.innerWidth,window.screen?.height||window.innerHeight);return a&&r&&d<=900}function yt(n){let{slug:t,locale:a=Ft(),baseUrl:r=Bt,token:d,zIndex:u=9999,autoIdentify:g=!0,launcher:T=!0}=n,l=document,h=ae(n.theme),c=h==="auto"?G():h,y=null,U=st(n.triggers),f=U,_=null,s=l.createElement("iframe");s.setAttribute("data-bitpalm-chat","");let K=`${r}/t/${t}/widget`,O=new URLSearchParams({locale:a,theme:c});d&&O.set("token",d),f==="off"&&O.set("triggers","off"),s.src=`${K}?${O.toString()}`,s.allow="clipboard-write; microphone",s.setAttribute("allowtransparency","true"),s.loading="lazy",s.style.cssText=`position:fixed;bottom:0;right:0;width:1px;height:1px;border:none;z-index:${u};background:transparent;color-scheme:normal;opacity:0;pointer-events:none;`;let le=new URL(s.src).origin,p=l.createElement("div");if(p.setAttribute("role","button"),p.setAttribute("aria-label","Chat"),p.setAttribute("data-bitpalm-launcher",""),p.style.cssText=`position:fixed;bottom:24px;right:24px;width:56px;height:56px;border-radius:50%;display:none;align-items:center;justify-content:center;cursor:pointer;z-index:${u-1};background:#171717;box-shadow:${pt};transition:transform .2s,opacity .3s;opacity:0;`,p.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7.9 20A9 9 0 1 0 4 16.1L2 22Z"/></svg>',p.onmouseenter=()=>{p.style.transform="scale(1.05)"},p.onmouseleave=()=>{p.style.transform="scale(1)"},p.onclick=()=>Y(),T&&l.body.appendChild(p),!l.getElementById("_bp_fade")){let e=l.createElement("style");e.id="_bp_fade",e.textContent="@keyframes _bp_fade{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}",l.head.appendChild(e)}let P=null,j=!1,S=!1,_e=!1,ce=!1,V=!1,X=()=>{_e||(_e=!0,l.body.appendChild(s))},Z=!1,de=0,Q={overflow:"",overscrollBehavior:""},E={overflow:"",overscrollBehavior:"",position:"",top:"",left:"",right:"",width:""},Me=()=>{if(Z||!Ie())return;let o=l.documentElement,i=l.body;de=window.scrollY||window.pageYOffset||0,Q.overflow=o.style.overflow,Q.overscrollBehavior=o.style.overscrollBehavior,E.overflow=i.style.overflow,E.overscrollBehavior=i.style.overscrollBehavior,E.position=i.style.position,E.top=i.style.top,E.left=i.style.left,E.right=i.style.right,E.width=i.style.width,o.style.overflow="hidden",o.style.overscrollBehavior="none",i.style.overflow="hidden",i.style.overscrollBehavior="none",i.style.position="fixed",i.style.top=`-${de}px`,i.style.left="0",i.style.right="0",i.style.width="100%",Z=!0},R=()=>{if(!Z)return;let e=l.documentElement,o=l.body;e.style.overflow=Q.overflow,e.style.overscrollBehavior=Q.overscrollBehavior,o.style.overflow=E.overflow,o.style.overscrollBehavior=E.overscrollBehavior,o.style.position=E.position,o.style.top=E.top,o.style.left=E.left,o.style.right=E.right,o.style.width=E.width,window.scrollTo(0,de),Z=!1},Ce=()=>{let e=Ie();s.style.display==="none"&&(s.style.display=""),e?(s.style.width="100vw",s.style.height="100dvh",s.style.left="0",s.style.top="0",s.style.bottom="0",s.style.right="0",Me()):(s.style.width="420px",s.style.height="620px",s.style.bottom="24px",s.style.right="24px",s.style.left="",s.style.top="",R()),s.style.opacity="1",s.style.pointerEvents="auto"},M=()=>{P&&(P.remove(),P=null)},ee=()=>{_!==null&&(_=null,z("trigger_hidden"))},Pe=()=>{s.contentWindow?.postMessage({type:"bitpalm-triggers",enabled:f!=="off"},"*")},te=()=>{},me=()=>{},D=!1,B=new Map;function z(e,o){let i=B.get(e);if(i)for(let b of i)try{b(o)}catch{}}let Be=e=>{if(e.origin===le){if(e.data?.type==="bitpalm-widget-config"){S=!1,j=!0,s.style.display==="none"&&(s.style.display=""),e.data.primaryColor&&(p.style.background=e.data.primaryColor,p.style.boxShadow=e.data.chatShadow==="none"?"none":pt);let o=e.data.chatButtonIconColor||"black";if(e.data.chatButtonIconSvg){p.innerHTML="";let i=l.createElement("span");i.style.cssText=`display:flex;align-items:center;justify-content:center;width:24px;height:24px;color:${o}`;let w=new DOMParser().parseFromString(e.data.chatButtonIconSvg,"image/svg+xml").querySelector("svg");w?(w.querySelectorAll("script,foreignObject").forEach(H=>H.remove()),w.querySelectorAll("*").forEach(H=>{for(let $ of[...H.attributes])($.name.startsWith("on")||$.value&&$.value.includes("javascript:"))&&H.removeAttribute($.name)}),w.setAttribute("width","24"),w.setAttribute("height","24"),w.style.display="block",i.appendChild(w)):i.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7.9 20A9 9 0 1 0 4 16.1L2 22Z"/></svg>',p.appendChild(i)}else{let i=p.querySelector("svg");i&&(i.style.stroke=o)}T&&(p.style.display="flex",requestAnimationFrame(()=>{p.style.opacity="1"})),Pe()}if(e.data?.type==="bitpalm-widget-resize"){let o=e.data.width>0,i=D;D=o,o&&!i&&z("widget_opened"),!o&&i&&z("widget_closed");let b=Ie();o?(s.style.width=b?"100vw":`${e.data.width}px`,s.style.height=b?"100dvh":`${e.data.height}px`,b?(s.style.left="0",s.style.top="0",s.style.bottom="0",s.style.right="0",Me()):R(),s.style.opacity="1",s.style.pointerEvents="auto"):(R(),s.style.width="1px",s.style.height="1px",s.style.left="",s.style.top="",s.style.opacity="0",s.style.pointerEvents="none"),p.style.display=o||!T?"none":"flex"}if(e.data?.type==="bitpalm-trigger-show"){if(S||!j||f==="off")return;let o=typeof e.data.message=="string"?e.data.message:"";if(!o)return;if(f==="events"){_=o,z("trigger_shown",{message:o,triggerId:e.data.triggerId,triggerType:e.data.triggerType});return}M(),P=rt(l,{message:o,zIndex:u,bottom:T?90:24,onDismiss:()=>{M(),s.contentWindow?.postMessage({type:"bitpalm-trigger-dismiss"},"*")},onEngage:()=>{if(M(),p.style.display="none",Ce(),X(),!ce){V=!0;return}s.contentWindow?.postMessage({type:"bitpalm-trigger-engaged",message:o},"*")}}),l.body.appendChild(P)}e.data?.type==="bitpalm-trigger-hide"&&(M(),ee()),e.data?.type==="bitpalm-request-context"&&te(),e.data?.type==="bitpalm-chat-event"&&e.data.event&&z(e.data.event,e.data.data),e.data?.type==="bitpalm-widget-blocked"&&(S=!0,j=!1,p.style.display="none",M(),ee(),R(),s.style.display="none")}};window.addEventListener("message",Be);let L=!1;try{L=localStorage.getItem(`${v}optout`)==="1"}catch{}let ne=`${v}vid`,x="";if(!L){try{x=localStorage.getItem(ne)||""}catch{}if(!x){let e=l.cookie.match(new RegExp(`(?:^|; )${ne}=([^;]+)`));x=e?decodeURIComponent(e[1]):""}x||(x=crypto.randomUUID?crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).slice(2,11)}`);try{localStorage.setItem(ne,x)}catch{}try{l.cookie=`${ne}=${encodeURIComponent(x)};path=/;max-age=31536000;SameSite=Lax`}catch{}}L||Ae(()=>{try{let e=new URLSearchParams(location.search),o={};for(let A of["utm_source","utm_medium","utm_campaign","utm_term","utm_content"]){let w=e.get(A);w&&(o[A]=w)}let i=JSON.stringify({tenant_slug:t,visitor_id:x,url:location.href,referrer:l.referrer||void 0,...Object.keys(o).length>0?{utm:o}:{}}),b=`${r}/api/widget/impression`;typeof navigator.sendBeacon=="function"?navigator.sendBeacon(b,new Blob([i],{type:"application/json"})):fetch(b,{method:"POST",body:i,headers:{"Content-Type":"application/json"},keepalive:!0}).catch(()=>{})}catch{}},2e3);let ue="",fe="",ge=0;try{ue=sessionStorage.getItem(ut)||"",fe=sessionStorage.getItem(ft)||"";let e=parseInt(sessionStorage.getItem(gt)||"0",10);Number.isFinite(e)&&e>0&&(ge=e)}catch{}let ke=(e,o="")=>{if(L||!x)return;let i={},b=m(e.name,140),A=ht(e.email),w=I(e.phone),H=m(e.company,160),$=m(e.external_user_id,140),nt=m(e.signature,260),we=Number(e.signed_at);if(b&&(i.name=b),A&&(i.email=A),w&&(i.phone=w),H&&(i.company=H),$&&(i.external_user_id=$),nt&&(i.signature=nt),Number.isFinite(we)&&we>0&&(i.signed_at=Math.floor(we)),(e.signature_version==="v1"||i.signature)&&(i.signature_version="v1"),(e.identify_source==="manual"||e.identify_source==="form")&&(i.identify_source=e.identify_source),!i.name&&!i.email&&!i.phone&&!i.company&&!i.external_user_id)return;let re=$t(i),Ee=[o.toLowerCase(),re].filter(Boolean).join("|"),Te=Date.now();if(!(Te-ge<Ht&&(Ee===ue||re===fe))){ue=Ee,fe=re,ge=Te;try{sessionStorage.setItem(ut,Ee),sessionStorage.setItem(ft,re),sessionStorage.setItem(gt,String(Te))}catch{}try{let ot=JSON.stringify({tenant_slug:t,visitor_id:x,url:location.href,referrer:l.referrer||void 0,...i}),it=`${r}/api/widget/identify`;typeof navigator.sendBeacon=="function"?navigator.sendBeacon(it,new Blob([ot],{type:"application/json"})):fetch(it,{method:"POST",body:ot,headers:{"Content-Type":"application/json"},keepalive:!0}).catch(()=>{})}catch{}}},He=e=>{if(L||!g||!x)return;let o=e.target instanceof HTMLFormElement?e.target:e.target instanceof Element?e.target.closest("form"):null;if(!(o instanceof HTMLFormElement))return;let i=(o.getAttribute("data-bp-identify")||o.getAttribute("data-bitpalm-identify")||"").toLowerCase();if(i==="off"||i==="false"||i==="0")return;let b=Wt(o);if(!b)return;let A=[o.getAttribute("id")||"",o.getAttribute("name")||"",o.getAttribute("action")||""].join("|");ke({...b,identify_source:"form"},A)};!L&&g&&l.addEventListener("submit",He,!0);let q=parseInt(sessionStorage.getItem(`${v}pages`)||"0")+1;sessionStorage.setItem(`${v}pages`,String(q));let k=JSON.parse(sessionStorage.getItem(`${v}hist`)||"[]");k.push(location.href),k.length>20&&(k=k.slice(-20)),sessionStorage.setItem(`${v}hist`,JSON.stringify(k));let $e=Date.now(),oe=parseInt(sessionStorage.getItem(`${v}site_start`)||"0");oe||(oe=$e,sessionStorage.setItem(`${v}site_start`,String(oe)));let Oe=[];te=()=>{let e=!1;try{e=!!localStorage.getItem(`${v}visited`)}catch{e=!1}if(s.contentWindow?.postMessage({type:"bitpalm-parent-context",url:location.href,title:l.title,returning:e,pageCount:q,pageHistory:k,loadedAt:$e,siteStart:oe,locale:a,visitorId:L?"":x},"*"),Je(),!e&&!L)try{localStorage.setItem(`${v}visited`,"1")}catch{}},s.addEventListener("load",()=>{ce=!0,te(),[120,450,1100].forEach(e=>{let o=setTimeout(()=>te(),e);Oe.push(o)}),V&&(V=!1,me())}),l.readyState==="loading"?l.addEventListener("DOMContentLoaded",()=>Ae(X,1600),{once:!0}):Ae(X,1600);let Re=history.pushState.bind(history),De=history.replaceState.bind(history),ie=()=>{q++,sessionStorage.setItem(`${v}pages`,String(q));let e=JSON.parse(sessionStorage.getItem(`${v}hist`)||"[]");if(e.push(location.href),e.length>20&&e.splice(0,e.length-20),k=e,sessionStorage.setItem(`${v}hist`,JSON.stringify(e)),s.contentWindow?.postMessage({type:"bitpalm-page-change",url:location.href,title:l.title,pageCount:q,pageHistory:e,loadedAt:Date.now()},"*"),!L)try{let o=JSON.stringify({tenant_slug:t,visitor_id:x,url:location.href}),i=`${r}/api/widget/impression`;typeof navigator.sendBeacon=="function"?navigator.sendBeacon(i,new Blob([o],{type:"application/json"})):fetch(i,{method:"POST",body:o,headers:{"Content-Type":"application/json"},keepalive:!0}).catch(()=>{})}catch{}};history.pushState=function(...e){Re(...e),ie()},history.replaceState=function(...e){De(...e),ie()},window.addEventListener("popstate",ie);let Ne=-1,pe,We=()=>{clearTimeout(pe),pe=setTimeout(()=>{let e=Math.max(l.documentElement.scrollHeight,l.body.scrollHeight)-window.innerHeight,o=e>0?Math.round(window.scrollY/e*100):100;o!==Ne&&(Ne=o,s.contentWindow?.postMessage({type:"bitpalm-scroll-depth",percent:o},"*"))},500)};window.addEventListener("scroll",We,{passive:!0});let Fe=e=>{e.clientY<=0&&s.contentWindow?.postMessage({type:"bitpalm-exit-intent"},"*")};l.addEventListener("mouseout",Fe);let he,Ue=!1,ye=()=>{clearTimeout(he),!Ue&&(he=setTimeout(()=>{Ue=!0,s.contentWindow?.postMessage({type:"bitpalm-inactivity"},"*")},15e3))},je=["mousemove","keydown","scroll","touchstart"];je.forEach(e=>l.addEventListener(e,ye,{passive:!0})),ye(),me=()=>{s.contentWindow?.postMessage({type:"bitpalm-open"},"*");let e=s.src.split("#")[0];s.src=`${e}#bp-open-${Date.now()}`};let Y=()=>{if(p.style.display="none",M(),Ce(),X(),!ce){V=!0;return}if(_!==null){let e=_;ee(),s.contentWindow?.postMessage({type:"bitpalm-trigger-engaged",message:e},"*");return}me()},ze=e=>{f=e,e==="off"&&(M(),ee()),Pe()},bt=()=>ze("off"),vt=()=>ze(U==="off"?"bubble":U),be=()=>{R(),s.contentWindow?.postMessage({type:"bitpalm-close"},"*")},qe=e=>{!e||typeof e!="object"||ke({external_user_id:m(e.externalUserId,140)||void 0,name:m(e.name,140)||void 0,email:ht(e.email)||void 0,phone:I(e.phone)||void 0,company:m(e.company,160)||void 0,signature:m(e.signature,260)||void 0,signed_at:Number.isFinite(Number(e.signedAt))?Math.floor(Number(e.signedAt)):void 0,signature_version:e.signatureVersion==="v1"?"v1":void 0,identify_source:"manual"},"manual")},wt=()=>{D?be():Y()},Et=()=>D,Ye=e=>{if(!e||typeof e!="string")return;let o=e.trim().slice(0,1e4);o&&(D||Y(),setTimeout(()=>{s.contentWindow?.postMessage({type:"bitpalm-send-message",message:o},"*")},D?50:500))};function Je(){s.contentWindow?.postMessage({type:"bitpalm-theme",theme:c},"*")}let se=e=>{e!==c&&(c=e,Je())},Ge=e=>{h=ae(e),y?.(),y=null,h==="auto"?(y=Le(se),se(G())):se(h)};h==="auto"&&(y=Le(se));let Ke=e=>{let o=e.detail;if(!o||typeof o!="object")return;let i=m(o.slug,120);i&&i!==t||Ge(ae(o.theme))};window.addEventListener("bitpalm-theme",Ke);let J={},Ve=e=>{if(!e||typeof e!="object"||Array.isArray(e))return;J={...J,...e};let o=JSON.stringify(J);o.length>mt&&console.warn(`[BitPalm] Custom context exceeds ${mt} bytes (${o.length}). It may be truncated.`),s.contentWindow?.postMessage({type:"bitpalm-custom-context",data:J},"*")},Tt=()=>{J={},s.contentWindow?.postMessage({type:"bitpalm-custom-context",data:{}},"*")},Xe=e=>{let i=e.detail;if(!i||typeof i!="object")return;let b=m(i.slug,120);if(b&&b!==t)return;let{slug:A,...w}=i;Ve(w)};window.addEventListener("bitpalm-context",Xe);let Ze=e=>{let i=e.detail;if(!i||typeof i!="object")return;let b=m(i.slug,120);b&&b!==t||qe(i)};window.addEventListener("bitpalm-identify",Ze);let ve=e=>{let o=e.detail,i=m(o?.slug,120);return!i||i===t},Qe=e=>{ve(e)&&Y()},et=e=>{ve(e)&&be()},tt=e=>{if(!ve(e))return;let o=e.detail?.message;typeof o=="string"&&Ye(o)};return window.addEventListener("bitpalm-open",Qe),window.addEventListener("bitpalm-close",et),window.addEventListener("bitpalm-send",tt),{open:Y,close:be,toggle:wt,isOpen:Et,identify:qe,context:Ve,resetContext:Tt,send:Ye,on:(e,o)=>(B.has(e)||B.set(e,new Set),B.get(e).add(o),()=>B.get(e)?.delete(o)),off:(e,o)=>{B.get(e)?.delete(o)},setTheme:Ge,disableTriggers:bt,enableTriggers:vt,destroy:()=>{window.removeEventListener("message",Be),window.removeEventListener("scroll",We),window.removeEventListener("popstate",ie),l.removeEventListener("mouseout",Fe),l.removeEventListener("submit",He,!0),je.forEach(e=>l.removeEventListener(e,ye)),clearTimeout(pe),clearTimeout(he),Oe.forEach(e=>clearTimeout(e)),history.pushState=Re,history.replaceState=De,window.removeEventListener("bitpalm-identify",Ze),window.removeEventListener("bitpalm-context",Xe),window.removeEventListener("bitpalm-theme",Ke),window.removeEventListener("bitpalm-open",Qe),window.removeEventListener("bitpalm-close",et),window.removeEventListener("bitpalm-send",tt),y?.(),B.clear(),R(),M(),p.remove(),s.remove()}}}function Ut(n){let t=(0,F.useRef)(null),a=(0,F.useRef)(!1);return(0,F.useEffect)(()=>{t.current?.setTheme(n.theme??"auto")},[n.theme]),(0,F.useEffect)(()=>{if(a.current)return;a.current=!0;let{onReady:r,...d}=n;return t.current=yt(d),r?.(t.current),()=>{t.current?.destroy(),t.current=null,a.current=!1}},[]),null}0&&(module.exports={BitPalmAgent});
1
+ "use strict";var Ie=Object.defineProperty;var kt=Object.getOwnPropertyDescriptor;var Pt=Object.getOwnPropertyNames;var _t=Object.prototype.hasOwnProperty;var Mt=(n,t)=>{for(var i in t)Ie(n,i,{get:t[i],enumerable:!0})},Bt=(n,t,i,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let c of Pt(t))!_t.call(n,c)&&c!==i&&Ie(n,c,{get:()=>t[c],enumerable:!(r=kt(t,c))||r.enumerable});return n};var $t=n=>Bt(Ie({},"__esModule",{value:!0}),n);var rn={};Mt(rn,{BitPalmAgent:()=>Zt,BitPalmApiError:()=>H,useBitPalmChat:()=>on});module.exports=$t(rn);var S=require("react");function at(n){if(n===!1)return"off";if(typeof n=="string"){let t=n.trim().toLowerCase();if(["false","off","0","no","none"].includes(t))return"off";if(t==="events")return"events"}return"bubble"}function lt(n,t){let i=n.createElement("div");i.setAttribute("data-bitpalm-trigger",""),i.style.cssText=`max-width:240px;background:#fff;border-radius:16px;padding:12px 32px 12px 12px;box-shadow:0 2px 20px rgba(0,0,0,0.08);cursor:pointer;z-index:${t.zIndex-1};font-family:system-ui,sans-serif;animation:_bp_fade .3s;`,i.style.position="fixed",i.style.right="24px",i.style.bottom=`${t.bottom}px`;let r=n.createElement("p");r.style.cssText="font-size:14px;color:#1f2937;margin:0;",r.textContent=t.message;let c=n.createElement("div");c.style.cssText="position:absolute;bottom:-8px;right:20px;width:0;height:0;border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid #fff;";let f=n.createElement("button");return f.type="button",f.setAttribute("aria-label","Close"),f.style.cssText="position:absolute;top:-8px;right:-8px;width:28px;height:28px;border-radius:50%;background:#fff;border:none;box-shadow:0 1px 4px rgba(0,0,0,0.1);cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:14px;color:#9ca3af;",f.textContent="\u2715",f.onclick=m=>{m.stopPropagation(),t.onDismiss()},i.onclick=()=>t.onEngage(),i.append(r,c,f),i}var Ot=["dark","dark-mode","dark-theme","theme-dark"],Rt=["light","light-mode","light-theme","theme-light"],ut=["data-theme","data-color-scheme","data-color-mode","data-mode","data-bs-theme"],mt="(prefers-color-scheme: dark)";function ue(n){return n==="light"||n==="dark"?n:"auto"}function ct(n){if(!n)return null;if(Ot.some(t=>n.classList.contains(t)))return"dark";if(Rt.some(t=>n.classList.contains(t)))return"light";for(let t of ut){let i=(n.getAttribute(t)||"").toLowerCase();if(i.includes("dark"))return"dark";if(i.includes("light"))return"light"}return null}function Ae(n){let t=n/255;return t<=.03928?t/12.92:((t+.055)/1.055)**2.4}function dt(n,t){if(!n)return null;let i=t.getComputedStyle(n).backgroundColor.match(/rgba?\(([^)]+)\)/);if(!i)return null;let[r,c,f,m=1]=i[1].split(/[\s,/]+/).filter(Boolean).map(Number);return[r,c,f,m].some(l=>Number.isNaN(l))||m<.5?null:.2126*Ae(r)+.7152*Ae(c)+.0722*Ae(f)<.2?"dark":"light"}function Ht(n,t){let i=t.getComputedStyle(n.documentElement).colorScheme||"",r=n.querySelector('meta[name="color-scheme"]')?.getAttribute("content")||"",c=`${i} ${r}`.toLowerCase();return c.includes("dark")?c.includes("light")?t.matchMedia?.(mt).matches?"dark":"light":"dark":null}function ne(n=document,t=window){return ct(n.documentElement)??ct(n.body)??dt(n.body,t)??dt(n.documentElement,t)??Ht(n,t)??"light"}function Le(n,t=document,i=window){let r=ne(t,i),c=!1,f=()=>{c=!1;let u=ne(t,i);u!==r&&(r=u,n(u))},m=()=>{c||(c=!0,typeof i.requestAnimationFrame=="function"?i.requestAnimationFrame(f):setTimeout(f,16))},y=typeof MutationObserver<"u"?new MutationObserver(m):null,l={attributes:!0,attributeFilter:["class","style",...ut]};y?.observe(t.documentElement,l),t.body&&y?.observe(t.body,l);let h=typeof i.matchMedia=="function"?i.matchMedia(mt):null;return h?.addEventListener?.("change",m),()=>{y?.disconnect(),h?.removeEventListener?.("change",m)}}var Dt="https://agents.bitpalm.ai",L="_bp_",Ut=new Set(["password","file","checkbox","radio","submit","button","reset","image"]),Nt=8e3,ft=4096,gt=`${L}identify_signature`,pt=`${L}identify_fingerprint`,ht=`${L}identify_sent_at`,yt="0 4px 14px rgba(0,0,0,0.18)";function Wt(n){return[n.external_user_id||"",n.email||"",n.phone||"",n.name||"",n.company||"",n.signature||"",n.signed_at!=null?String(n.signed_at):"",n.signature_version||"",n.identify_source||""].join("|").toLowerCase()}function p(n,t=180){return n?n.replace(/\s+/g," ").trim().slice(0,t):""}function jt(n){return n?` ${n.toLowerCase().replace(/[_-]+/g," ").replace(/[^a-z0-9\s@.]/g," ").replace(/\s+/g," ").trim()} `:""}function K(n,t){for(let i of t)if(n.includes(i))return!0;return!1}function F(n){return/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/i.test(n)}function N(n){let t=p(n,50);if(!t)return"";let i=t.startsWith("+"),r=t.replace(/\D/g,"");return r.length<6?"":`${i?"+":""}${r.slice(0,20)}`}function bt(n){let t=p(n,140).toLowerCase();return!t||!F(t)?"":t}function Q(n,t){for(let i of t){let r=n.querySelector(i),c=p(r?.value);if(c)return c}return""}function Ft(n){return p(n.getAttribute("data-bp-field")||n.getAttribute("data-bitpalm-field"),64).toLowerCase().replace(/[_\s]+/g,"-")}function qt(n){return n.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function zt(n,t){let i=[],r=(l,h=140)=>{let u=p(l,h);u&&i.push(u)};r(t.name),r(t.id),r(t.getAttribute("autocomplete")),r(t.getAttribute("placeholder")),r(t.getAttribute("aria-label")),r(t.getAttribute("data-field")),r(t.getAttribute("data-name")),r(t.getAttribute("data-label")),r(t.getAttribute("data-bp-field")),r(t.getAttribute("data-bitpalm-field"));let c=new Set,f=l=>{let h=p(l,200);!h||c.has(h)||(c.add(h),i.push(h))};for(let l of Array.from(t.labels||[]))f(l.textContent);if(t.id){let l=n.querySelector(`label[for="${qt(t.id)}"]`);f(l?.textContent)}let m=t.closest("label");f(m?.textContent);let y=t.getAttribute("aria-labelledby");if(y)for(let l of y.split(/\s+/)){if(!l)continue;let h=n.ownerDocument.getElementById(l);f(h?.textContent)}return i}function Yt(n){let t=p(Q(n,["[data-bp-email]","[data-bitpalm-email]"]),140).toLowerCase(),i=N(Q(n,["[data-bp-phone]","[data-bitpalm-phone]"])),r=p(Q(n,["[data-bp-name]","[data-bitpalm-name]","[data-bp-full-name]","[data-bitpalm-full-name]"])),c=p(Q(n,["[data-bp-first-name]","[data-bitpalm-first-name]"])),f=p(Q(n,["[data-bp-last-name]","[data-bitpalm-last-name]"])),m=p(Q(n,["[data-bp-company]","[data-bitpalm-company]"]));for(let u of Array.from(n.elements)){if(!(u instanceof HTMLInputElement||u instanceof HTMLTextAreaElement||u instanceof HTMLSelectElement)||u.disabled||u instanceof HTMLInputElement&&Ut.has(u.type.toLowerCase()))continue;let v=Ft(u),k=u.hasAttribute("data-bp-email")||u.hasAttribute("data-bitpalm-email")||u.hasAttribute("data-bp-phone")||u.hasAttribute("data-bitpalm-phone")||u.hasAttribute("data-bp-name")||u.hasAttribute("data-bitpalm-name")||u.hasAttribute("data-bp-full-name")||u.hasAttribute("data-bitpalm-full-name")||u.hasAttribute("data-bp-first-name")||u.hasAttribute("data-bitpalm-first-name")||u.hasAttribute("data-bp-last-name")||u.hasAttribute("data-bitpalm-last-name")||u.hasAttribute("data-bp-company")||u.hasAttribute("data-bitpalm-company")||!!v;if(u instanceof HTMLInputElement&&u.type.toLowerCase()==="hidden"&&!k)continue;let g=p(u.value);if(!g)continue;let A=u instanceof HTMLInputElement?u.type.toLowerCase():"",o=jt(zt(n,u).join(" "));if(!t&&v==="email"&&F(g)){t=g.toLowerCase();continue}if(!i&&(v==="phone"||v==="tel"||v==="mobile"||v==="whatsapp")){let E=N(g);if(E){i=E;continue}}if(!m&&v==="company"){m=p(g,160);continue}if(!c&&(v==="first-name"||v==="firstname")){c=p(g,100);continue}if(!f&&(v==="last-name"||v==="lastname"||v==="surname")){f=p(g,100);continue}if(!r&&(v==="name"||v==="full-name"||v==="fullname")){!F(g)&&!N(g)&&(r=p(g,140));continue}let d=A==="email"||K(o,[" email "," e mail "," mail "," email adresse "," mailadresse "," correo "]),w=A==="tel"||K(o,[" phone "," phone number "," mobile "," tel "," telefon "," telefonnummer "," whatsapp "," handy "," kontakt "," nummer "]),x=K(o,[" company "," company name "," firma "," firmenname "," organization "," organisation "," business "," unternehmen "," agency "," brokerage "]),b=K(o,[" first name "," firstname "," given name "," givenname "," vorname "," fname "]),M=K(o,[" last name "," lastname "," family name "," familyname "," surname "," nachname "," lname "]),I=K(o,[" full name "," fullname "," contact name "," name "])&&!d&&!w;if(!t&&d&&F(g)){t=g.toLowerCase();continue}if(!i&&w){let E=N(g);if(E){i=E;continue}}if(!m&&x){m=p(g,160);continue}if(!c&&b){c=p(g,100);continue}if(!f&&M){f=p(g,100);continue}if(!r&&I&&!F(g)&&!N(g)){r=p(g,140);continue}!t&&F(g)&&(t=g.toLowerCase())}if(r&&(F(r)||N(r))&&(r=""),m&&(F(m)||N(m))&&(m=""),r||(r=p([c,f].filter(Boolean).join(" "),140)),r&&t&&r.toLowerCase()===t.toLowerCase()&&(r=""),!!!(t||i)&&!!!(r&&m))return null;let h={...r?{name:r}:{},...t?{email:t}:{},...i?{phone:i}:{},...m?{company:m}:{}};return Object.keys(h).length>0?h:null}function Jt(){if(typeof document<"u"){let n=document.documentElement.lang;if(n)return n.slice(0,2).toLowerCase()}return"en"}function ke(n,t=1200){if(typeof window<"u"&&"requestIdleCallback"in window){window.requestIdleCallback(n,{timeout:t});return}setTimeout(n,Math.min(t,300))}function Pe(){if(typeof window>"u")return!1;let n=typeof navigator<"u"?navigator.userAgent:"";if(/Android|iPhone|iPad|iPod|IEMobile|Windows Phone|Mobile/i.test(n))return!0;let i=window.matchMedia("(pointer: coarse)").matches,r=window.matchMedia("(hover: none)").matches,c=Math.min(window.screen?.width||window.innerWidth,window.screen?.height||window.innerHeight);return i&&r&&c<=900}function vt(n){let{slug:t,locale:i=Jt(),baseUrl:r=Dt,token:c,zIndex:f=9999,autoIdentify:m=!0,launcher:y=!0}=n,l=document,h=ue(n.theme),u=h==="auto"?ne():h,v=null,k=at(n.triggers),g=k,A=null,o=l.createElement("iframe");o.setAttribute("data-bitpalm-chat","");let d=`${r}/t/${t}/widget`,w=new URLSearchParams({locale:i,theme:u});c&&w.set("token",c),g==="off"&&w.set("triggers","off"),o.src=`${d}?${w.toString()}`,o.allow="clipboard-write; microphone",o.setAttribute("allowtransparency","true"),o.loading="lazy",o.style.cssText=`position:fixed;bottom:0;right:0;width:1px;height:1px;border:none;z-index:${f};background:transparent;color-scheme:normal;opacity:0;pointer-events:none;`;let x=new URL(o.src).origin,b=l.createElement("div");if(b.setAttribute("role","button"),b.setAttribute("aria-label","Chat"),b.setAttribute("data-bitpalm-launcher",""),b.style.cssText=`position:fixed;bottom:24px;right:24px;width:56px;height:56px;border-radius:50%;display:none;align-items:center;justify-content:center;cursor:pointer;z-index:${f-1};background:#171717;box-shadow:${yt};transition:transform .2s,opacity .3s;opacity:0;`,b.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7.9 20A9 9 0 1 0 4 16.1L2 22Z"/></svg>',b.onmouseenter=()=>{b.style.transform="scale(1.05)"},b.onmouseleave=()=>{b.style.transform="scale(1)"},b.onclick=()=>ee(),y&&l.body.appendChild(b),!l.getElementById("_bp_fade")){let e=l.createElement("style");e.id="_bp_fade",e.textContent="@keyframes _bp_fade{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}",l.head.appendChild(e)}let M=null,I=!1,E=!1,P=!1,C=!1,B=!1,R=()=>{P||(P=!0,l.body.appendChild(o))},W=!1,fe=0,oe={overflow:"",overscrollBehavior:""},$={overflow:"",overscrollBehavior:"",position:"",top:"",left:"",right:"",width:""},_e=()=>{if(W||!Pe())return;let s=l.documentElement,a=l.body;fe=window.scrollY||window.pageYOffset||0,oe.overflow=s.style.overflow,oe.overscrollBehavior=s.style.overscrollBehavior,$.overflow=a.style.overflow,$.overscrollBehavior=a.style.overscrollBehavior,$.position=a.style.position,$.top=a.style.top,$.left=a.style.left,$.right=a.style.right,$.width=a.style.width,s.style.overflow="hidden",s.style.overscrollBehavior="none",a.style.overflow="hidden",a.style.overscrollBehavior="none",a.style.position="fixed",a.style.top=`-${fe}px`,a.style.left="0",a.style.right="0",a.style.width="100%",W=!0},V=()=>{if(!W)return;let e=l.documentElement,s=l.body;e.style.overflow=oe.overflow,e.style.overscrollBehavior=oe.overscrollBehavior,s.style.overflow=$.overflow,s.style.overscrollBehavior=$.overscrollBehavior,s.style.position=$.position,s.style.top=$.top,s.style.left=$.left,s.style.right=$.right,s.style.width=$.width,window.scrollTo(0,fe),W=!1},Me=()=>{let e=Pe();o.style.display==="none"&&(o.style.display=""),e?(o.style.width="100vw",o.style.height="100dvh",o.style.left="0",o.style.top="0",o.style.bottom="0",o.style.right="0",_e()):(o.style.width="420px",o.style.height="620px",o.style.bottom="24px",o.style.right="24px",o.style.left="",o.style.top="",V()),o.style.opacity="1",o.style.pointerEvents="auto"},j=()=>{M&&(M.remove(),M=null)},ie=()=>{A!==null&&(A=null,X("trigger_hidden"))},Be=()=>{o.contentWindow?.postMessage({type:"bitpalm-triggers",enabled:g!=="off"},"*")},re=()=>{},ge=()=>{},G=!1,q=new Map;function X(e,s){let a=q.get(e);if(a)for(let T of a)try{T(s)}catch{}}let $e=e=>{if(e.origin===x){if(e.data?.type==="bitpalm-widget-config"){E=!1,I=!0,o.style.display==="none"&&(o.style.display=""),e.data.primaryColor&&(b.style.background=e.data.primaryColor,b.style.boxShadow=e.data.chatShadow==="none"?"none":yt);let s=e.data.chatButtonIconColor||"black";if(e.data.chatButtonIconSvg){b.innerHTML="";let a=l.createElement("span");a.style.cssText=`display:flex;align-items:center;justify-content:center;width:24px;height:24px;color:${s}`;let _=new DOMParser().parseFromString(e.data.chatButtonIconSvg,"image/svg+xml").querySelector("svg");_?(_.querySelectorAll("script,foreignObject").forEach(Y=>Y.remove()),_.querySelectorAll("*").forEach(Y=>{for(let J of[...Y.attributes])(J.name.startsWith("on")||J.value&&J.value.includes("javascript:"))&&Y.removeAttribute(J.name)}),_.setAttribute("width","24"),_.setAttribute("height","24"),_.style.display="block",a.appendChild(_)):a.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7.9 20A9 9 0 1 0 4 16.1L2 22Z"/></svg>',b.appendChild(a)}else{let a=b.querySelector("svg");a&&(a.style.stroke=s)}y&&(b.style.display="flex",requestAnimationFrame(()=>{b.style.opacity="1"})),Be()}if(e.data?.type==="bitpalm-widget-resize"){let s=e.data.width>0,a=G;G=s,s&&!a&&X("widget_opened"),!s&&a&&X("widget_closed");let T=Pe();s?(o.style.width=T?"100vw":`${e.data.width}px`,o.style.height=T?"100dvh":`${e.data.height}px`,T?(o.style.left="0",o.style.top="0",o.style.bottom="0",o.style.right="0",_e()):V(),o.style.opacity="1",o.style.pointerEvents="auto"):(V(),o.style.width="1px",o.style.height="1px",o.style.left="",o.style.top="",o.style.opacity="0",o.style.pointerEvents="none"),b.style.display=s||!y?"none":"flex"}if(e.data?.type==="bitpalm-trigger-show"){if(E||!I||g==="off")return;let s=typeof e.data.message=="string"?e.data.message:"";if(!s)return;if(g==="events"){A=s,X("trigger_shown",{message:s,triggerId:e.data.triggerId,triggerType:e.data.triggerType});return}j(),M=lt(l,{message:s,zIndex:f,bottom:y?90:24,onDismiss:()=>{j(),o.contentWindow?.postMessage({type:"bitpalm-trigger-dismiss"},"*")},onEngage:()=>{if(j(),b.style.display="none",Me(),R(),!C){B=!0;return}o.contentWindow?.postMessage({type:"bitpalm-trigger-engaged",message:s},"*")}}),l.body.appendChild(M)}e.data?.type==="bitpalm-trigger-hide"&&(j(),ie()),e.data?.type==="bitpalm-request-context"&&re(),e.data?.type==="bitpalm-chat-event"&&e.data.event&&X(e.data.event,e.data.data),e.data?.type==="bitpalm-widget-blocked"&&(E=!0,I=!1,b.style.display="none",j(),ie(),V(),o.style.display="none")}};window.addEventListener("message",$e);let D=!1;try{D=localStorage.getItem(`${L}optout`)==="1"}catch{}let se=`${L}vid`,O="";if(!D){try{O=localStorage.getItem(se)||""}catch{}if(!O){let e=l.cookie.match(new RegExp(`(?:^|; )${se}=([^;]+)`));O=e?decodeURIComponent(e[1]):""}O||(O=crypto.randomUUID?crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).slice(2,11)}`);try{localStorage.setItem(se,O)}catch{}try{l.cookie=`${se}=${encodeURIComponent(O)};path=/;max-age=31536000;SameSite=Lax`}catch{}}D||ke(()=>{try{let e=new URLSearchParams(location.search),s={};for(let U of["utm_source","utm_medium","utm_campaign","utm_term","utm_content"]){let _=e.get(U);_&&(s[U]=_)}let a=JSON.stringify({tenant_slug:t,visitor_id:O,url:location.href,referrer:l.referrer||void 0,...Object.keys(s).length>0?{utm:s}:{}}),T=`${r}/api/widget/impression`;typeof navigator.sendBeacon=="function"?navigator.sendBeacon(T,new Blob([a],{type:"application/json"})):fetch(T,{method:"POST",body:a,headers:{"Content-Type":"application/json"},keepalive:!0}).catch(()=>{})}catch{}},2e3);let pe="",he="",ye=0;try{pe=sessionStorage.getItem(gt)||"",he=sessionStorage.getItem(pt)||"";let e=parseInt(sessionStorage.getItem(ht)||"0",10);Number.isFinite(e)&&e>0&&(ye=e)}catch{}let Oe=(e,s="")=>{if(D||!O)return;let a={},T=p(e.name,140),U=bt(e.email),_=N(e.phone),Y=p(e.company,160),J=p(e.external_user_id,140),it=p(e.signature,260),Se=Number(e.signed_at);if(T&&(a.name=T),U&&(a.email=U),_&&(a.phone=_),Y&&(a.company=Y),J&&(a.external_user_id=J),it&&(a.signature=it),Number.isFinite(Se)&&Se>0&&(a.signed_at=Math.floor(Se)),(e.signature_version==="v1"||a.signature)&&(a.signature_version="v1"),(e.identify_source==="manual"||e.identify_source==="form")&&(a.identify_source=e.identify_source),!a.name&&!a.email&&!a.phone&&!a.company&&!a.external_user_id)return;let de=Wt(a),Te=[s.toLowerCase(),de].filter(Boolean).join("|"),Ce=Date.now();if(!(Ce-ye<Nt&&(Te===pe||de===he))){pe=Te,he=de,ye=Ce;try{sessionStorage.setItem(gt,Te),sessionStorage.setItem(pt,de),sessionStorage.setItem(ht,String(Ce))}catch{}try{let rt=JSON.stringify({tenant_slug:t,visitor_id:O,url:location.href,referrer:l.referrer||void 0,...a}),st=`${r}/api/widget/identify`;typeof navigator.sendBeacon=="function"?navigator.sendBeacon(st,new Blob([rt],{type:"application/json"})):fetch(st,{method:"POST",body:rt,headers:{"Content-Type":"application/json"},keepalive:!0}).catch(()=>{})}catch{}}},Re=e=>{if(D||!m||!O)return;let s=e.target instanceof HTMLFormElement?e.target:e.target instanceof Element?e.target.closest("form"):null;if(!(s instanceof HTMLFormElement))return;let a=(s.getAttribute("data-bp-identify")||s.getAttribute("data-bitpalm-identify")||"").toLowerCase();if(a==="off"||a==="false"||a==="0")return;let T=Yt(s);if(!T)return;let U=[s.getAttribute("id")||"",s.getAttribute("name")||"",s.getAttribute("action")||""].join("|");Oe({...T,identify_source:"form"},U)};!D&&m&&l.addEventListener("submit",Re,!0);let Z=parseInt(sessionStorage.getItem(`${L}pages`)||"0")+1;sessionStorage.setItem(`${L}pages`,String(Z));let z=JSON.parse(sessionStorage.getItem(`${L}hist`)||"[]");z.push(location.href),z.length>20&&(z=z.slice(-20)),sessionStorage.setItem(`${L}hist`,JSON.stringify(z));let He=Date.now(),ae=parseInt(sessionStorage.getItem(`${L}site_start`)||"0");ae||(ae=He,sessionStorage.setItem(`${L}site_start`,String(ae)));let De=[];re=()=>{let e=!1;try{e=!!localStorage.getItem(`${L}visited`)}catch{e=!1}if(o.contentWindow?.postMessage({type:"bitpalm-parent-context",url:location.href,title:l.title,returning:e,pageCount:Z,pageHistory:z,loadedAt:He,siteStart:ae,locale:i,visitorId:D?"":O},"*"),Ge(),!e&&!D)try{localStorage.setItem(`${L}visited`,"1")}catch{}},o.addEventListener("load",()=>{C=!0,re(),[120,450,1100].forEach(e=>{let s=setTimeout(()=>re(),e);De.push(s)}),B&&(B=!1,ge())}),l.readyState==="loading"?l.addEventListener("DOMContentLoaded",()=>ke(R,1600),{once:!0}):ke(R,1600);let Ue=history.pushState.bind(history),Ne=history.replaceState.bind(history),le=()=>{Z++,sessionStorage.setItem(`${L}pages`,String(Z));let e=JSON.parse(sessionStorage.getItem(`${L}hist`)||"[]");if(e.push(location.href),e.length>20&&e.splice(0,e.length-20),z=e,sessionStorage.setItem(`${L}hist`,JSON.stringify(e)),o.contentWindow?.postMessage({type:"bitpalm-page-change",url:location.href,title:l.title,pageCount:Z,pageHistory:e,loadedAt:Date.now()},"*"),!D)try{let s=JSON.stringify({tenant_slug:t,visitor_id:O,url:location.href}),a=`${r}/api/widget/impression`;typeof navigator.sendBeacon=="function"?navigator.sendBeacon(a,new Blob([s],{type:"application/json"})):fetch(a,{method:"POST",body:s,headers:{"Content-Type":"application/json"},keepalive:!0}).catch(()=>{})}catch{}};history.pushState=function(...e){Ue(...e),le()},history.replaceState=function(...e){Ne(...e),le()},window.addEventListener("popstate",le);let We=-1,be,je=()=>{clearTimeout(be),be=setTimeout(()=>{let e=Math.max(l.documentElement.scrollHeight,l.body.scrollHeight)-window.innerHeight,s=e>0?Math.round(window.scrollY/e*100):100;s!==We&&(We=s,o.contentWindow?.postMessage({type:"bitpalm-scroll-depth",percent:s},"*"))},500)};window.addEventListener("scroll",je,{passive:!0});let Fe=e=>{e.clientY<=0&&o.contentWindow?.postMessage({type:"bitpalm-exit-intent"},"*")};l.addEventListener("mouseout",Fe);let ve,qe=!1,we=()=>{clearTimeout(ve),!qe&&(ve=setTimeout(()=>{qe=!0,o.contentWindow?.postMessage({type:"bitpalm-inactivity"},"*")},15e3))},ze=["mousemove","keydown","scroll","touchstart"];ze.forEach(e=>l.addEventListener(e,we,{passive:!0})),we(),ge=()=>{o.contentWindow?.postMessage({type:"bitpalm-open"},"*");let e=o.src.split("#")[0];o.src=`${e}#bp-open-${Date.now()}`};let ee=()=>{if(b.style.display="none",j(),Me(),R(),!C){B=!0;return}if(A!==null){let e=A;ie(),o.contentWindow?.postMessage({type:"bitpalm-trigger-engaged",message:e},"*");return}ge()},Ye=e=>{g=e,e==="off"&&(j(),ie()),Be()},Tt=()=>Ye("off"),Ct=()=>Ye(k==="off"?"bubble":k),xe=()=>{V(),o.contentWindow?.postMessage({type:"bitpalm-close"},"*")},Je=e=>{!e||typeof e!="object"||Oe({external_user_id:p(e.externalUserId,140)||void 0,name:p(e.name,140)||void 0,email:bt(e.email)||void 0,phone:N(e.phone)||void 0,company:p(e.company,160)||void 0,signature:p(e.signature,260)||void 0,signed_at:Number.isFinite(Number(e.signedAt))?Math.floor(Number(e.signedAt)):void 0,signature_version:e.signatureVersion==="v1"?"v1":void 0,identify_source:"manual"},"manual")},It=()=>{G?xe():ee()},At=()=>G,Ve=e=>{if(!e||typeof e!="string")return;let s=e.trim().slice(0,1e4);s&&(G||ee(),setTimeout(()=>{o.contentWindow?.postMessage({type:"bitpalm-send-message",message:s},"*")},G?50:500))};function Ge(){o.contentWindow?.postMessage({type:"bitpalm-theme",theme:u},"*")}let ce=e=>{e!==u&&(u=e,Ge())},Ke=e=>{h=ue(e),v?.(),v=null,h==="auto"?(v=Le(ce),ce(ne())):ce(h)};h==="auto"&&(v=Le(ce));let Qe=e=>{let s=e.detail;if(!s||typeof s!="object")return;let a=p(s.slug,120);a&&a!==t||Ke(ue(s.theme))};window.addEventListener("bitpalm-theme",Qe);let te={},Xe=e=>{if(!e||typeof e!="object"||Array.isArray(e))return;te={...te,...e};let s=JSON.stringify(te);s.length>ft&&console.warn(`[BitPalm] Custom context exceeds ${ft} bytes (${s.length}). It may be truncated.`),o.contentWindow?.postMessage({type:"bitpalm-custom-context",data:te},"*")},Lt=()=>{te={},o.contentWindow?.postMessage({type:"bitpalm-custom-context",data:{}},"*")},Ze=e=>{let a=e.detail;if(!a||typeof a!="object")return;let T=p(a.slug,120);if(T&&T!==t)return;let{slug:U,..._}=a;Xe(_)};window.addEventListener("bitpalm-context",Ze);let et=e=>{let a=e.detail;if(!a||typeof a!="object")return;let T=p(a.slug,120);T&&T!==t||Je(a)};window.addEventListener("bitpalm-identify",et);let Ee=e=>{let s=e.detail,a=p(s?.slug,120);return!a||a===t},tt=e=>{Ee(e)&&ee()},nt=e=>{Ee(e)&&xe()},ot=e=>{if(!Ee(e))return;let s=e.detail?.message;typeof s=="string"&&Ve(s)};return window.addEventListener("bitpalm-open",tt),window.addEventListener("bitpalm-close",nt),window.addEventListener("bitpalm-send",ot),{open:ee,close:xe,toggle:It,isOpen:At,identify:Je,context:Xe,resetContext:Lt,send:Ve,on:(e,s)=>(q.has(e)||q.set(e,new Set),q.get(e).add(s),()=>q.get(e)?.delete(s)),off:(e,s)=>{q.get(e)?.delete(s)},setTheme:Ke,disableTriggers:Tt,enableTriggers:Ct,destroy:()=>{window.removeEventListener("message",$e),window.removeEventListener("scroll",je),window.removeEventListener("popstate",le),l.removeEventListener("mouseout",Fe),l.removeEventListener("submit",Re,!0),ze.forEach(e=>l.removeEventListener(e,we)),clearTimeout(be),clearTimeout(ve),De.forEach(e=>clearTimeout(e)),history.pushState=Ue,history.replaceState=Ne,window.removeEventListener("bitpalm-identify",et),window.removeEventListener("bitpalm-context",Ze),window.removeEventListener("bitpalm-theme",Qe),window.removeEventListener("bitpalm-open",tt),window.removeEventListener("bitpalm-close",nt),window.removeEventListener("bitpalm-send",ot),v?.(),q.clear(),V(),j(),b.remove(),o.remove()}}}function Vt(n){let t=n.split(`
2
+ `).filter(i=>i.startsWith("data:")).map(i=>i.slice(5).trimStart()).join(`
3
+ `);if(!t)return null;try{let i=JSON.parse(t);return i&&typeof i.type=="string"?i:null}catch{return null}}function me(n){let t=[],i=n.replace(/\r\n/g,`
4
+ `),r=i.indexOf(`
5
+
6
+ `);for(;r>=0;){let c=Vt(i.slice(0,r));c&&t.push(c),i=i.slice(r+2),r=i.indexOf(`
7
+
8
+ `)}return{events:t,rest:i}}function wt(n){return me(`${n}
9
+
10
+ `).events}var H=class extends Error{constructor(i,r,c){super(r);this.code=i;this.status=c;this.name="BitPalmApiError"}},Gt="https://agents.bitpalm.ai";function Kt(){try{return typeof localStorage>"u"?null:localStorage}catch{return null}}function Qt(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`v-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,12)}`}async function Xt(n){let t=await n.json().catch(()=>null);return new H(t?.error?.code??"server_error",t?.error?.message??`Request failed (${n.status})`,n.status)}function xt(n){if(!n?.key?.startsWith("bp_pk_"))throw new Error("createChatClient needs an app key (bp_pk_\u2026) from the BitPalm dashboard.");let t=(n.baseUrl??Gt).replace(/\/+$/,""),i=n.storage===void 0?Kt():n.storage,r=`bitpalm:${n.key.slice(0,14)}`,c=o=>{try{return i?.getItem(`${r}:${o}`)??null}catch{return null}},f=(o,d)=>{try{d===null?i?.removeItem(`${r}:${o}`):i?.setItem(`${r}:${o}`,d)}catch{}},m=n.visitorId??c("visitor")??Qt();n.visitorId||f("visitor",m);let y=c("conversation"),l=!1,h=null,u=o=>{for(let d of o)d.fromHuman&&d.createdAt&&(!h||d.createdAt>h)&&(h=d.createdAt)},v={Authorization:`Bearer ${n.key}`},k=async(o,d)=>{let w=await fetch(`${t}${o}`,{...d,headers:{...v,...d?.headers??{}}});if(!w.ok)throw await Xt(w);return w},g=o=>{y=o,f("conversation",o)},A=(o,d,w)=>{for(let x of o)if(x.type==="delta")d.text+=x.text,w?.(x.text,d.text);else if(x.type==="replace")d.text=x.text,w?.("",d.text);else if(x.type==="done")d.result={text:d.text,conversationId:x.conversationId,...x.cards?{cards:x.cards}:{},...x.handoff?{handoff:!0}:{}};else if(x.type==="error")throw new H("server_error",x.message,500)};return{visitorId:m,get conversationId(){return y},get handoff(){return l},async agent(o){let d=new URLSearchParams({locale:n.locale??"en"});return o?.url&&d.set("url",o.url),(await k(`/api/v1/agent?${d.toString()}`)).json()},async send(o,d={}){let w=await k("/api/v1/chat",{method:"POST",headers:{"Content-Type":"application/json"},signal:d.signal,body:JSON.stringify({message:o,visitorId:m,conversationId:y??void 0,context:d.context,fileIds:d.fileIds})}),x={text:"",result:null},b=w.body&&typeof w.body.getReader=="function"?w.body.getReader():null;if(b){let I=new TextDecoder,E="";for(;;){let{done:P,value:C}=await b.read();if(P)break;let B=me(E+I.decode(C,{stream:!0}));E=B.rest,A(B.events,x,d.onDelta)}A(me(`${E}
11
+
12
+ `).events,x,d.onDelta)}else A(wt(await w.text()),x,d.onDelta);let M=x.result??{text:x.text,conversationId:y??""};return M.conversationId&&g(M.conversationId),l=M.handoff===!0,M},async history(){let o=new URLSearchParams({visitorId:m});y&&o.set("conversationId",y);let d=await(await k(`/api/v1/chat/history?${o.toString()}`)).json();return d.conversationId&&g(d.conversationId),l=d.handoff===!0,h=null,u(d.messages),d.messages},async updates(){if(!y)return{handoff:!1,teamTyping:!1,messages:[]};let o=new URLSearchParams({visitorId:m,conversationId:y});h&&o.set("after",h);let d=await(await k(`/api/v1/chat/updates?${o.toString()}`)).json(),w=d.messages??[];return u(w),l=d.handoff===!0,{handoff:l,teamTyping:d.teamTyping===!0,messages:w}},async identify(o){await k("/api/v1/identify",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({...o,visitorId:m})})},async upload(o,d="photo.jpg"){let w=new FormData;w.append("file",o,d),w.append("visitorId",m),y&&w.append("conversationId",y);let x=await(await k("/api/v1/chat/upload",{method:"POST",body:w})).json();return{id:x.id,url:x.url}},async feedback(o,d){if(!y)throw new H("bad_request","There is no conversation yet.",400);await k("/api/v1/chat/feedback",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({visitorId:m,conversationId:y,messageIndex:o,feedback:d})})},reset(){g(null),l=!1,h=null}}}function Zt(n){let t=(0,S.useRef)(null),i=(0,S.useRef)(!1);return(0,S.useEffect)(()=>{t.current?.setTheme(n.theme??"auto")},[n.theme]),(0,S.useEffect)(()=>{if(i.current)return;i.current=!0;let{onReady:r,...c}=n;return t.current=vt(c),r?.(t.current),()=>{t.current?.destroy(),t.current=null,i.current=!1}},[]),null}var en=3e3;function tn(){return typeof document<"u"&&document.visibilityState==="hidden"}function Et(n,t){return[...n.slice(0,-1),t]}function nn(n,t){let i=new Set(n.map(c=>c.id).filter(Boolean)),r=t.filter(c=>!c.id||!i.has(c.id));return r.length?[...n,...r]:n}function St(n){let t=n[n.length-1];return t?.role==="assistant"&&!t.text&&!t.cards?.length?n.slice(0,-1):n}function on(n){let[t]=(0,S.useState)(()=>xt(n)),[i,r]=(0,S.useState)([]),[c,f]=(0,S.useState)("idle"),[m,y]=(0,S.useState)(null),[l,h]=(0,S.useState)(null),[u,v]=(0,S.useState)(!1),[k,g]=(0,S.useState)(!1),A=(0,S.useRef)(!1),o=(0,S.useRef)(0),d=n.loadHistory!==!1,w=n.live!==!1;(0,S.useEffect)(()=>{let I=!0;return t.agent().then(E=>I&&h(E)).catch(()=>{}),d&&t.history().then(E=>{I&&(r(P=>P.length?P:E),v(t.handoff))}).catch(()=>{}),()=>{I=!1}},[t,d]),(0,S.useEffect)(()=>{if(!w||!u)return;let I=!1,E=!1,P=async()=>{if(!(I||E||tn())){E=!0;try{let R=await t.updates();if(I)return;g(R.teamTyping),R.messages.length&&r(W=>nn(W,R.messages)),R.handoff||v(!1)}catch{}finally{E=!1}}},C=()=>{P()};P();let B=setInterval(()=>{P()},en);return typeof document<"u"&&document.addEventListener("visibilitychange",C),()=>{I=!0,clearInterval(B),typeof document<"u"&&document.removeEventListener("visibilitychange",C)}},[t,u,w]);let x=(0,S.useCallback)(async(I,E={})=>{let P=I.trim();if(!P&&!E.fileIds?.length)return null;r(C=>[...C,{role:"user",text:P},{role:"assistant",text:""}]),f("streaming"),y(null),A.current=!0,o.current+=1;try{let C=await t.send(P,{...E,onDelta:(B,R)=>r(W=>Et(W,{role:"assistant",text:R}))});return r(B=>St(Et(B,{role:"assistant",text:C.text,...C.cards?{cards:C.cards}:{}}))),v(C.handoff===!0),f("idle"),C}catch(C){let B=C instanceof H?C:new H("network_error",String(C),0);return r(St),y(B),f("error"),null}finally{A.current=!1}},[t]),b=(0,S.useCallback)(async()=>{if(A.current)return;let I=o.current,E=await t.history();A.current||o.current!==I||(r(E),v(t.handoff))},[t]),M=(0,S.useCallback)(()=>{t.reset(),r([]),y(null),v(!1),f("idle")},[t]);return{messages:i,send:x,status:c,error:m,agent:l,handoff:u,teamTyping:u&&k,refresh:b,reset:M,client:t}}0&&(module.exports={BitPalmAgent,BitPalmApiError,useBitPalmChat});
2
13
  //# sourceMappingURL=react.cjs.map