@oyehello/chat 0.5.1 → 0.6.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/LICENSE +1 -1
- package/README.md +24 -12
- package/dist/index.cjs +139 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.global.js +139 -7
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +139 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/protocol.ts","../src/transport.ts","../src/fingerprint.ts","../src/journey.ts","../src/client.ts","../src/markdown.ts","../src/styles.ts","../src/icons.ts","../src/emoji.ts","../src/element.ts","../src/index.ts"],"names":["store"],"mappings":"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","file":"index.js","sourcesContent":["export class ChatApiError extends Error {\n constructor(message: string, readonly status: number, readonly code?: string, readonly meta?: Record<string, unknown>) {\n super(message);\n this.name = 'ChatApiError';\n }\n}\n","// SDK↔server wire-protocol version. Sent in the session-open request BODY (a custom header would need\n// a /chat/* CORS allowedHeaders entry); the server echoes its own version in the open response so the\n// SDK can warn (in the browser console) when an embed is out of date. Bump when the wire shape changes.\nexport const CHAT_PROTOCOL_VERSION = 1;\n\n// Mirrors the backend ChatEvent union (apps/api/src/telemetry/chat-event-sink.ts) EXACTLY.\nexport type ChatEvent =\n | { type: 'token'; text: string }\n | { type: 'message'; turnId: string; text: string }\n | { type: 'state'; state: string }\n | { type: 'done' }\n | { type: 'error'; message: string }\n | { type: 'tool_call'; callId: string; name: string; args: Record<string, unknown> }\n // Echoes a visitor's message attachments back over SSE (Phase 5 uploads) so the widget can render\n // the upload against the turn even on a reconnect/replay, without keeping its own optimistic state.\n | { type: 'attachment'; turnId?: string; items: { storageRef: string; contentType: string; name?: string }[] }\n // RAG source refs retrieved for this turn (Phase 6) - carries the same turnId as the `message`\n // event it follows. Absent KB / no retrieval this turn = no event.\n | { type: 'citations'; turnId: string; sources: { id: string; title: string; snippet: string }[] }\n // A human agent's reply, sent from the console inbox (Phase 7 handoff). The widget renders this\n // as a distinct \"human\" bubble.\n | { type: 'human_message'; turnId: string; text: string }\n // Echoes the visitor's own message back over SSE so the console inbox sees every visitor turn\n // live (Phase 7 handoff). The widget ignores this - it already renders its own message optimistically.\n | { type: 'visitor_message'; turnId: string; text: string }\n // A human agent is (or stopped) typing in the console during a handoff (Phase 7 followups). The\n // widget surfaces a transient \"agent is typing…\" affordance - never pushed as a message.\n | { type: 'agent_typing'; active: boolean }\n // Flow-derived follow-up quick-reply chips for the turn (same turnId as its `message`). The widget\n // renders them as chips; the next turn's event replaces them; an empty list clears them.\n | { type: 'suggestions'; turnId: string; items: string[] };\n\n// Pre-session widget config (GET /chat/widget-config) — read before the visitor opens the panel to\n// theme the launcher and show the teaser. brand is null unless the workspace has white-label branding.\nexport interface WidgetConfig {\n teaser: string;\n brand: { name: string | null; logoUrl: string | null; accentColor: string | null } | null;\n // Staffed-hours: when true the agent is outside its business hours - the widget shows offlineMessage\n // and a session-open attempt is refused server-side (code: agent_offline).\n offline?: boolean;\n offlineMessage?: string;\n}\n\nexport interface OpenSessionResponse {\n sessionId: string;\n sessionToken: string;\n expiresAt: string;\n agent: { id: string; name: string };\n // The server's wire-protocol version (see CHAT_PROTOCOL_VERSION). Absent from older servers.\n protocol?: number;\n}\n\nexport interface StreamTicket { ticket: string; expiresAt: string }\n\nexport interface ChatClientOptions {\n apiKey: string; // ohk_pub_… publishable key (created in the console)\n agentId: string;\n baseUrl: string; // the oyehello API origin, e.g. https://api.oyehello.ai\n user?: { id?: string };\n fetch?: typeof fetch; // injectable for tests\n eventSource?: typeof EventSource; // injectable for tests\n // SDK-side cap on files passed to a single sendMessage() call, enforced before any network call.\n // Mirrors the server's CHAT_ATTACHMENT_MAX_PER_MESSAGE default (apps/api/src/config/env.ts) so a\n // visitor gets an immediate error instead of a round-trip 400 on the message post.\n maxAttachments?: number;\n // SDK-side cap (bytes) on each file passed to a single sendMessage() call, enforced before any\n // upload. Mirrors the server's CHAT_ATTACHMENT_MAX_BYTES default (apps/api/src/config/env.ts).\n // This is UX-only - the server enforces the real limit (message-time HeadObject size check), so a\n // visitor just gets an immediate error instead of uploading a file that will be rejected anyway.\n maxAttachmentBytes?: number;\n}\n\n// A resolved attachment reference, shared shape between a message post body and the `attachment`\n// ChatEvent's items (protocol.ts's ChatEvent union above is the source of truth for the SSE shape;\n// this alias exists only so client.ts/transport.ts/element.ts don't repeat the inline object type).\nexport interface ChatAttachmentDescriptor { storageRef: string; contentType: string; name?: string }\n","import { ChatApiError } from './errors';\nimport { CHAT_PROTOCOL_VERSION } from './protocol';\nimport type { ChatAttachmentDescriptor, OpenSessionResponse, StreamTicket, WidgetConfig } from './protocol';\nimport type { JourneyView } from './journey';\n\nasync function asError(res: Response, fallbackCode?: string): Promise<ChatApiError> {\n let body: { error?: string; code?: string; meta?: Record<string, unknown> } = {};\n try { body = (await res.json()) as { error?: string; code?: string; meta?: Record<string, unknown> }; } catch { /* non-json */ }\n return new ChatApiError(body.error ?? `HTTP ${res.status}`, res.status, body.code ?? fallbackCode, body.meta);\n}\n\nexport async function openSession(opts: { baseUrl: string; apiKey: string; agentId: string; user?: { id?: string }; clientTools?: string[]; fingerprint?: string; fetchImpl: typeof fetch }): Promise<OpenSessionResponse> {\n // Protocol version rides in the BODY, not a custom header - a custom request header would have to be\n // added to the /chat/* CORS allowedHeaders allowlist or every browser preflight fails. The body is\n // already sent as application/json, which needs no extra CORS allowance.\n const body: Record<string, unknown> = { agentId: opts.agentId, protocol: CHAT_PROTOCOL_VERSION };\n if (opts.user) body.user = opts.user;\n if (opts.clientTools && opts.clientTools.length > 0) body.clientTools = opts.clientTools;\n if (opts.fingerprint) body.fingerprint = opts.fingerprint;\n const res = await opts.fetchImpl(`${opts.baseUrl}/chat/sessions`, {\n method: 'POST', credentials: 'omit',\n headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${opts.apiKey}` },\n body: JSON.stringify(body),\n });\n if (!res.ok) throw await asError(res);\n return (await res.json()) as OpenSessionResponse;\n}\n\n// Pre-session widget config (brand + teaser). Publishable-key auth, no session opened. A failure is\n// non-fatal for the widget — the caller falls back to defaults — so callers catch and ignore.\nexport async function getWidgetConfig(opts: { baseUrl: string; apiKey: string; agentId: string; fetchImpl: typeof fetch }): Promise<WidgetConfig> {\n const res = await opts.fetchImpl(`${opts.baseUrl}/chat/widget-config?agentId=${encodeURIComponent(opts.agentId)}`, {\n method: 'GET', credentials: 'omit',\n headers: { Authorization: `Bearer ${opts.apiKey}` },\n });\n if (!res.ok) throw await asError(res);\n return (await res.json()) as WidgetConfig;\n}\n\nexport async function postMessage(opts: { baseUrl: string; sessionId: string; sessionToken: string; text: string; attachments?: ChatAttachmentDescriptor[]; fetchImpl: typeof fetch }): Promise<void> {\n const body: Record<string, unknown> = { text: opts.text };\n if (opts.attachments && opts.attachments.length > 0) body.attachments = opts.attachments;\n const res = await opts.fetchImpl(`${opts.baseUrl}/chat/sessions/${opts.sessionId}/messages`, {\n method: 'POST', credentials: 'omit',\n headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${opts.sessionToken}` },\n body: JSON.stringify(body),\n });\n // A 401 here means the 15-min session token expired (no refresh endpoint) — surface a stable code\n // so the client can transparently re-open a session and retry.\n if (!res.ok) throw await asError(res, res.status === 401 ? 'session_expired' : undefined);\n}\n\n// POST /chat/sessions/:id/page-views — visitor-journey ingest (Task 21 SDK side / Task 20 server\n// route). Session-token auth, mirrors postMessage's shape. Fire-and-forget-friendly: the caller\n// (client.ts) guards this and only advances its local high-water mark on a resolved (2xx) response,\n// so a network failure just leaves the views unsent for the next flush — never thrown into the host\n// page from here beyond a normal rejected promise.\nexport async function postPageViews(opts: { baseUrl: string; sessionId: string; sessionToken: string; views: JourneyView[]; fetchImpl: typeof fetch }): Promise<void> {\n const res = await opts.fetchImpl(`${opts.baseUrl}/chat/sessions/${opts.sessionId}/page-views`, {\n method: 'POST', credentials: 'omit',\n headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${opts.sessionToken}` },\n body: JSON.stringify({ views: opts.views }),\n });\n if (!res.ok) throw await asError(res, res.status === 401 ? 'session_expired' : undefined);\n}\n\nexport async function endSession(opts: { baseUrl: string; sessionId: string; sessionToken: string; fetchImpl: typeof fetch }): Promise<void> {\n await opts.fetchImpl(`${opts.baseUrl}/chat/sessions/${opts.sessionId}/end`, {\n method: 'POST', credentials: 'omit',\n headers: { Authorization: `Bearer ${opts.sessionToken}` },\n }).catch(() => {}); // best-effort teardown\n}\n\nexport async function postToolResult(opts: { baseUrl: string; sessionId: string; sessionToken: string; callId: string; ok: boolean; result: unknown; fetchImpl: typeof fetch }): Promise<void> {\n await opts.fetchImpl(`${opts.baseUrl}/chat/sessions/${opts.sessionId}/tool-results`, {\n method: 'POST', credentials: 'omit',\n headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${opts.sessionToken}` },\n body: JSON.stringify({ callId: opts.callId, ok: opts.ok, result: opts.result }),\n }).catch(() => {}); // best-effort; a dropped result times out server-side and the model recovers\n}\n\n// Re-mint a fresh session token for the SAME session before the current one expires, so a long,\n// actively-used conversation stays on one session (one chat in the console) instead of the message\n// path reopening a new session on token expiry. Auth is the current (still-valid) token.\nexport async function refreshSessionToken(opts: { baseUrl: string; sessionId: string; sessionToken: string; fetchImpl: typeof fetch }): Promise<{ sessionToken: string; expiresAt: string }> {\n const res = await opts.fetchImpl(`${opts.baseUrl}/chat/sessions/${opts.sessionId}/refresh-token`, {\n method: 'POST', credentials: 'omit',\n headers: { Authorization: `Bearer ${opts.sessionToken}` },\n });\n if (!res.ok) throw await asError(res, res.status === 401 ? 'session_expired' : undefined);\n return (await res.json()) as { sessionToken: string; expiresAt: string };\n}\n\nexport async function mintStreamTicket(opts: { baseUrl: string; sessionId: string; sessionToken: string; fetchImpl: typeof fetch }): Promise<StreamTicket> {\n const res = await opts.fetchImpl(`${opts.baseUrl}/chat/sessions/${opts.sessionId}/stream-ticket`, {\n method: 'POST', credentials: 'omit',\n headers: { Authorization: `Bearer ${opts.sessionToken}` },\n });\n // A 401 here means the session token is invalid/expired — surface a stable code so the client\n // can distinguish this from a transient failure (mirrors postMessage's 401 mapping).\n if (!res.ok) throw await asError(res, res.status === 401 ? 'session_expired' : undefined);\n return (await res.json()) as StreamTicket;\n}\n\nexport function streamUrl(baseUrl: string, sessionId: string, ticket: string): string {\n return `${baseUrl}/chat/sessions/${sessionId}/stream?ticket=${encodeURIComponent(ticket)}`;\n}\n\n// POST /chat/sessions/:id/attachments — mints a presigned S3 PUT for a visitor upload. Bearer session\n// token auth, mirrors mintStreamTicket's shape/error-mapping exactly.\n// Server-proxied upload (the default): POST the file to OUR API as multipart/form-data; the server\n// streams it to storage and returns the storageRef. No direct browser→bucket PUT, so no bucket CORS to\n// configure. Only Authorization is a custom header (allowed by /chat/* CORS); the browser sets the\n// multipart Content-Type/boundary itself.\nexport async function uploadAttachment(opts: { baseUrl: string; sessionId: string; sessionToken: string; file: File; fetchImpl: typeof fetch }): Promise<ChatAttachmentDescriptor> {\n const form = new FormData();\n form.append('file', opts.file, opts.file.name);\n const res = await opts.fetchImpl(`${opts.baseUrl}/chat/sessions/${opts.sessionId}/upload`, {\n method: 'POST', credentials: 'omit',\n headers: { Authorization: `Bearer ${opts.sessionToken}` },\n body: form,\n });\n if (!res.ok) throw await asError(res, res.status === 401 ? 'session_expired' : undefined);\n const j = (await res.json()) as { storageRef: string; contentType: string; name?: string };\n return { storageRef: j.storageRef, contentType: j.contentType, name: j.name };\n}\n\nexport async function presignAttachment(opts: { baseUrl: string; sessionId: string; sessionToken: string; contentType: string; fetchImpl: typeof fetch }): Promise<{ storageRef: string; uploadUrl: string }> {\n const res = await opts.fetchImpl(`${opts.baseUrl}/chat/sessions/${opts.sessionId}/attachments`, {\n method: 'POST', credentials: 'omit',\n headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${opts.sessionToken}` },\n body: JSON.stringify({ contentType: opts.contentType }),\n });\n // A 401 here means the session token is invalid/expired — surface a stable code so the client\n // can distinguish this from a transient failure (mirrors postMessage's 401 mapping).\n if (!res.ok) throw await asError(res, res.status === 401 ? 'session_expired' : undefined);\n return (await res.json()) as { storageRef: string; uploadUrl: string };\n}\n\n// POST /chat/sessions/:id/attachment-url — mints a presigned S3 GET so an already-uploaded\n// attachment can be read back (e.g. rendering an image thumbnail on reconnect, when no local blob\n// is cached). Bearer session token auth, mirrors presignAttachment's shape/error-mapping exactly.\nexport async function getAttachmentUrl(opts: { baseUrl: string; sessionId: string; sessionToken: string; storageRef: string; fetchImpl: typeof fetch }): Promise<string> {\n const res = await opts.fetchImpl(`${opts.baseUrl}/chat/sessions/${opts.sessionId}/attachment-url`, {\n method: 'POST', credentials: 'omit',\n headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${opts.sessionToken}` },\n body: JSON.stringify({ storageRef: opts.storageRef }),\n });\n // A 401 here means the session token is invalid/expired — surface a stable code so the client\n // can distinguish this from a transient failure (mirrors postMessage's 401 mapping).\n if (!res.ok) throw await asError(res, res.status === 401 ? 'session_expired' : undefined);\n return ((await res.json()) as { url: string }).url;\n}\n\n// Uploads a file directly to the presigned S3 URL. The URL is already absolute and fully signed —\n// NO baseUrl prefix, NO Authorization header (would break the signature), just a bare PUT with the\n// file's own content type (Task 4 dropped SSE from the presign so this needs no extra headers).\nexport async function uploadToPresigned(uploadUrl: string, file: File, fetchImpl: typeof fetch): Promise<void> {\n const res = await fetchImpl(uploadUrl, { method: 'PUT', body: file, headers: { 'Content-Type': file.type } });\n if (!res.ok) throw new ChatApiError(`attachment upload failed with HTTP ${res.status}`, res.status);\n}\n","// A lightweight, dependency-free device fingerprint: a stable hash of a handful of browser/device\n// signals, sent on session-open so the backend can flag abuse / recognise a returning device. NOT a\n// hardened anti-fraud fingerprint (no canvas/WebGL probing) — deliberately modest and privacy-lighter.\n// Returns null outside a browser (no navigator) or on any error, so it never blocks opening a session.\n\nasync function sha256Hex(input: string): Promise<string | null> {\n const g = globalThis as unknown as { crypto?: { subtle?: SubtleCrypto }; TextEncoder?: typeof TextEncoder };\n try {\n if (g.crypto?.subtle && typeof TextEncoder !== 'undefined') {\n const buf = await g.crypto.subtle.digest('SHA-256', new TextEncoder().encode(input));\n return Array.from(new Uint8Array(buf)).map((b) => b.toString(16).padStart(2, '0')).join('').slice(0, 32);\n }\n } catch { /* fall through to the non-crypto hash */ }\n // djb2 fallback (older/insecure contexts where SubtleCrypto is unavailable).\n let h = 5381;\n for (let i = 0; i < input.length; i++) h = ((h << 5) + h + input.charCodeAt(i)) >>> 0;\n return h.toString(16).padStart(8, '0');\n}\n\nexport async function computeDeviceFingerprint(): Promise<string | null> {\n try {\n const nav = typeof navigator !== 'undefined' ? (navigator as Navigator & { deviceMemory?: number }) : null;\n if (!nav) return null;\n const scr = typeof screen !== 'undefined' ? screen : null;\n const tz = (() => { try { return Intl.DateTimeFormat().resolvedOptions().timeZone; } catch { return ''; } })();\n const dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : '';\n const signals = [\n nav.userAgent,\n Array.isArray(nav.languages) ? nav.languages.join(',') : '',\n nav.language,\n (nav as Navigator & { platform?: string }).platform,\n nav.hardwareConcurrency,\n nav.deviceMemory,\n scr ? `${scr.width}x${scr.height}x${scr.colorDepth}` : '',\n dpr,\n tz,\n ].map((v) => String(v ?? '')).join('|');\n return await sha256Hex(signals);\n } catch {\n return null;\n }\n}\n","// Visitor-journey page-view tracking (Task 21). Buffered in sessionStorage from page load so\n// pre-chat browsing is captured even on Astro multi-page (full-reload) navigation — a session isn't\n// open yet when the visitor is just browsing, so there's nowhere to POST to until one is. The buffer\n// is flushed once a chat session exists (client.ts: on open() success, and live on every\n// recordPageView() call while a session is already open).\n//\n// Storage shape per agent, keyed `oyehello-chat:journey:<agentId>`:\n// { views: [{ path, at }, ...], flushed: number }\n// `flushed` is a high-water mark into `views` — everything before it has already been POSTed and\n// acknowledged by the server; unsentViews() returns the tail past it, markFlushed() advances it.\n// All sessionStorage access is guarded (try/catch) — it may throw (privacy mode, quota) or be\n// entirely unavailable, and this module must never throw into the host page.\n\nexport interface JourneyView { path: string; at: string }\ninterface JourneyStore { views: JourneyView[]; flushed: number }\n\nconst MAX_BUFFER = 25;\n\nconst storageKey = (agentId: string) => `oyehello-chat:journey:${agentId}`;\n\nconst store = (): Storage | null => {\n try { return globalThis.sessionStorage ?? null; } catch { return null; }\n};\n\nfunction load(agentId: string): JourneyStore {\n const s = store();\n if (!s) return { views: [], flushed: 0 };\n try {\n const raw = s.getItem(storageKey(agentId));\n if (!raw) return { views: [], flushed: 0 };\n const parsed = JSON.parse(raw) as Partial<JourneyStore> | null;\n const views = Array.isArray(parsed?.views)\n ? parsed!.views.filter((v): v is JourneyView => !!v && typeof v.path === 'string' && typeof v.at === 'string')\n : [];\n const flushedRaw = typeof parsed?.flushed === 'number' && parsed!.flushed >= 0 ? parsed!.flushed : 0;\n return { views, flushed: Math.min(flushedRaw, views.length) };\n } catch { return { views: [], flushed: 0 }; }\n}\n\nfunction save(agentId: string, data: JourneyStore): void {\n const s = store();\n if (!s) return;\n try { s.setItem(storageKey(agentId), JSON.stringify(data)); } catch { /* storage blocked/full */ }\n}\n\n// Strip query + hash (the caller passes `location.pathname` for the current-page case, so this\n// mainly protects installSpaHooks' `location.pathname` reads and any other caller that hands in a\n// fuller path string).\nconst sanitizePath = (raw: string): string => (raw || '/').split('?')[0]!.split('#')[0]!;\n\n// Append a view for `path` to the capped buffer, deduped against the immediately-previous entry\n// (so re-recording the same page — e.g. a redundant replaceState — doesn't spam the journey).\nexport function recordView(agentId: string, path: string): void {\n try {\n const p = sanitizePath(path);\n const data = load(agentId);\n const last = data.views[data.views.length - 1];\n if (last && last.path === p) return;\n data.views.push({ path: p, at: new Date().toISOString() });\n if (data.views.length > MAX_BUFFER) {\n const drop = data.views.length - MAX_BUFFER;\n data.views = data.views.slice(drop);\n data.flushed = Math.max(0, data.flushed - drop);\n }\n save(agentId, data);\n } catch { /* never throw into the host page */ }\n}\n\n// Views recorded but not yet acknowledged by the server (past the flushed high-water mark).\nexport function unsentViews(agentId: string): JourneyView[] {\n try {\n const data = load(agentId);\n return data.views.slice(data.flushed);\n } catch { return []; }\n}\n\n// Advance the flushed high-water mark by `count` (called after a successful POST of that many\n// unsent views) so they aren't resent on the next flush.\nexport function markFlushed(agentId: string, count: number): void {\n if (count <= 0) return;\n try {\n const data = load(agentId);\n data.flushed = Math.min(data.views.length, data.flushed + count);\n save(agentId, data);\n } catch { /* ignore */ }\n}\n\n// SPA support: Astro MPA navigation is already covered by a fresh recordView() on each full-page\n// connectedCallback, but a client-routed site never remounts the element — so patch history's\n// navigation entry points and notify on every push/replace/back-forward. Returns an uninstaller that\n// restores the originals and removes the popstate listener (call from disconnectedCallback).\nexport function installSpaHooks(onNav: () => void): () => void {\n const originalPush = history.pushState;\n const originalReplace = history.replaceState;\n // Reassigning history.pushState/replaceState can throw — some privacy/security tooling freezes\n // `history` (Object.defineProperty(..., { writable: false })) to stop exactly this kind of\n // monkey-patch. Guard each assignment independently so a frozen pushState doesn't stop replaceState\n // or the popstate listener from installing, and track what actually got installed so the uninstaller\n // only restores/removes what this call put in place.\n let pushInstalled = false;\n let replaceInstalled = false;\n try {\n history.pushState = function (this: History, ...args: Parameters<History['pushState']>) {\n const ret = originalPush.apply(this, args);\n try { onNav(); } catch { /* ignore */ }\n return ret;\n };\n pushInstalled = true;\n } catch { /* frozen/non-writable history.pushState — fall back to popstate-only below */ }\n try {\n history.replaceState = function (this: History, ...args: Parameters<History['replaceState']>) {\n const ret = originalReplace.apply(this, args);\n try { onNav(); } catch { /* ignore */ }\n return ret;\n };\n replaceInstalled = true;\n } catch { /* frozen/non-writable history.replaceState — fall back to popstate-only below */ }\n const onPopState = () => { try { onNav(); } catch { /* ignore */ } };\n let popstateInstalled = false;\n try { window.addEventListener('popstate', onPopState); popstateInstalled = true; } catch { /* ignore */ }\n return () => {\n if (pushInstalled) { try { history.pushState = originalPush; } catch { /* ignore */ } }\n if (replaceInstalled) { try { history.replaceState = originalReplace; } catch { /* ignore */ } }\n if (popstateInstalled) { try { window.removeEventListener('popstate', onPopState); } catch { /* ignore */ } }\n };\n}\n","import { openSession, postMessage, endSession, streamUrl, mintStreamTicket, refreshSessionToken, postToolResult, uploadAttachment, getAttachmentUrl, getWidgetConfig, postPageViews } from './transport';\nimport { ChatApiError } from './errors';\nimport { CHAT_PROTOCOL_VERSION } from './protocol';\nimport { computeDeviceFingerprint } from './fingerprint';\nimport { recordView, unsentViews, markFlushed } from './journey';\nimport type { ChatAttachmentDescriptor, ChatClientOptions, ChatEvent, OpenSessionResponse, WidgetConfig } from './protocol';\n\nexport interface ChatMessage { id: string; role: 'user' | 'assistant' | 'human'; text: string; streaming: boolean; attachments?: ChatAttachmentDescriptor[]; sources?: { id: string; title: string; snippet: string }[]; turnId?: string }\nexport type ChatClientState = 'idle' | 'opening' | 'ready' | 'ended' | 'error';\n// Handoff status of the session, driven by the backend's `state` SSE event (Phase 7). 'ai' = the\n// AI is answering (default/no handoff), 'awaiting_human' = a handoff was requested and no human\n// has taken over yet, 'human' = a human agent is answering.\nexport type HandoffState = 'ai' | 'awaiting_human' | 'human';\nexport type ChatClientEvent =\n | { type: 'state'; state: ChatClientState }\n | { type: 'messages'; messages: ChatMessage[] }\n | { type: 'error'; error: Error }\n | { type: 'agent'; agent: { id: string; name: string } }\n // Handoff status changed (Phase 7) - the widget uses this to show a status line.\n | { type: 'handoff'; state: HandoffState }\n // A human agent is (or stopped) typing in the console during a handoff (Phase 7 followups). The\n // widget uses this to show a transient \"agent is typing…\" affordance - never a message.\n | { type: 'agentTyping'; active: boolean }\n // Flow-derived follow-up chips for the latest turn; a later turn replaces them, an empty list clears.\n | { type: 'suggestions'; items: string[] };\nexport type ChatToolHandler = (args: Record<string, unknown>) => unknown | Promise<unknown>;\nexport interface ChatClient {\n start(): Promise<void>;\n sendMessage(text: string, files?: File[]): Promise<void>;\n end(): Promise<void>;\n // Detach the transport (close the SSE stream + timers) WITHOUT ending the server session or clearing\n // the persisted session. For a transient DOM unmount (framework navigation / Astro View Transitions):\n // the element re-mounts and resumes the same conversation instead of killing it + opening a new chat.\n detach(): void;\n // Clear the conversation thread (messages + dedup + handoff state) back to a blank slate, without\n // opening a session. Call before start() to begin a genuinely fresh conversation (e.g. the widget's\n // \"New message\" after a session ended).\n reset(): void;\n getMessages(): ChatMessage[];\n getState(): ChatClientState;\n on(listener: (e: ChatClientEvent) => void): () => void;\n // Register browser-side tool handlers the server may call mid-conversation. Register BEFORE\n // start() — the handler names are sent as `clientTools` on session open so the server knows\n // which tools this session can execute.\n registerTools(handlers: Record<string, ChatToolHandler>): void;\n // Resolves a read-back URL for an already-uploaded attachment (e.g. an image thumbnail with no\n // local blob cached — a reconnect, or an `attachment` SSE echo). Requires start() to have been\n // called (a live session).\n getAttachmentUrl(storageRef: string): Promise<string>;\n // Pre-session widget config (brand + teaser). Safe to call before start(); no session is opened.\n getWidgetConfig(): Promise<WidgetConfig>;\n // Record a visitor page view for the CRM journey timeline (Task 21). Buffers via journey.ts\n // (survives an Astro full-page reload) and, if a session is already open, also flushes the newly\n // unsent views to the server immediately - never throws into the host page.\n recordPageView(path: string): void;\n}\n\nlet seq = 0;\nconst uid = (p: string) => `${p}_${Date.now().toString(36)}_${(seq++).toString(36)}`;\n\nexport function createChatClient(options: ChatClientOptions): ChatClient {\n // Native fetch must be invoked with `this === window`; the transport calls this as\n // `opts.fetchImpl(...)`, so a bare `globalThis.fetch` reference throws \"Illegal invocation\".\n // Bind the default to the global. A caller-supplied fetch is used as-is.\n const fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis);\n const ES = options.eventSource ?? globalThis.EventSource;\n // Mirrors the server's CHAT_ATTACHMENT_MAX_PER_MESSAGE default (apps/api/src/config/env.ts).\n const maxAttachments = options.maxAttachments ?? 4;\n // Mirrors the server's CHAT_ATTACHMENT_MAX_BYTES default (apps/api/src/config/env.ts). UX-only\n // fast pre-check - the server is authoritative (message-time HeadObject size enforcement).\n const maxAttachmentBytes = options.maxAttachmentBytes ?? 10_000_000;\n const listeners = new Set<(e: ChatClientEvent) => void>();\n let state: ChatClientState = 'idle';\n const messages: ChatMessage[] = [];\n let streamingId: string | null = null;\n let session: OpenSessionResponse | null = null;\n let es: EventSource | null = null;\n const seenTurnIds = new Set<string>();\n const seenCallIds = new Set<string>();\n let handoffState: HandoffState = 'ai';\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n let reconnectAttempts = 0;\n let closed = false;\n let warnedProtocol = false;\n // Device fingerprint: computed once (undefined = not yet computed, null = unavailable), reused across\n // reconnects/reopens so the same device reports a stable id.\n let deviceFingerprint: string | null | undefined;\n let refreshTimer: ReturnType<typeof setTimeout> | null = null;\n const toolHandlers = new Map<string, ChatToolHandler>();\n // Flush any journey.ts-buffered page views (recorded before a session existed, or since the last\n // flush) to the now-open session. Best-effort: a failed POST leaves the views unsent - the flushed\n // high-water mark only advances on a resolved response, so they're retried on the next open()/\n // recordPageView() rather than lost.\n //\n // Serialized via journeyFlushChain/journeyFlushQueued so two flushes triggered close together (e.g.\n // open()'s post-session flush racing a live recordPageView() call) never both read unsentViews()\n // before either markFlushed runs - that would POST the same pending views twice (bulkInsert has no\n // idempotency, so duplicate rows). At most one POST is ever in flight; a flushJourney() call that\n // arrives while one is running just sets a \"run once more\" flag (coalescing any number of calls\n // during that window into a single follow-up round), which re-reads unsentViews() AFTER the\n // in-flight POST's markFlushed has run, so it only sends what's genuinely still unsent.\n let journeyFlushChain: Promise<void> = Promise.resolve();\n let journeyFlushQueued = false;\n const flushJourney = () => {\n if (!session) return;\n if (journeyFlushQueued) return; // a follow-up round is already queued behind the in-flight flush\n journeyFlushQueued = true;\n journeyFlushChain = journeyFlushChain.then(async () => {\n journeyFlushQueued = false;\n if (!session) return;\n const pending = unsentViews(options.agentId);\n if (pending.length === 0) return;\n const s = session;\n try {\n await postPageViews({ baseUrl: options.baseUrl, sessionId: s.sessionId, sessionToken: s.sessionToken, views: pending, fetchImpl });\n markFlushed(options.agentId, pending.length);\n } catch { /* left unsent; retried on the next flush */ }\n });\n };\n const clearReconnect = () => { if (reconnectTimer) { clearTimeout(reconnectTimer); reconnectTimer = null; } };\n const clearRefresh = () => { if (refreshTimer) { clearTimeout(refreshTimer); refreshTimer = null; } };\n // Proactively re-mint the session token ~60s before it expires so a long active conversation stays on\n // ONE session (a token lapse would otherwise make the next message reopen a fresh session = a new\n // console chat). On failure (session ended/expired) the stored session is dropped and the normal\n // session_expired path opens a fresh one.\n const scheduleRefresh = () => {\n clearRefresh();\n if (closed || !session) return;\n const untilExpiry = Date.parse(session.expiresAt) - Date.now();\n const delay = Number.isNaN(untilExpiry) ? 10 * 60_000 : Math.max(5_000, untilExpiry - 60_000);\n refreshTimer = setTimeout(async () => {\n if (closed || !session) return;\n try {\n const r = await refreshSessionToken({ baseUrl: options.baseUrl, sessionId: session.sessionId, sessionToken: session.sessionToken, fetchImpl });\n session = { ...session, sessionToken: r.sessionToken, expiresAt: r.expiresAt };\n persistSession(session);\n scheduleRefresh();\n } catch (err) {\n // Only drop the session if it's definitively gone. A transient/404 (e.g. an API not yet\n // redeployed with the refresh route) leaves the still-valid session intact - it stays usable\n // until its original expiry, and the message path's session_expired handling covers the lapse.\n const code = (err as ChatApiError | undefined)?.code;\n if (code === 'session_ended' || code === 'session_expired') clearStoredSession();\n }\n }, delay);\n (refreshTimer as { unref?: () => void }).unref?.();\n };\n\n // Persist the open session per-tab so a page RELOAD resumes the SAME server session instead of\n // opening a new one (which would spawn a fresh chat in the console on every reload). Keyed by agent\n // and scoped to sessionStorage: a reload keeps it, a new tab starts fresh. Resume is driven by the\n // session TOKEN we minted (an unguessable bearer secret owned by this device) - NOT the device\n // fingerprint, which is spoofable and collides across identical devices (keying reuse on it would let\n // one visitor resume another's chat). The fingerprint stays a server-side analytics/abuse signal only.\n const sessKey = `oyehello-chat-sess:${options.agentId}`;\n const store = (() => { try { return globalThis.sessionStorage ?? null; } catch { return null; } })();\n const loadStoredSession = (): OpenSessionResponse | null => {\n if (!store) return null;\n try {\n const raw = store.getItem(sessKey);\n if (!raw) return null;\n const s = JSON.parse(raw) as OpenSessionResponse;\n if (!s?.sessionId || !s?.sessionToken || !s?.expiresAt || !s?.agent) return null;\n const exp = Date.parse(s.expiresAt);\n if (Number.isNaN(exp) || Date.now() >= exp - 5_000) { store.removeItem(sessKey); return null; } // bad or (near-)expired token\n return s;\n } catch { return null; }\n };\n const persistSession = (s: OpenSessionResponse) => {\n try { store?.setItem(sessKey, JSON.stringify({ sessionId: s.sessionId, sessionToken: s.sessionToken, expiresAt: s.expiresAt, agent: s.agent })); } catch { /* storage blocked */ }\n };\n const clearStoredSession = () => { try { store?.removeItem(sessKey); } catch { /* storage blocked */ } };\n\n const emit = (e: ChatClientEvent) => { for (const l of listeners) l(e); };\n const setState = (s: ChatClientState) => { state = s; emit({ type: 'state', state: s }); };\n const emitMessages = () => emit({ type: 'messages', messages: messages.slice() });\n\n const onEvent = (ev: ChatEvent) => {\n if (ev.type === 'token') {\n let m = streamingId ? messages.find((x) => x.id === streamingId) : undefined;\n if (!m) { m = { id: uid('m'), role: 'assistant', text: '', streaming: true }; messages.push(m); streamingId = m.id; }\n m.text += ev.text; emitMessages();\n } else if (ev.type === 'message') {\n if (seenTurnIds.has(ev.turnId)) {\n // Replay of an already-finalized turn (EventSource reconnect replays the session's\n // event buffer). Discard it, and drop any partial streaming bubble its replayed\n // tokens built up, without emitting a duplicate assistant message.\n if (streamingId) {\n const idx = messages.findIndex((x) => x.id === streamingId);\n if (idx !== -1) messages.splice(idx, 1);\n streamingId = null;\n emitMessages();\n }\n return;\n }\n seenTurnIds.add(ev.turnId);\n const m = streamingId ? messages.find((x) => x.id === streamingId) : undefined;\n // Keep the streamed text if the finalize carries none: a streaming turn's `message` event may\n // arrive with an empty `text` (the text was delivered via tokens), and overwriting with '' would\n // blank the just-streamed bubble.\n if (m) { m.text = ev.text || m.text; m.streaming = false; m.turnId = ev.turnId; } else { messages.push({ id: uid('m'), role: 'assistant', text: ev.text, streaming: false, turnId: ev.turnId }); }\n streamingId = null; emitMessages();\n } else if (ev.type === 'citations') {\n // Arrives AFTER `message` (streamingId already cleared) so the target message is located by\n // the turnId stamped above, not by streamingId. Ignore an unknown turnId (reconnect-safe: a\n // stale/duplicate citations replay for a turn we don't have never crashes or creates a bubble).\n const m = messages.find((x) => x.turnId === ev.turnId);\n if (m) { m.sources = ev.sources; emitMessages(); }\n } else if (ev.type === 'error') {\n emit({ type: 'error', error: new Error(ev.message) });\n } else if (ev.type === 'tool_call') {\n if (seenCallIds.has(ev.callId)) return; // replayed on EventSource reconnect — dispatch once\n seenCallIds.add(ev.callId);\n const handler = toolHandlers.get(ev.name);\n void (async () => {\n if (!session) return;\n const base = { baseUrl: options.baseUrl, sessionId: session.sessionId, sessionToken: session.sessionToken, callId: ev.callId, fetchImpl };\n if (!handler) {\n await postToolResult({ ...base, ok: false, result: `no handler registered for ${ev.name}` });\n return;\n }\n try {\n const out = await handler(ev.args);\n await postToolResult({ ...base, ok: true, result: typeof out === 'string' ? out : JSON.stringify(out ?? { ok: true }) });\n } catch (err) {\n await postToolResult({ ...base, ok: false, result: (err as Error).message });\n }\n })();\n } else if (ev.type === 'attachment') {\n // The runtime re-publishes a visitor's message attachments over this event (Phase 5\n // follow-up) so a reconnecting client (buffer replay) or a future second viewer can render\n // them, now that a read-back URL exists (getAttachmentUrl / element.ts's lazy image src).\n // Hardened so it can never double-render on the SENDING client itself, which already rendered\n // these optimistically from its own sendMessage(): if any existing message already carries an\n // attachment with one of these storageRefs, the event is a stale/duplicate echo of something\n // already rendered — ignore it entirely instead of guessing which message to attach to (a\n // \"most recent attachment-less user message\" heuristic misattaches when a second image-first\n // message is sent before the echo of the first one arrives).\n const items = ev.items;\n const alreadyRendered = messages.some((m) => m.attachments?.some((a) => items.some((i) => i.storageRef === a.storageRef)));\n if (alreadyRendered) return;\n const target = [...messages].reverse().find((m) => m.role === 'user' && !m.attachments);\n if (target) target.attachments = items;\n else messages.push({ id: uid('u'), role: 'user', text: '', streaming: false, attachments: items });\n emitMessages();\n } else if (ev.type === 'human_message') {\n // A human agent's reply from the console inbox (Phase 7 handoff) - render as a distinct bubble.\n // Dedup by turnId (shared with the `message` branch's seenTurnIds) - EventSource reconnect\n // replays the session's buffered events, and human_message turnIds (newId('tn')) are distinct\n // from message turnIds, so sharing the Set is safe.\n if (seenTurnIds.has(ev.turnId)) return;\n seenTurnIds.add(ev.turnId);\n messages.push({ id: uid('m'), role: 'human', text: ev.text, streaming: false });\n emitMessages();\n } else if (ev.type === 'visitor_message') {\n // Echo of the visitor's own message, published so the console inbox sees it live. The widget\n // already rendered this optimistically in sendMessage() - ignore the echo entirely.\n } else if (ev.type === 'state') {\n // Handoff status transition (Phase 7): 'ai' | 'awaiting_human' | 'human'. Ignore any other/\n // future state string - forward-compat, no status line for an unrecognized value.\n if (ev.state === 'ai' || ev.state === 'awaiting_human' || ev.state === 'human') {\n handoffState = ev.state;\n emit({ type: 'handoff', state: handoffState });\n }\n } else if (ev.type === 'agent_typing') {\n // Transient signal only - never pushed as a message, never touches dedup/streaming state.\n emit({ type: 'agentTyping', active: !!ev.active });\n } else if (ev.type === 'suggestions') {\n // Flow-derived quick-reply chips for the latest turn - forwarded verbatim to the widget.\n emit({ type: 'suggestions', items: Array.isArray(ev.items) ? ev.items : [] });\n } else if (ev.type === 'done') {\n // The session ended (flow finished, idle sweep, or a console close). Terminal: stop the stream\n // and reconnection, and surface 'ended' so the widget can offer a fresh start. Drop the persisted\n // session so a reload doesn't resume the dead one (it opens a fresh chat instead).\n closed = true; clearReconnect(); clearRefresh(); es?.close(); es = null;\n clearStoredSession();\n setState('ended');\n }\n // Unknown/future event types are ignored (forward-compat).\n };\n\n // Tickets are single-use and short-lived: a fresh one must be minted for every (re)connect.\n // Native EventSource auto-reconnect would retry the SAME url whose ticket is already consumed\n // (→ 401 forever), so on error we close it ourselves and drive reconnection here instead.\n const openStream = async () => {\n if (!session || closed) return;\n es?.close();\n const { ticket } = await mintStreamTicket({ baseUrl: options.baseUrl, sessionId: session.sessionId, sessionToken: session.sessionToken, fetchImpl });\n if (closed) return;\n es = new ES(streamUrl(options.baseUrl, session.sessionId, ticket));\n es.onopen = () => { reconnectAttempts = 0; };\n es.onmessage = (e: MessageEvent) => { try { onEvent(JSON.parse(e.data) as ChatEvent); } catch { /* ignore malformed */ } };\n es.onerror = () => { es?.close(); es = null; scheduleReconnect(); };\n };\n\n const scheduleReconnect = () => {\n if (closed) return;\n clearReconnect();\n const delay = Math.min(30_000, 500 * 2 ** reconnectAttempts);\n reconnectAttempts += 1;\n reconnectTimer = setTimeout(() => {\n openStream().catch((err) => {\n if (err instanceof ChatApiError && (err as ChatApiError).code === 'session_expired') {\n clearStoredSession(); // don't resume the expired session - force a fresh open\n open().catch((e) => { emit({ type: 'error', error: e as Error }); scheduleReconnect(); });\n } else {\n scheduleReconnect();\n }\n });\n }, delay);\n };\n\n const open = async () => {\n // Resume the existing session on reload (no new /chat/sessions → no new chat in the console). If the\n // resumed session turns out ended/gone server-side, the first message hits the session_expired path,\n // which clears the stored session and opens a fresh one.\n const resumed = loadStoredSession();\n if (resumed) {\n session = resumed;\n emit({ type: 'agent', agent: resumed.agent });\n await openStream();\n scheduleRefresh();\n flushJourney();\n return;\n }\n if (deviceFingerprint === undefined) deviceFingerprint = await computeDeviceFingerprint().catch(() => null);\n session = await openSession({ baseUrl: options.baseUrl, apiKey: options.apiKey, agentId: options.agentId, user: options.user, clientTools: Array.from(toolHandlers.keys()), fingerprint: deviceFingerprint ?? undefined, fetchImpl });\n persistSession(session);\n // Surface a version drift to the integrator (browser console only, non-fatal) so a stale embed is\n // noticeable when the server contract has moved on.\n if (!warnedProtocol && typeof session.protocol === 'number' && session.protocol !== CHAT_PROTOCOL_VERSION) {\n warnedProtocol = true;\n try { console.warn(`[oyehello-chat] SDK protocol v${CHAT_PROTOCOL_VERSION} vs server v${session.protocol} - update @oyehello/chat to the latest version.`); } catch { /* no console */ }\n }\n emit({ type: 'agent', agent: session.agent });\n await openStream();\n scheduleRefresh();\n flushJourney();\n };\n\n // Presign + PUT every file against the CURRENT session. Called from the main sendMessage path and,\n // after a session_expired reopen, from the retry — a storageRef presigned against the old\n // interactionId is rejected cross-session (403 attachment_cross_session) if reused post-reopen.\n const uploadFiles = async (files: File[]): Promise<ChatAttachmentDescriptor[]> => {\n // Server-proxied: the file goes to OUR API, which streams it to storage (no direct browser→bucket\n // PUT, so no bucket CORS). A storageRef presigned/created against the old interactionId is rejected\n // cross-session if reused post-reopen, so this is re-run from the session_expired retry too.\n return Promise.all(files.map((file) =>\n uploadAttachment({ baseUrl: options.baseUrl, sessionId: session!.sessionId, sessionToken: session!.sessionToken, file, fetchImpl })));\n };\n\n return {\n getMessages: () => messages.slice(),\n getState: () => state,\n on(listener) { listeners.add(listener); return () => listeners.delete(listener); },\n registerTools(handlers) { for (const [name, fn] of Object.entries(handlers)) toolHandlers.set(name, fn); },\n async getAttachmentUrl(storageRef) {\n if (!session) throw new Error('call start() before getAttachmentUrl');\n return getAttachmentUrl({ baseUrl: options.baseUrl, sessionId: session.sessionId, sessionToken: session.sessionToken, storageRef, fetchImpl });\n },\n getWidgetConfig() {\n return getWidgetConfig({ baseUrl: options.baseUrl, apiKey: options.apiKey, agentId: options.agentId, fetchImpl });\n },\n recordPageView(path) {\n try {\n recordView(options.agentId, path);\n flushJourney(); // no-op if no session yet - open()'s flush covers it once one exists\n } catch { /* never throw into the host page */ }\n },\n async start() {\n // Ignore only while a connect is in flight or already live; allow a (re)start from idle, error,\n // or ended so a transient failure is recoverable (e.g. the widget's Retry button) without a page\n // reload. Reset closed/backoff so a restart genuinely reconnects.\n if (state === 'opening' || state === 'ready') return;\n closed = false;\n clearReconnect();\n reconnectAttempts = 0;\n setState('opening');\n try { await open(); setState('ready'); }\n catch (err) { setState('error'); emit({ type: 'error', error: err as Error }); }\n },\n async sendMessage(text, files) {\n if (!session) { emit({ type: 'error', error: new Error('call start() before sendMessage') }); return; }\n const fileList = files ?? [];\n if (fileList.length > maxAttachments) {\n emit({ type: 'error', error: new Error(`too many attachments: max ${maxAttachments} per message`) });\n return;\n }\n const oversized = fileList.find((f) => f.size > maxAttachmentBytes);\n if (oversized) {\n emit({ type: 'error', error: new Error(`attachment too large: ${oversized.name} exceeds ${maxAttachmentBytes} bytes`) });\n return;\n }\n // Upload every file BEFORE posting the message or pushing the optimistic bubble — a failed\n // upload must never leave a broken/partial message in the thread.\n let attachments: ChatAttachmentDescriptor[] = [];\n if (fileList.length > 0) {\n try {\n attachments = await uploadFiles(fileList);\n } catch (err) {\n emit({ type: 'error', error: err as Error });\n return;\n }\n }\n messages.push({ id: uid('u'), role: 'user', text, streaming: false, attachments: attachments.length > 0 ? attachments : undefined }); emitMessages();\n try {\n await postMessage({ baseUrl: options.baseUrl, sessionId: session.sessionId, sessionToken: session.sessionToken, text, attachments, fetchImpl });\n } catch (err) {\n if (err instanceof ChatApiError && err.code === 'session_expired') {\n try {\n clearStoredSession(); // the stored session just expired - don't resume it, open fresh\n await open(); // fresh backend session, same UI thread\n // Re-upload against the NEW session — the old attachments' storageRefs are bound to the\n // stale interactionId and would 403 (attachment_cross_session) if re-posted as-is.\n const freshAttachments = fileList.length ? await uploadFiles(fileList) : [];\n await postMessage({ baseUrl: options.baseUrl, sessionId: session!.sessionId, sessionToken: session!.sessionToken, text, attachments: freshAttachments, fetchImpl });\n } catch (retryErr) {\n emit({ type: 'error', error: retryErr as Error });\n }\n } else { emit({ type: 'error', error: err as Error }); }\n }\n },\n detach() {\n // Stop the transport but keep the server session + stored session alive (see interface note).\n closed = true; clearReconnect(); clearRefresh();\n es?.close(); es = null;\n },\n async end() {\n closed = true; clearReconnect(); clearRefresh(); clearStoredSession();\n if (session) await endSession({ baseUrl: options.baseUrl, sessionId: session.sessionId, sessionToken: session.sessionToken, fetchImpl });\n es?.close(); es = null; setState('ended');\n },\n reset() {\n // Blank slate for a new conversation. start() (allowed from 'ended'/'idle') opens a fresh session.\n // Drop the persisted session so start() doesn't resume the old one.\n clearStoredSession();\n es?.close(); es = null; clearReconnect(); clearRefresh();\n session = null; streamingId = null; handoffState = 'ai';\n messages.length = 0; seenTurnIds.clear(); seenCallIds.clear();\n emit({ type: 'messages', messages: [] });\n emit({ type: 'handoff', state: 'ai' });\n setState('idle');\n },\n };\n}\n","import { marked } from 'marked';\nimport DOMPurify from 'dompurify';\n\n// GitHub-flavored markdown with single-newline line breaks (chat text rarely uses the two-space\n// hard-break convention). Set once at module load.\nmarked.setOptions({ gfm: true, breaks: true });\n\nlet hookInstalled = false;\nfunction installLinkHook(): void {\n if (hookInstalled) return;\n // Every surviving link opens in a new tab and drops referrer/opener; nofollow since the content is\n // model-generated and visitor-influenced.\n DOMPurify.addHook('afterSanitizeAttributes', (node) => {\n if (node.nodeName === 'A') {\n node.setAttribute('target', '_blank');\n node.setAttribute('rel', 'noopener noreferrer nofollow');\n }\n });\n hookInstalled = true;\n}\n\n// Tags/attributes a chat message may render. Everything else (script, style, iframe, event handlers,\n// inline styles, data-*) is stripped by DOMPurify. javascript:/data: URLs are rejected by the URI\n// regexp, so no link can execute script.\nconst ALLOWED_TAGS = ['p', 'br', 'strong', 'em', 'b', 'i', 'del', 's', 'code', 'pre', 'blockquote',\n 'ul', 'ol', 'li', 'a', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr',\n 'table', 'thead', 'tbody', 'tr', 'th', 'td', 'span'];\nconst ALLOWED_ATTR = ['href', 'target', 'rel', 'class'];\n\n// Render a markdown string to sanitized HTML safe to inject into the widget's shadow DOM. The input\n// is model-generated (and a visitor can influence the conversation), so the output is ALWAYS run\n// through DOMPurify — marked itself passes raw HTML through untouched.\nexport function renderMarkdown(text: string): string {\n installLinkHook();\n const raw = marked.parse(text, { async: false }) as string;\n return DOMPurify.sanitize(raw, {\n ALLOWED_TAGS,\n ALLOWED_ATTR,\n ALLOW_DATA_ATTR: false,\n ALLOWED_URI_REGEXP: /^(?:https?:|mailto:)/i,\n });\n}\n","// Widget CSS, injected once into the shadow root. Ported from the Oyehello Chat Widget design.\n// Every token is namespaced --oc-* so a host page's own custom properties can't bleed across the\n// shadow boundary (custom properties inherit through it). The accent reads the public --oc-accent\n// override (default #096DD9). State is driven by classes on the `.oc` wrapper (open/max/emoji/\n// show-teaser/away/focus/ready/unread/show-ring), so the element toggles classes rather than\n// restyling nodes. NB: state classes are prefixed (show-teaser/show-ring) where a same-named element\n// class exists (.teaser/.ring) — a bare `.teaser{display:none}` would otherwise also match `.oc.teaser`\n// and hide the whole widget (equal specificity, later rule wins).\nexport const STYLES = `\n :host {\n /* accent (consumer-overridable via --oc-accent) + its derivations */\n --oc-ac: var(--oc-accent, #096DD9);\n --oc-btn-rim: color-mix(in oklab, var(--oc-ac) 70%, black);\n --oc-btn-edge: 0 6px 16px -10px color-mix(in oklab, var(--oc-ac) 55%, transparent);\n --oc-danger: #D92D20;\n --oc-ease: cubic-bezier(0.16,1,0.3,1);\n --oc-bounce: cubic-bezier(0.18,0.89,0.32,1.13);\n --oc-mono: 'Geist Mono', ui-monospace, monospace;\n --oc-r-full: 999px;\n\n /* light palette (base) */\n --oc-bg: #FFFFFF; --oc-bg-sunk: #F6F8FB;\n --oc-fg: #0A0D12; --oc-fg-muted: rgba(10,13,18,0.66); --oc-fg-dim: rgba(10,13,18,0.44);\n --oc-border: rgba(9,13,20,0.10);\n --oc-accent-text: color-mix(in oklab, var(--oc-ac) 88%, black);\n --oc-tint-1: rgba(9,13,20,0.025); --oc-tint-2: rgba(9,13,20,0.04); --oc-tint-3: rgba(9,13,20,0.055);\n --oc-field-bg: #FFFFFF; --oc-field-border: rgba(9,13,20,0.22);\n --oc-glass-border: rgba(9,13,20,0.12);\n\n position: fixed; right: 24px; bottom: 24px; z-index: 2147483000;\n /* Explicit display/visibility so a host-page reset or consent/privacy tool that blanket-hides\n * body children (oyehello-chat { display:none }) can't silently kill the widget. Also pinned\n * inline with !important at mount (see element.ts) to beat an external !important rule. */\n display: block; visibility: visible; opacity: 1;\n font-family: 'Geist', system-ui, -apple-system, 'Helvetica Neue', sans-serif;\n -webkit-font-smoothing: antialiased;\n }\n @media (prefers-color-scheme: dark) {\n :host(:not([theme=\"light\"])) {\n --oc-bg: #000000; --oc-bg-sunk: #000000;\n --oc-fg: #FFFFFF; --oc-fg-muted: rgba(255,255,255,0.68); --oc-fg-dim: rgba(255,255,255,0.42);\n --oc-border: rgba(255,255,255,0.09);\n --oc-accent-text: color-mix(in oklab, var(--oc-ac) 62%, white);\n --oc-tint-1: rgba(255,255,255,0.03); --oc-tint-2: rgba(255,255,255,0.05); --oc-tint-3: rgba(255,255,255,0.07);\n --oc-field-bg: rgba(255,255,255,0.045); --oc-field-border: rgba(255,255,255,0.20);\n --oc-glass-border: rgba(255,255,255,0.12);\n }\n }\n :host([theme=\"dark\"]) {\n --oc-bg: #000000; --oc-bg-sunk: #000000;\n --oc-fg: #FFFFFF; --oc-fg-muted: rgba(255,255,255,0.68); --oc-fg-dim: rgba(255,255,255,0.42);\n --oc-border: rgba(255,255,255,0.09);\n --oc-accent-text: color-mix(in oklab, var(--oc-ac) 62%, white);\n --oc-tint-1: rgba(255,255,255,0.03); --oc-tint-2: rgba(255,255,255,0.05); --oc-tint-3: rgba(255,255,255,0.07);\n --oc-field-bg: rgba(255,255,255,0.045); --oc-field-border: rgba(255,255,255,0.20);\n --oc-glass-border: rgba(255,255,255,0.12);\n }\n * { box-sizing: border-box; }\n button { font-family: inherit; }\n\n .oc { display: flex; flex-direction: column; align-items: flex-end; gap: 14px; }\n\n /* ── Launcher ─────────────────────────────────────────────────────────────── */\n .launcher {\n position: relative; flex: none; width: 46px; height: 46px; border-radius: var(--oc-r-full);\n border: 1px solid var(--oc-btn-rim); background: var(--oc-ac);\n box-shadow: 0 8px 22px -8px color-mix(in oklab, var(--oc-ac) 70%, transparent), 0 18px 48px -18px rgba(0,0,0,0.6);\n color: #fff; display: flex; align-items: center; justify-content: center; cursor: pointer;\n transition: transform .26s var(--oc-bounce), filter .2s var(--oc-ease); align-self: flex-end;\n }\n .launcher:hover { transform: scale(1.06); }\n .launcher:active { transform: scale(0.93); }\n .ring { pointer-events: none; position: absolute; inset: -1px; border-radius: var(--oc-r-full); border: 2px solid var(--oc-ac); opacity: 0; }\n .oc.show-ring:not(.open) .ring { animation: w-ring 2.4s ease-out 1.1s 3; }\n .ic-chat, .ic-close { position: absolute; display: flex; align-items: center; justify-content: center; transition: all .3s var(--oc-bounce); }\n .ic-chat { width: 28px; height: 28px; opacity: 1; transform: rotate(0) scale(1); }\n .ic-close { opacity: 0; transform: rotate(90deg) scale(0.6); }\n .oc.open .ic-chat { opacity: 0; transform: rotate(-90deg) scale(0.6); }\n .oc.open .ic-close { opacity: 1; transform: rotate(0) scale(1); }\n .badge {\n position: absolute; top: -2px; right: -2px; min-width: 17px; height: 17px; padding: 0 5px;\n border-radius: var(--oc-r-full); border: 2px solid var(--oc-bg-sunk); background: var(--oc-danger);\n color: #fff; font-family: var(--oc-mono); font-size: 10px; font-weight: 700;\n display: flex; align-items: center; justify-content: center; opacity: 0; transform: scale(0.4);\n transition: all .26s var(--oc-bounce);\n }\n .oc.unread:not(.open) .badge { opacity: 1; transform: scale(1); }\n\n /* ── Teaser ───────────────────────────────────────────────────────────────── */\n .teaser {\n position: absolute; right: 0; bottom: 60px; display: none; align-items: center; gap: 11px;\n opacity: 0; transform: translateY(8px) scale(0.94); pointer-events: none;\n transition: opacity .3s var(--oc-ease), transform .38s var(--oc-bounce);\n }\n .oc.has-teaser .teaser { display: flex; }\n .oc.show-teaser:not(.open) .teaser { opacity: 1; transform: none; pointer-events: auto; }\n .teaser-btn {\n max-width: 250px; display: flex; align-items: center; gap: 10px; padding: 11px 15px;\n border-radius: 16px 16px 5px 16px; border: 1px solid var(--oc-glass-border); background: var(--oc-bg);\n box-shadow: 0 10px 30px -14px rgba(0,0,0,0.5); color: var(--oc-fg); font-size: 13.5px; line-height: 1.45;\n text-align: left; cursor: pointer; transition: transform .2s var(--oc-ease);\n }\n .teaser-btn:hover { transform: translateY(-1px); }\n .teaser-btn .logo { flex: none; width: 24px; height: 24px; border-radius: 6px; overflow: hidden; color: var(--oc-ac); }\n .teaser-x {\n flex: none; width: 22px; height: 22px; border-radius: var(--oc-r-full); border: 1px solid var(--oc-border);\n background: var(--oc-bg); color: var(--oc-fg-dim); display: flex; align-items: center; justify-content: center; cursor: pointer;\n }\n .teaser-x:hover { color: var(--oc-fg); }\n\n /* ── Panel ────────────────────────────────────────────────────────────────── */\n .panel {\n position: relative; width: min(384px, calc(100vw - 40px)); height: min(560px, calc(100vh - 108px));\n display: flex; flex-direction: column; border-radius: 20px; border: 1px solid var(--oc-glass-border);\n background: var(--oc-bg); box-shadow: 0 12px 28px -12px rgba(0,0,0,0.28), 0 40px 90px -30px rgba(0,0,0,0.55);\n overflow: hidden; transform-origin: bottom right;\n opacity: 0; transform: translateY(16px) scale(0.94); pointer-events: none; visibility: hidden;\n transition: opacity .24s var(--oc-ease), transform .34s var(--oc-bounce), visibility .34s, width .3s var(--oc-ease), height .3s var(--oc-ease);\n }\n .oc.open .panel { opacity: 1; transform: none; pointer-events: auto; visibility: visible; }\n .oc.max .panel { width: min(720px, calc(100vw - 40px)); height: calc(100vh - 108px); }\n\n .hd { position: relative; flex: none; display: flex; align-items: center; gap: 12px; padding: 13px 14px 12px; background: var(--oc-ac); color: #fff; overflow: hidden; }\n .hd-grid { pointer-events: none; position: absolute; inset: 0; background-image: linear-gradient(90deg, rgba(255,255,255,0.11) 1px, transparent 1px), linear-gradient(180deg, rgba(255,255,255,0.11) 1px, transparent 1px); background-size: 26px 26px; }\n .hd .logo { position: relative; flex: none; width: 32px; height: 32px; border-radius: 7px; overflow: hidden; color: rgba(255,255,255,0.22); }\n .hd-txt { position: relative; flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }\n .hd-title { font-size: 14.5px; font-weight: 600; letter-spacing: -0.015em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n .hd-status { display: flex; align-items: center; gap: 6px; font-size: 11.5px; opacity: 0.9; }\n .hd-status .dot { width: 6px; height: 6px; border-radius: var(--oc-r-full); background: #7BE3A6; flex: none; }\n .hd-status .t { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n .hd-btn { position: relative; flex: none; width: 28px; height: 28px; border-radius: 8px; border: none; background: rgba(255,255,255,0.16); color: #fff; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: background .18s var(--oc-ease); }\n .hd-btn:hover { background: rgba(255,255,255,0.28); }\n .hd-btn .i { position: absolute; display: flex; transition: opacity .2s var(--oc-ease); }\n .i-expand { opacity: 1; } .i-shrink { opacity: 0; }\n .oc.max .i-expand { opacity: 0; } .oc.max .i-shrink { opacity: 1; }\n\n /* Inline connection error, shown inside the chat window (no banner) */\n .oc-err { margin: auto; display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 24px 16px; text-align: center; }\n .oc-err-t { font-size: 13px; line-height: 1.5; color: var(--oc-fg-muted); text-wrap: pretty; }\n .oc-err-retry { padding: 7px 15px; font-size: 12.5px; font-weight: 500; border-radius: var(--oc-r-full); border: 1px solid var(--oc-border); background: var(--oc-tint-2); color: var(--oc-fg); cursor: pointer; transition: background .18s var(--oc-ease); }\n .oc-err-retry:hover { background: var(--oc-tint-3); }\n\n /* Session-ended state, inside the chat window */\n .oc-ended { margin: auto; display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 24px 16px; text-align: center; }\n .oc-ended-t { font-size: 13.5px; line-height: 1.5; color: var(--oc-fg-muted); text-wrap: pretty; }\n .oc-newmsg { padding: 9px 18px; font-size: 13px; font-weight: 600; border-radius: var(--oc-r-full); border: 1px solid var(--oc-btn-rim); background: var(--oc-ac); color: #fff; box-shadow: var(--oc-btn-edge); cursor: pointer; transition: filter .18s var(--oc-ease); }\n .oc-newmsg:hover { filter: brightness(1.08); }\n\n /* ── Message list ─────────────────────────────────────────────────────────── */\n .body { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 16px; padding: 16px 16px 26px; background: var(--oc-bg); scroll-behavior: smooth; }\n .turn { display: flex; flex-direction: column; gap: 6px; animation: w-in .42s var(--oc-ease) both; }\n .turn.bot { align-items: flex-start; } .turn.user { align-items: flex-end; }\n .b { font-size: 13.5px; line-height: 1.55; text-wrap: pretty; word-break: break-word; }\n .turn.bot .b { max-width: 86%; padding: 13px 15px; border-radius: 20px; background: var(--oc-tint-2); color: var(--oc-fg); }\n .turn.user .b { max-width: 82%; padding: 11px 15px; border-radius: var(--oc-r-full); background: var(--oc-ac); color: #fff; }\n .turn.human .b { max-width: 86%; padding: 13px 15px; border-radius: 20px; background: color-mix(in oklab, var(--oc-ac) 16%, transparent); color: var(--oc-fg); }\n .src { display: inline-flex; align-items: center; gap: 7px; padding: 5px 10px 5px 8px; border-radius: var(--oc-r-full); border: 1px solid var(--oc-border); background: var(--oc-tint-1); max-width: 100%; }\n .src .t { min-width: 0; font-size: 11.5px; color: var(--oc-fg-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .byline { display: flex; align-items: center; gap: 6px; padding: 0 4px; font-size: 11.5px; color: var(--oc-fg-dim); }\n .human-label { font-size: 11px; font-weight: 600; opacity: .7; margin-bottom: 2px; }\n\n /* markdown inside a bot bubble */\n .md > :first-child { margin-top: 0; } .md > :last-child { margin-bottom: 0; }\n .md p { margin: 0 0 8px; } .md ul, .md ol { margin: 0 0 8px; padding-left: 20px; } .md li { margin: 2px 0; }\n .md a { color: var(--oc-accent-text); text-decoration: underline; text-underline-offset: 2px; }\n .md code { font-family: var(--oc-mono); font-size: 12.5px; background: var(--oc-tint-3); padding: 1px 5px; border-radius: 5px; }\n .md pre { background: color-mix(in oklab, var(--oc-fg) 10%, transparent); padding: 10px 12px; border-radius: 8px; overflow-x: auto; margin: 0 0 8px; }\n .md pre code { background: none; padding: 0; }\n .md blockquote { margin: 0 0 8px; padding-left: 10px; border-left: 3px solid var(--oc-border); color: var(--oc-fg-muted); }\n .md h1, .md h2, .md h3, .md h4 { margin: 8px 0 6px; font-size: 15px; }\n .md table { border-collapse: collapse; font-size: 13px; margin: 0 0 8px; display: block; overflow-x: auto; }\n .md th, .md td { border: 1px solid var(--oc-border); padding: 4px 8px; }\n .att-thumb { display: block; max-width: 180px; max-height: 180px; border-radius: 8px; margin-bottom: 6px; }\n .att-chip { display: inline-block; font-size: 12px; background: var(--oc-tint-3); border-radius: 6px; padding: 2px 8px; margin: 0 0 6px; }\n .turn.user .att-chip { background: rgba(255,255,255,0.25); }\n\n .typing { align-self: flex-start; display: flex; align-items: center; gap: 5px; padding: 13px 16px; border-radius: 20px; background: var(--oc-tint-2); animation: w-in .3s var(--oc-ease) both; }\n .typing span { width: 6px; height: 6px; border-radius: var(--oc-r-full); background: var(--oc-fg-muted); animation: w-dot 1.2s ease-in-out infinite; }\n .typing span:nth-child(2) { animation-delay: .15s; } .typing span:nth-child(3) { animation-delay: .3s; }\n\n .chips { display: flex; flex-wrap: wrap; gap: 7px; padding-top: 2px; animation: w-in .42s var(--oc-ease) both; animation-delay: .3s; }\n .chip { padding: 8px 13px; border-radius: var(--oc-r-full); border: 1px solid color-mix(in oklab, var(--oc-ac) 34%, transparent); background: color-mix(in oklab, var(--oc-ac) 10%, transparent); color: var(--oc-accent-text); font-size: 12px; font-weight: 500; cursor: pointer; white-space: nowrap; transition: all .18s var(--oc-ease); }\n .chip:hover { background: color-mix(in oklab, var(--oc-ac) 18%, transparent); }\n\n /* ── Jump to latest ───────────────────────────────────────────────────────── */\n .jump-wrap { position: relative; flex: none; height: 0; z-index: 2; display: flex; justify-content: center; }\n .jump { position: absolute; bottom: 8px; width: 34px; height: 34px; border-radius: var(--oc-r-full); border: 1px solid var(--oc-border); background: var(--oc-bg); box-shadow: 0 8px 20px -10px rgba(0,0,0,0.5); color: var(--oc-fg-muted); display: flex; align-items: center; justify-content: center; cursor: pointer; opacity: 0; transform: translateY(6px) scale(0.8); pointer-events: none; transition: all .22s var(--oc-ease); }\n .oc.away .jump { opacity: 1; transform: none; pointer-events: auto; }\n .jump:hover { color: var(--oc-fg); border-color: var(--oc-fg-dim); }\n\n /* ── Composer ─────────────────────────────────────────────────────────────── */\n .composer { flex: none; display: flex; flex-direction: column; gap: 9px; padding: 12px 14px 13px; background: var(--oc-bg); }\n .composer[hidden] { display: none; }\n .field { display: flex; flex-direction: column; gap: 11px; padding: 13px 14px 11px; border-radius: 18px; border: 1px solid var(--oc-field-border); background: var(--oc-field-bg); transition: border-color .18s var(--oc-ease); }\n .oc.focus .field { border-color: var(--oc-ac); }\n .input { width: 100%; border: none; background: transparent; color: var(--oc-fg); font-size: 13.5px; line-height: 1.4; outline: none; padding: 0; resize: none; max-height: 108px; font-family: inherit; }\n .input::placeholder { color: var(--oc-fg-dim); }\n .acts { display: flex; align-items: center; gap: 16px; }\n .act { flex: none; display: flex; border: none; background: transparent; padding: 4px; margin: -4px; color: var(--oc-fg-dim); cursor: pointer; transition: color .18s var(--oc-ease); }\n .act:hover { color: var(--oc-fg-muted); }\n .oc.emoji .act.emoji-btn { color: var(--oc-accent-text); }\n .send { flex: none; margin-left: auto; width: 34px; height: 34px; border-radius: var(--oc-r-full); border: 1px solid var(--oc-border); background: var(--oc-tint-3); color: var(--oc-fg-dim); box-shadow: none; display: flex; align-items: center; justify-content: center; cursor: default; transition: all .22s var(--oc-ease); }\n .oc.ready .send { border-color: var(--oc-btn-rim); background: var(--oc-ac); color: #fff; box-shadow: var(--oc-btn-edge); cursor: pointer; }\n .oc.ready .send:hover { filter: brightness(1.1); }\n .send:active { transform: scale(0.92); }\n\n .foot { position: relative; display: none; text-align: center; font-size: 11.5px; line-height: 1.5; color: var(--oc-fg-dim); }\n .oc.has-privacy .foot { display: block; }\n .foot .priv { color: var(--oc-fg-muted); text-decoration: underline; text-underline-offset: 2px; cursor: default; }\n .foot .tip { position: absolute; left: 0; right: 0; bottom: 16px; padding-bottom: 8px; z-index: 7; display: flex; justify-content: flex-end; pointer-events: none; opacity: 0; transition: opacity .18s var(--oc-ease); }\n .oc.max .foot .tip { right: 188px; }\n .foot:hover .tip { opacity: 1; }\n .foot .tip-card { max-width: 100%; width: 262px; padding: 13px 15px; border-radius: 14px; border: 1px solid var(--oc-border); background: var(--oc-bg); box-shadow: 0 8px 22px -12px rgba(0,0,0,0.32); text-align: left; font-size: 11.5px; line-height: 1.55; color: var(--oc-fg-muted); text-wrap: pretty; transform: translateY(6px); transition: transform .24s var(--oc-bounce); }\n .foot:hover .tip-card { transform: none; }\n .foot .tip-card a { color: var(--oc-fg); text-decoration: underline; text-underline-offset: 2px; }\n\n /* ── Emoji picker ─────────────────────────────────────────────────────────── */\n .emoji-scrim { position: absolute; inset: 0; z-index: 3; display: none; }\n .oc.emoji .emoji-scrim { display: block; }\n .emoji-panel { position: absolute; left: 10px; right: 10px; bottom: 96px; z-index: 4; max-height: min(340px, 58%); display: flex; flex-direction: column; border-radius: 18px; border: 1px solid var(--oc-border); background: var(--oc-bg); box-shadow: 0 18px 46px -18px rgba(0,0,0,0.6); overflow: hidden; opacity: 0; transform: translateY(10px) scale(0.96); transform-origin: bottom center; pointer-events: none; visibility: hidden; transition: opacity .18s var(--oc-ease), transform .26s var(--oc-bounce), visibility .26s; }\n .oc.emoji .emoji-panel { opacity: 1; transform: none; pointer-events: auto; visibility: visible; }\n .emoji-search { flex: none; display: flex; align-items: center; gap: 11px; padding: 13px 16px; border-bottom: 1px solid var(--oc-border); color: var(--oc-fg-dim); }\n .emoji-search input { flex: 1 1 auto; min-width: 0; border: none; background: transparent; color: var(--oc-fg); font-size: 14.5px; outline: none; font-family: inherit; }\n .emoji-search input::placeholder { color: var(--oc-fg-dim); }\n .emoji-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; padding: 12px 14px 16px; }\n .emoji-grp { display: flex; flex-direction: column; gap: 6px; }\n .emoji-grp + .emoji-grp { padding-top: 8px; }\n .emoji-grp-name { font-family: var(--oc-mono); font-size: 9.5px; font-weight: 600; letter-spacing: 0.15em; text-transform: uppercase; color: var(--oc-fg-dim); }\n .emoji-grid { display: grid; grid-template-columns: repeat(7, minmax(0,1fr)); gap: 2px; }\n .emoji-grid button { display: flex; align-items: center; justify-content: center; height: 34px; border-radius: 8px; border: none; background: transparent; font-size: 20px; line-height: 1; cursor: pointer; transition: background .14s var(--oc-ease); }\n .emoji-grid button:hover { background: var(--oc-tint-3); }\n .emoji-empty { display: none; flex-direction: column; align-items: center; gap: 5px; padding: 26px 10px; text-align: center; }\n .emoji-empty .h { font-size: 14px; color: var(--oc-fg); } .emoji-empty .s { font-size: 12.5px; color: var(--oc-fg-dim); }\n\n @media (max-width: 480px) {\n :host { right: 0; bottom: 0; }\n .oc { padding: 0 16px 16px; }\n .panel { position: fixed; inset: 0; width: 100vw; height: 100dvh; border-radius: 0; }\n .oc.max .panel { width: 100vw; height: 100dvh; }\n }\n @media (prefers-reduced-motion: reduce) {\n .launcher, .panel, .teaser, .turn, .jump, .emoji-panel { transition: none; animation: none; }\n .ring { animation: none; } .body { scroll-behavior: auto; }\n }\n\n @keyframes w-in { from { opacity: 0; transform: translateY(10px) scale(0.97); } to { opacity: 1; transform: none; } }\n @keyframes w-dot { 0%,60%,100% { transform: translateY(0); opacity: .45; } 30% { transform: translateY(-4px); opacity: 1; } }\n @keyframes w-ring { 0% { transform: scale(1); opacity: .5; } 70%,100% { transform: scale(1.7); opacity: 0; } }\n`;\n","// SVG markup used across the widget, extracted from the design. Kept as strings so the element can\n// inline them into its shadow DOM without a dependency.\n\n// The OyeHello brand mark. `rectFill` colors the rounded-square backdrop; the glyph is always white.\nexport const logoMark = (rectFill: string) =>\n `<svg viewBox=\"0 0 1032 1024\" fill=\"none\" style=\"display:block;width:100%;height:100%\"><rect x=\"4\" width=\"1024\" height=\"1024\" rx=\"150\" fill=\"${rectFill}\"></rect><path d=\"M430.924 831.644C270.203 859.983 138.14 760.606 111.329 608.551C84.5174 456.497 174.627 317.945 335.348 289.605C496.068 261.266 628.131 360.643 654.943 512.698C681.754 664.752 591.644 803.304 430.924 831.644ZM406.613 693.77C488.549 679.323 518.727 615.513 505.252 539.092C491.777 462.671 441.594 413.031 359.658 427.478C277.722 441.926 247.544 505.736 261.02 582.157C274.495 658.578 324.677 708.218 406.613 693.77ZM870.337 558.389L744.281 580.616C727.055 482.923 674.565 369.515 652.06 241.884L841.143 208.543C863.509 335.387 853.111 460.696 870.337 558.389ZM910.583 740.568L768.771 765.573L745.016 630.852L886.828 605.846L910.583 740.568Z\" fill=\"#fff\"></path></svg>`;\n\nconst stroke = (w: number, path: string, size = 24) =>\n `<svg width=\"${size}\" height=\"${size}\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"${w}\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"display:block;flex:none\">${path}</svg>`;\n\nexport const ICON = {\n close: (size = 19) => stroke(2.4, '<path d=\"M18 6 6 18M6 6l12 12\"/>', size),\n minus: stroke(2, '<path d=\"M6 12h12\"/>', 15),\n expand: stroke(2, '<path d=\"M15 4h5v5M20 4l-6.5 6.5M9 20H4v-5M4 20l6.5-6.5\"/>', 15),\n shrink: stroke(2, '<path d=\"M20 9h-5V4M15 9l5.5-5.5M4 15h5v5M9 15l-5.5 5.5\"/>', 15),\n chevronDown: stroke(2.1, '<path d=\"m6 9 6 6 6-6\"/>', 16),\n send: stroke(2.2, '<path d=\"M12 19V5M6 11l6-6 6 6\"/>', 16),\n paperclip: stroke(1.7, '<path d=\"M21 11.5 12.5 20a5.5 5.5 0 0 1-7.8-7.8l8.5-8.5a3.7 3.7 0 0 1 5.2 5.2l-8.5 8.5a1.8 1.8 0 0 1-2.6-2.6l7.9-7.8\"/>', 17),\n emoji: stroke(1.7, '<circle cx=\"12\" cy=\"12\" r=\"9\"/><path d=\"M8.5 14.5a4.5 4.5 0 0 0 7 0M9 9.5h.01M15 9.5h.01\"/>', 17),\n mic: stroke(1.7, '<rect x=\"9\" y=\"3\" width=\"6\" height=\"11\" rx=\"3\"/><path d=\"M5 11a7 7 0 0 0 14 0M12 18v3\"/>', 17),\n search: stroke(1.9, '<circle cx=\"11\" cy=\"11\" r=\"7.5\"/><path d=\"m21 21-4.3-4.3\"/>', 17),\n clear: stroke(2.2, '<path d=\"M18 6 6 18M6 6l12 12\"/>', 15),\n // Two-page \"source\" glyph for citation chips.\n book: `<svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.7\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"display:block;flex:none;color:var(--oc-accent-text)\"><path d=\"M3 5.5A2.5 2.5 0 0 1 5.5 3H11v18H5.5A2.5 2.5 0 0 1 3 18.5Z\"/><path d=\"M21 5.5A2.5 2.5 0 0 0 18.5 3H13v18h5.5a2.5 2.5 0 0 0 2.5-2.5Z\"/></svg>`,\n teaserDismiss: stroke(2.4, '<path d=\"M18 6 6 18M6 6l12 12\"/>', 12),\n};\n","// Emoji catalogue + search for the composer's picker, ported from the design. Each entry is\n// [character, keyword]; the keyword is what the search box matches against.\nexport interface EmojiGroup { name: string; items: { ch: string; name: string }[] }\n\nconst CATS: { name: string; items: [string, string][] }[] = [\n { name: 'Frequently used', items: [\n ['👍', 'thumbs up'], ['🙏', 'thanks'], ['👋', 'wave'], ['✅', 'done'], ['📞', 'call'], ['😊', 'smile'], ['❤️', 'heart'],\n ] },\n { name: 'Smileys and emotion', items: [\n ['😀', 'grinning'], ['😃', 'smiley'], ['😄', 'grin'], ['😁', 'beaming'], ['😆', 'squinting'], ['😅', 'relief'], ['🤣', 'rolling'],\n ['😂', 'tears of joy'], ['🙂', 'slightly smiling'], ['🙃', 'upside down'], ['😉', 'wink'], ['😇', 'halo'], ['🥰', 'smiling hearts'], ['😍', 'heart eyes'],\n ['😘', 'kiss'], ['😋', 'yum'], ['🤔', 'thinking'], ['🤨', 'raised brow'], ['😐', 'neutral'], ['🙄', 'eye roll'], ['😬', 'grimace'],\n ['😥', 'sad'], ['😢', 'crying'], ['😭', 'sobbing'], ['😠', 'angry'], ['😳', 'flushed'], ['🤩', 'star struck'], ['😴', 'sleeping'],\n ] },\n { name: 'Gestures', items: [\n ['👎', 'thumbs down'], ['👏', 'clap'], ['🙌', 'raised hands'], ['🤝', 'handshake'], ['👌', 'ok hand'], ['✌️', 'victory'], ['💪', 'strong'],\n ['👀', 'eyes'], ['🧠', 'brain'], ['🤟', 'love you'], ['☝️', 'point up'], ['👇', 'point down'], ['🤚', 'raised back'], ['🤞', 'fingers crossed'],\n ] },\n { name: 'Work and travel', items: [\n ['📅', 'calendar'], ['📄', 'document'], ['💰', 'money'], ['📊', 'chart'], ['📦', 'package'], ['🏥', 'hospital'], ['🏦', 'bank'],\n ['🚚', 'truck'], ['✈️', 'plane'], ['📱', 'phone'], ['💻', 'laptop'], ['🔍', 'search'], ['📌', 'pin'], ['🔔', 'bell'],\n ] },\n { name: 'Symbols', items: [\n ['🔥', 'fire'], ['✨', 'sparkles'], ['🎉', 'celebrate'], ['💯', 'hundred'], ['⚠️', 'warning'], ['❌', 'cross'], ['⭐', 'star'],\n ['🚀', 'launch'], ['💚', 'green heart'], ['💙', 'blue heart'], ['🕒', 'clock'], ['💡', 'idea'], ['🔒', 'lock'], ['🎯', 'target'],\n ] },\n];\n\nconst toGroup = (name: string, items: [string, string][]): EmojiGroup => ({\n name,\n items: items.map(([ch, kw]) => ({ ch, name: kw })),\n});\n\n// No query → all categories. With a query → a single group of de-duped keyword matches (mirrors the\n// design's search behaviour), or an empty array when nothing matches (the caller shows an empty state).\nexport function emojiGroups(query: string): EmojiGroup[] {\n const q = query.trim().toLowerCase();\n if (!q) return CATS.map((c) => toGroup(c.name, c.items));\n const hits: [string, string][] = [];\n for (const c of CATS) for (const e of c.items) {\n if (e[1].indexOf(q) >= 0 && !hits.some((h) => h[0] === e[0])) hits.push(e);\n }\n if (!hits.length) return [];\n return [toGroup(`${hits.length} result${hits.length === 1 ? '' : 's'}`, hits)];\n}\n","import { createChatClient, type ChatClient, type ChatClientEvent, type ChatMessage, type ChatClientState, type ChatToolHandler, type HandoffState } from './client';\nimport { recordView, installSpaHooks } from './journey';\nimport type { ChatAttachmentDescriptor } from './protocol';\nimport { renderMarkdown } from './markdown';\nimport { STYLES } from './styles';\nimport { ICON, logoMark } from './icons';\nimport { emojiGroups } from './emoji';\n\nconst AGENT_TYPING_TEXT = 'The agent is typing…';\nconst DEFAULT_STATUS = 'Replies in a few seconds';\nconst ATTACHMENT_ACCEPT = 'image/*,application/pdf,text/plain,text/csv';\n// Distance (px) from the bottom past which we treat the reader as scrolled-up (\"away\").\nconst AWAY_THRESHOLD = 60;\n\nconst HANDOFF_STATUS: Record<HandoffState, string | null> = {\n ai: null,\n awaiting_human: 'Connecting you to a person…',\n human: \"You're chatting with a person\",\n};\n\nexport class OyehelloChatElement extends HTMLElement {\n static observedAttributes = ['api-key', 'agent-id', 'base-url', 'title', 'theme'];\n\n // ── live client state ──\n private client: ChatClient | null = null;\n private off: (() => void) | null = null;\n private messages: ChatMessage[] = [];\n private state: ChatClientState = 'idle';\n private agentName: string | null = null;\n private handoffState: HandoffState = 'ai';\n private agentTyping = false;\n private lastError: string | null = null;\n private pendingTools: Record<string, ChatToolHandler> = {};\n private pendingFiles: File[] = [];\n private imagePreviewCache = new Map<string, string>();\n private resolvedUrlCache = new Map<string, string>();\n private mdCache = new Map<string, string>();\n private receivedAt = new Map<string, number>();\n\n // ── widget UI state ──\n private uiOpen = false;\n private started = false;\n private uiMax = false;\n private emojiOpen = false;\n private emojiQuery = '';\n private away = false; // reader scrolled up\n private unseen = 0;\n private focused = false;\n private teaserActive = false;\n private renderedCount = 0;\n private renderedBotFinal = 0;\n private timers: ReturnType<typeof setTimeout>[] = [];\n // Server (flow) suggestions for the latest turn; null until the first `suggestions` event, then the\n // widget prefers these over the static `suggestions` attribute.\n private serverSuggestions: string[] | null = null;\n // The live streaming assistant bubble's markdown element + message id — so growing tokens patch just\n // that element in place instead of rebuilding the whole message list on every token.\n private streamId: string | null = null;\n private streamEl: HTMLElement | null = null;\n private audioCtx: AudioContext | null = null;\n private teaserText = 'Need a hand? Ask me anything.';\n private teaserShownOnce = false;\n // Staffed-hours: set from widget-config. When offline, the panel shows offlineMessage and the\n // composer is disabled (opening a session is refused server-side anyway).\n private offline = false;\n private offlineMessage = \"We're offline right now. Please check back during business hours.\";\n private configLoaded = false; // widget-config resolved (so we know online/offline before starting)\n private idleTimer: ReturnType<typeof setTimeout> | null = null;\n private idleReset: (() => void) | null = null;\n // Uninstaller for the SPA history-navigation hooks (journey tracking), installed in\n // connectedCallback and torn down in disconnectedCallback alongside everything else.\n private uninstallSpaHooks: (() => void) | null = null;\n\n // ── shadow refs ──\n private oc!: HTMLElement;\n private bodyEl!: HTMLElement;\n private textareaEl!: HTMLTextAreaElement;\n private composerEl!: HTMLElement;\n private fileEl!: HTMLInputElement;\n private titleEl!: HTMLElement;\n private statusEl!: HTMLElement;\n private emojiListEl!: HTMLElement;\n private emojiSearchEl!: HTMLInputElement;\n\n connectedCallback() {\n if (!this.shadowRoot) this.attachShadow({ mode: 'open' });\n const apiKey = this.getAttribute('api-key');\n const agentId = this.getAttribute('agent-id');\n const baseUrl = this.getAttribute('base-url');\n if (!apiKey || !agentId || !baseUrl) { this.renderError('oyehello-chat: api-key, agent-id and base-url are required'); return; }\n // A `teaser` attribute overrides the server/default text; otherwise the config endpoint supplies it.\n this.teaserText = this.getAttribute('teaser') || this.teaserText;\n this.client = createChatClient({ apiKey, agentId, baseUrl });\n if (Object.keys(this.pendingTools).length > 0) { this.client.registerTools(this.pendingTools); this.pendingTools = {}; }\n this.off = this.client.on((e) => this.onClientEvent(e));\n // Visitor-journey tracking (Task 21): record the current page on every mount - this is what makes\n // Astro's multi-page (full-reload) navigation work, since the element re-mounts fresh on each load.\n // installSpaHooks covers client-routed sites, where the element stays mounted across navigation.\n recordView(agentId, location.pathname);\n // installSpaHooks is written to never throw, but this call site is guarded too - defense in\n // depth, so a host page that manages to make it throw anyway can never abort connectedCallback\n // before renderShell() runs (which would leave the widget entirely unrendered).\n try { this.uninstallSpaHooks = installSpaHooks(() => this.client?.recordPageView(location.pathname)); }\n catch { this.uninstallSpaHooks = null; }\n this.renderShell();\n // Pin the critical visibility inline with !important so a host-page stylesheet (a reset, or a\n // consent/privacy tool that hides body children) can't blank the widget - inline !important beats\n // any external rule, even !important. Positioning stays in the shadow :host rule.\n this.style.setProperty('display', 'block', 'important');\n this.style.setProperty('visibility', 'visible', 'important');\n this.style.setProperty('opacity', '1', 'important');\n this.renderMessages();\n this.updateHeader();\n this.updateStatus();\n this.updateClasses();\n void this.loadWidgetConfig();\n\n let wasOpen = false;\n try { wasOpen = sessionStorage.getItem(this.key('open')) === '1'; } catch { /* blocked */ }\n if (wasOpen) { this.openPanel(); return; }\n\n // Launcher ring (a few pulses to draw the eye) + a teaser nudge after the visitor sits idle.\n this.updateClasses(true);\n this.timers.push(setTimeout(() => { this.oc?.classList.remove('show-ring'); }, 6000));\n this.armIdleTeaser();\n }\n\n // Show the teaser once the visitor has been idle (no page interaction) for 10s — unless the panel\n // is already open or the teaser was dismissed this session. Fires at most once.\n private armIdleTeaser() {\n let dismissed = false;\n try { dismissed = sessionStorage.getItem(this.key('teaser')) === '0'; } catch { /* ignore */ }\n if (dismissed) return;\n const reset = () => {\n if (this.idleTimer) clearTimeout(this.idleTimer);\n this.idleTimer = setTimeout(() => {\n if (!this.uiOpen && !this.teaserShownOnce) { this.teaserActive = true; this.teaserShownOnce = true; this.updateClasses(); this.teardownIdle(); }\n }, 10000);\n };\n this.idleReset = reset;\n for (const ev of ['mousemove', 'keydown', 'scroll', 'touchstart', 'click']) document.addEventListener(ev, reset, { passive: true });\n reset();\n }\n private teardownIdle() {\n if (this.idleTimer) { clearTimeout(this.idleTimer); this.idleTimer = null; }\n if (this.idleReset) { for (const ev of ['mousemove', 'keydown', 'scroll', 'touchstart', 'click']) document.removeEventListener(ev, this.idleReset); this.idleReset = null; }\n }\n\n private async loadWidgetConfig() {\n try {\n const cfg = await this.client!.getWidgetConfig();\n if (!this.getAttribute('teaser') && cfg.teaser) { this.teaserText = cfg.teaser; this.applyTeaserText(); }\n if (cfg.brand) {\n if (cfg.brand.accentColor) this.style.setProperty('--oc-accent', cfg.brand.accentColor);\n if (cfg.brand.name && !this.getAttribute('title')) { this.agentName = cfg.brand.name; this.updateHeader(); }\n if (cfg.brand.logoUrl) this.applyBrandLogo(cfg.brand.logoUrl);\n }\n if (cfg.offline) {\n this.offline = true;\n if (cfg.offlineMessage) this.offlineMessage = cfg.offlineMessage;\n this.renderMessages();\n this.updateStatus();\n }\n } catch { /* non-fatal: defaults stand */ }\n finally {\n // Config is now known. If the panel was opened before it resolved (restore path / a fast click),\n // openPanel deferred the session start to avoid opening one the server would refuse while offline;\n // start it now, unless we're offline.\n this.configLoaded = true;\n if (this.uiOpen && !this.started && !this.offline && this.client) { this.started = true; void this.client.start(); }\n }\n }\n private applyTeaserText() {\n const el = this.shadowRoot?.querySelector('.teaser-btn span:last-child');\n if (el) el.textContent = this.teaserText;\n }\n private applyBrandLogo(url: string) {\n // Set via DOM (img.src property, not innerHTML) so the URL can't be an HTML-injection vector.\n const set = (host: Element | null | undefined) => {\n if (!host) return;\n host.textContent = '';\n const img = document.createElement('img');\n img.src = url; img.alt = '';\n img.style.cssText = 'width:100%;height:100%;object-fit:contain';\n host.appendChild(img);\n };\n set(this.shadowRoot?.querySelector('.hd .logo'));\n set(this.shadowRoot?.querySelector('.teaser-btn .logo'));\n }\n\n disconnectedCallback() {\n // Detach, do NOT end: a transient unmount (framework nav / Astro View Transitions) then re-mounts\n // and resumes the same session, instead of the widget killing the chat + opening a new one on every\n // navigation (the \"launcher comes and goes / new chat each time\" symptom). A real page close leaves\n // the session for the idle sweep.\n this.off?.(); this.client?.detach();\n this.teardownIdle();\n this.uninstallSpaHooks?.(); this.uninstallSpaHooks = null;\n for (const t of this.timers) clearTimeout(t);\n for (const url of this.imagePreviewCache.values()) { if (typeof URL.revokeObjectURL === 'function') URL.revokeObjectURL(url); }\n this.imagePreviewCache.clear();\n }\n\n registerTools(handlers: Record<string, ChatToolHandler>) {\n if (this.client) this.client.registerTools(handlers);\n else Object.assign(this.pendingTools, handlers);\n }\n\n private key(k: string) { return `oyehello-chat:${k}:${this.getAttribute('agent-id') ?? ''}`; }\n // Static fallback chips from the `suggestions` attribute (for embedders without flow-driven ones).\n private get attrSuggestions(): string[] {\n return (this.getAttribute('suggestions') ?? '').split(',').map((s) => s.trim()).filter(Boolean);\n }\n // Effective chips: server (flow) suggestions once received, else the static attribute fallback.\n private get chipLabels(): string[] {\n return this.serverSuggestions ?? this.attrSuggestions;\n }\n\n // ── Shell (built once) ─────────────────────────────────────────────────────────────────────────\n private renderShell() {\n const root = this.shadowRoot!;\n const hasPrivacy = !!this.getAttribute('privacy-url');\n const teaserText = this.teaserText;\n root.innerHTML = `\n <style>${STYLES}</style>\n <div class=\"oc has-teaser${hasPrivacy ? ' has-privacy' : ''}\">\n <div class=\"panel\" role=\"dialog\" aria-label=\"Chat\">\n <div class=\"hd\">\n <span class=\"hd-grid\"></span>\n <span class=\"logo\">${logoMark('currentColor')}</span>\n <span class=\"hd-txt\"><span class=\"hd-title\">Chat</span><span class=\"hd-status\"><span class=\"dot\"></span><span class=\"t\"></span></span></span>\n <button type=\"button\" class=\"hd-btn max\" aria-label=\"Expand\"><span class=\"i i-expand\">${ICON.expand}</span><span class=\"i i-shrink\">${ICON.shrink}</span></button>\n <button type=\"button\" class=\"hd-btn min\" aria-label=\"Minimise\">${ICON.minus}</button>\n </div>\n <div class=\"body\"></div>\n <span class=\"emoji-scrim\"></span>\n <div class=\"emoji-panel\">\n <div class=\"emoji-search\">${ICON.search}<input type=\"text\" placeholder=\"Search emoji…\" aria-label=\"Search emoji\" /></div>\n <div class=\"emoji-list\"></div>\n </div>\n <div class=\"jump-wrap\"><button type=\"button\" class=\"jump\" aria-label=\"Jump to latest\">${ICON.chevronDown}</button></div>\n <div class=\"composer\">\n <form class=\"field\">\n <textarea class=\"input\" rows=\"1\" aria-label=\"message\" placeholder=\"Ask a question…\"></textarea>\n <div class=\"acts\">\n <button type=\"button\" class=\"act attach\" aria-label=\"Attach a file\">${ICON.paperclip}</button>\n <input type=\"file\" accept=\"${ATTACHMENT_ACCEPT}\" multiple hidden />\n <button type=\"button\" class=\"act emoji-btn\" aria-label=\"Insert emoji\">${ICON.emoji}</button>\n <button type=\"button\" class=\"act mic\" aria-label=\"Send a voice note\">${ICON.mic}</button>\n <button type=\"submit\" class=\"send\" aria-label=\"Send\">${ICON.send}</button>\n </div>\n </form>\n <div class=\"foot\">\n <span>By chatting with us, you agree to our </span><span class=\"priv\">Privacy Policy</span>\n <span class=\"tip\"><span class=\"tip-card\">By chatting with us, you agree to the monitoring and recording of this chat to deliver our services and processing of your personal data in accordance with our Privacy Policy. <a href=\"${this.escapeAttr(this.getAttribute('privacy-url') ?? '#')}\" target=\"_blank\" rel=\"noopener noreferrer\">See our Privacy Policy</a>.</span></span>\n </div>\n </div>\n </div>\n\n <div class=\"teaser\">\n <button type=\"button\" class=\"teaser-btn\"><span class=\"logo\">${logoMark('currentColor')}</span><span>${escapeHtml(teaserText)}</span></button>\n <button type=\"button\" class=\"teaser-x\" aria-label=\"Dismiss\">${ICON.teaserDismiss}</button>\n </div>\n\n <button type=\"button\" class=\"launcher\" aria-label=\"Open chat\">\n <span class=\"ring\"></span>\n <span class=\"ic-chat\">${logoMark('var(--oc-ac)')}</span>\n <span class=\"ic-close\">${ICON.close(19)}</span>\n <span class=\"badge\"></span>\n </button>\n </div>`;\n\n this.oc = root.querySelector('.oc')!;\n this.bodyEl = root.querySelector('.body')!;\n this.textareaEl = root.querySelector('textarea.input')!;\n this.composerEl = root.querySelector('.composer')!;\n this.fileEl = root.querySelector('input[type=\"file\"]')!;\n this.titleEl = root.querySelector('.hd-title')!;\n this.statusEl = root.querySelector('.hd-status .t')!;\n this.emojiListEl = root.querySelector('.emoji-list')!;\n this.emojiSearchEl = root.querySelector('.emoji-search input')!;\n\n root.querySelector('.launcher')!.addEventListener('click', () => this.toggle());\n root.querySelector('.hd-btn.min')!.addEventListener('click', () => this.closePanel());\n root.querySelector('.hd-btn.max')!.addEventListener('click', () => { this.uiMax = !this.uiMax; this.updateClasses(); });\n root.querySelector('.teaser-btn')!.addEventListener('click', () => this.openPanel());\n root.querySelector('.teaser-x')!.addEventListener('click', () => this.dismissTeaser());\n root.querySelector('.jump')!.addEventListener('click', () => this.scrollToBottom());\n root.querySelector('.attach')!.addEventListener('click', () => this.fileEl.click());\n this.fileEl.addEventListener('change', () => { this.pendingFiles = this.fileEl.files ? Array.from(this.fileEl.files) : []; });\n root.querySelector('.emoji-btn')!.addEventListener('click', () => this.toggleEmoji());\n root.querySelector('.emoji-scrim')!.addEventListener('click', () => this.closeEmoji());\n this.emojiSearchEl.addEventListener('input', () => { this.emojiQuery = this.emojiSearchEl.value; this.renderEmoji(); });\n this.bodyEl.addEventListener('scroll', () => this.onScroll());\n root.querySelector('form.field')!.addEventListener('submit', (e) => { e.preventDefault(); this.doSend(); });\n this.textareaEl.addEventListener('input', () => { this.autoGrow(); this.updateClasses(); });\n this.textareaEl.addEventListener('focus', () => { this.focused = true; this.updateClasses(); });\n this.textareaEl.addEventListener('blur', () => { this.focused = false; this.updateClasses(); });\n this.textareaEl.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey && !e.isComposing) { e.preventDefault(); this.doSend(); }\n if (e.key === 'Escape') { if (this.emojiOpen) this.closeEmoji(); else this.closePanel(); }\n });\n }\n\n private renderError(msg: string) {\n if (!this.shadowRoot) this.attachShadow({ mode: 'open' });\n // eslint-disable-next-line no-console\n console.error(msg);\n this.shadowRoot!.innerHTML = `<div style=\"position:fixed;right:16px;bottom:16px;color:#b91c1c;font:12px system-ui;background:#fef2f2;border:1px solid #fecaca;padding:8px 12px;border-radius:8px\">${escapeHtml(msg)}</div>`;\n }\n\n // ── State-class sync ──────────────────────────────────────────────────────────────────────────\n // State classes on `.oc` MUST NOT share a name with any element class that has a bare base rule\n // (e.g. `.teaser`, `.ring`): the bare selector would also match `.oc.<state>` and, tying `.oc`'s\n // own rule on specificity, win on source order — e.g. `.teaser{display:none}` would hide the whole\n // widget. Hence the `show-` prefix on the teaser/ring state classes.\n private updateClasses(initialRing = false) {\n if (!this.oc) return;\n const c = this.oc.classList;\n c.toggle('open', this.uiOpen);\n c.toggle('max', this.uiMax);\n c.toggle('emoji', this.emojiOpen);\n c.toggle('show-teaser', this.teaserActive);\n c.toggle('away', this.away);\n c.toggle('focus', this.focused);\n c.toggle('ready', (this.textareaEl?.value.trim().length ?? 0) > 0);\n c.toggle('unread', this.unseen > 0);\n if (initialRing) c.add('show-ring');\n const badge = this.oc.querySelector('.badge');\n if (badge) badge.textContent = this.unseen > 9 ? '9+' : String(this.unseen);\n const launcher = this.oc.querySelector('.launcher');\n if (launcher) launcher.setAttribute('aria-label', this.uiOpen ? 'Close chat' : 'Open chat');\n }\n\n // ── Open / close ───────────────────────────────────────────────────────────────────────────────\n private toggle() { this.uiOpen ? this.closePanel() : this.openPanel(); }\n private openPanel() {\n this.uiOpen = true; this.teaserActive = false; this.unseen = 0;\n this.teardownIdle();\n try { sessionStorage.setItem(this.key('open'), '1'); } catch { /* ignore */ }\n // Don't open a session before widget-config has resolved (we might be offline, and the server would\n // refuse it → the widget would show an error instead of the offline message). If the panel opens\n // first, loadWidgetConfig's finally starts the session once config is known (and not offline).\n if (!this.started && this.client && this.configLoaded && !this.offline) { this.started = true; void this.client.start(); }\n this.updateClasses();\n this.renderMessages();\n this.scrollToBottom();\n if (!this.textareaEl.disabled) setTimeout(() => this.textareaEl.focus(), 60);\n }\n private closePanel() {\n this.uiOpen = false; this.uiMax = false; this.emojiOpen = false;\n try { sessionStorage.setItem(this.key('open'), '0'); } catch { /* ignore */ }\n this.updateClasses();\n }\n private dismissTeaser() {\n this.teaserActive = false;\n try { sessionStorage.setItem(this.key('teaser'), '0'); } catch { /* ignore */ }\n this.updateClasses();\n }\n\n // ── Client events ─────────────────────────────────────────────────────────────────────────────\n private onClientEvent(e: ChatClientEvent) {\n if (e.type === 'messages') this.messages = e.messages;\n else if (e.type === 'state') { this.state = e.state; if (e.state === 'ready' || e.state === 'opening') this.lastError = null; }\n else if (e.type === 'agent') { this.agentName = e.agent.name; this.updateHeader(); }\n else if (e.type === 'handoff') this.handoffState = e.state;\n else if (e.type === 'agentTyping') this.agentTyping = e.active;\n else if (e.type === 'suggestions') this.serverSuggestions = e.items;\n else if (e.type === 'error') this.lastError = e.error.message;\n this.updateStatus();\n this.renderMessages();\n }\n\n private updateHeader() {\n if (this.titleEl) this.titleEl.textContent = this.getAttribute('title') ?? this.agentName ?? 'Chat';\n }\n\n private updateStatus() {\n if (!this.textareaEl) return;\n const disabled = this.state !== 'ready' || this.offline;\n this.textareaEl.disabled = disabled;\n // Once the conversation has ended, hide the composer entirely (not just disable it) - the \"New\n // message\" button in the body is the only way forward. Also hidden while offline (no session).\n if (this.composerEl) this.composerEl.hidden = this.state === 'ended' || this.offline;\n const handoff = HANDOFF_STATUS[this.handoffState];\n const text = this.offline ? 'Offline' : this.state === 'opening' ? 'Connecting…' : handoff ?? (this.getAttribute('status') ?? DEFAULT_STATUS);\n if (this.statusEl) this.statusEl.textContent = text;\n // A connection error is shown inline inside the chat window (see renderMessages), not as a banner.\n }\n\n // ── Message list + scroll ─────────────────────────────────────────────────────────────────────\n private renderMessages() {\n if (!this.bodyEl) return;\n const body = this.bodyEl;\n const last = this.messages[this.messages.length - 1];\n\n // Fast path — the streaming assistant reply grew: patch ONLY its bubble's text instead of\n // rebuilding the whole list (no per-token flicker, other bubbles untouched, scroll preserved).\n if (this.uiOpen && this.streamEl && last && last.id === this.streamId\n && last.role === 'assistant' && last.streaming && this.messages.length === this.renderedCount) {\n this.streamEl.innerHTML = renderMarkdown(last.text || '');\n if (!this.away) this.scrollToBottom();\n return;\n }\n\n const prevTop = body.scrollTop;\n const added = this.messages.length - this.renderedCount;\n const botFinal = this.messages.filter((m) => m.role === 'assistant' && !m.streaming).length;\n const newBotFinal = botFinal > this.renderedBotFinal;\n\n const now = Date.now();\n for (const m of this.messages) if (!this.receivedAt.has(m.id)) this.receivedAt.set(m.id, now);\n\n const lastBot = (() => { for (let i = this.messages.length - 1; i >= 0; i--) if (this.messages[i]?.role === 'assistant') return i; return -1; })();\n let html = this.messages.map((m, i) => this.turnHtml(m, i === lastBot && !this.agentTyping)).join('');\n if (this.agentTyping) html += '<span class=\"typing\"><span></span><span></span><span></span></span>';\n const sugg = this.chipLabels;\n if (sugg.length > 0 && !this.agentTyping && this.state === 'ready') {\n html += `<span class=\"chips\">${sugg.map((s, i) => `<button type=\"button\" class=\"chip\" data-chip=\"${i}\">${escapeHtml(s)}</button>`).join('')}</span>`;\n }\n // Connection error, inline inside the chat window (subtle — no red banner), only when present.\n if (this.state === 'error' && this.lastError) {\n html += `<div class=\"oc-err\"><span class=\"oc-err-t\">${escapeHtml(this.lastError)}</span><button type=\"button\" class=\"oc-err-retry\">Try again</button></div>`;\n }\n // Session ended (flow finished, idle sweep, or a console close): offer a fresh conversation.\n if (this.state === 'ended') {\n html += `<div class=\"oc-ended\"><span class=\"oc-ended-t\">Your conversation has ended.</span><button type=\"button\" class=\"oc-newmsg\">New message</button></div>`;\n }\n // Outside staffed hours: show the offline message (no session has been opened; server refuses one).\n if (this.offline && this.messages.length === 0 && this.state !== 'ended') {\n html += `<div class=\"oc-ended\"><span class=\"oc-ended-t\">${escapeHtml(this.offlineMessage)}</span></div>`;\n }\n body.innerHTML = html;\n this.hydrateAttachmentImages();\n this.bindChips();\n this.renderedCount = this.messages.length;\n this.renderedBotFinal = botFinal;\n\n // Capture the streaming bubble so subsequent token growth hits the fast path above.\n this.streamId = null;\n this.streamEl = null;\n if (last && last.role === 'assistant' && last.streaming) {\n const mds = this.bodyEl.querySelectorAll<HTMLElement>('.turn.bot .md');\n this.streamEl = mds[mds.length - 1] ?? null;\n if (this.streamEl) this.streamId = last.id;\n }\n\n if (!this.uiOpen) { if (added > 0) { this.unseen += added; this.maybeChime(); } this.updateClasses(); return; }\n if (newBotFinal && !this.away) this.parkLastQuestion();\n else if (!this.away) this.scrollToBottom();\n else { body.scrollTop = prevTop; if (added > 0) { this.unseen += added; this.maybeChime(); } }\n this.updateClasses();\n }\n\n // After a reply lands, float the question that prompted it to the top so the answer reads from its\n // first line rather than its last (the design's behaviour).\n private parkLastQuestion() {\n const users = this.bodyEl.querySelectorAll<HTMLElement>('.turn.user');\n const last = users[users.length - 1];\n if (!last) { this.scrollToBottom(); return; }\n const top = Math.max(0, Math.min(last.offsetTop - 22, this.bodyEl.scrollHeight - this.bodyEl.clientHeight));\n this.bodyEl.scrollTo({ top, behavior: 'smooth' });\n }\n\n private onScroll() {\n const b = this.bodyEl;\n const away = b.scrollHeight - b.scrollTop - b.clientHeight > AWAY_THRESHOLD;\n if (away !== this.away) { this.away = away; if (!away) this.unseen = 0; this.updateClasses(); }\n }\n private scrollToBottom() {\n if (!this.bodyEl) return;\n this.bodyEl.scrollTop = this.bodyEl.scrollHeight;\n this.away = false; this.unseen = 0;\n this.updateClasses();\n }\n\n // ── Composer ──────────────────────────────────────────────────────────────────────────────────\n private autoGrow() {\n const ta = this.textareaEl;\n ta.style.height = 'auto';\n ta.style.height = `${Math.min(ta.scrollHeight, 108)}px`;\n }\n private doSend() {\n const text = this.textareaEl.value;\n if (!text.trim()) return;\n const files = this.pendingFiles; this.pendingFiles = []; this.fileEl.value = '';\n for (const f of files) {\n if (f.type.startsWith('image/') && typeof URL.createObjectURL === 'function' && !this.imagePreviewCache.has(f.name)) {\n this.imagePreviewCache.set(f.name, URL.createObjectURL(f));\n }\n }\n this.away = false; this.emojiOpen = false; this.serverSuggestions = []; // hide chips until the next turn's arrive\n void this.client?.sendMessage(text, files.length > 0 ? files : undefined);\n this.textareaEl.value = ''; this.textareaEl.style.height = 'auto';\n this.updateClasses();\n }\n private sendChip(text: string) {\n this.away = false; this.emojiOpen = false; this.serverSuggestions = []; // hide chips until the next turn's arrive\n void this.client?.sendMessage(text);\n this.updateClasses();\n }\n private bindChips() {\n const sugg = this.chipLabels;\n this.bodyEl.querySelectorAll<HTMLButtonElement>('.chip[data-chip]').forEach((btn) => {\n const i = Number(btn.getAttribute('data-chip'));\n const text = sugg[i];\n if (text) btn.addEventListener('click', () => this.sendChip(text));\n });\n // Inline connection-error retry (rendered in the body, not a banner).\n this.bodyEl.querySelector('.oc-err-retry')?.addEventListener('click', () => { void this.client?.start(); });\n // \"New message\" after a session ended → fresh conversation.\n this.bodyEl.querySelector('.oc-newmsg')?.addEventListener('click', () => this.startFresh());\n }\n\n // Reset the thread and open a brand-new session (the widget's \"New message\" after a session ended).\n private startFresh() {\n this.serverSuggestions = null;\n this.receivedAt.clear();\n this.mdCache.clear();\n this.streamId = null; this.streamEl = null;\n this.renderedCount = 0; this.renderedBotFinal = 0;\n this.away = false; this.unseen = 0;\n this.client?.reset();\n this.started = true;\n void this.client?.start();\n setTimeout(() => this.textareaEl?.focus(), 60);\n }\n\n // A short two-tone chime for an incoming message the visitor hasn't seen (panel closed or scrolled\n // up). Off when the `sound=\"off\"` attribute is set. Uses WebAudio (no asset); silent if unavailable\n // or the browser hasn't allowed audio yet.\n private maybeChime() {\n const last = this.messages[this.messages.length - 1];\n if (last && (last.role === 'assistant' || last.role === 'human')) this.playChime();\n }\n private playChime() {\n if (this.getAttribute('sound') === 'off') return;\n try {\n const Ctx = window.AudioContext ?? (window as unknown as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;\n if (!Ctx) return;\n if (!this.audioCtx) this.audioCtx = new Ctx();\n const ctx = this.audioCtx;\n if (ctx.state === 'suspended') void ctx.resume();\n const now = ctx.currentTime;\n [880, 1174.66].forEach((freq, i) => {\n const osc = ctx.createOscillator();\n const gain = ctx.createGain();\n osc.type = 'sine';\n osc.frequency.value = freq;\n const t = now + i * 0.11;\n gain.gain.setValueAtTime(0.0001, t);\n gain.gain.exponentialRampToValueAtTime(0.12, t + 0.02);\n gain.gain.exponentialRampToValueAtTime(0.0001, t + 0.18);\n osc.connect(gain);\n gain.connect(ctx.destination);\n osc.start(t);\n osc.stop(t + 0.2);\n });\n } catch { /* audio unavailable */ }\n }\n\n // ── Emoji ─────────────────────────────────────────────────────────────────────────────────────\n private toggleEmoji() { this.emojiOpen = !this.emojiOpen; this.emojiQuery = ''; this.emojiSearchEl.value = ''; this.renderEmoji(); this.updateClasses(); if (this.emojiOpen) setTimeout(() => this.emojiSearchEl.focus(), 60); }\n private closeEmoji() { this.emojiOpen = false; this.emojiQuery = ''; this.updateClasses(); }\n private renderEmoji() {\n const groups = emojiGroups(this.emojiQuery);\n let html = groups.map((g) => `\n <div class=\"emoji-grp\"><span class=\"emoji-grp-name\">${escapeHtml(g.name)}</span>\n <div class=\"emoji-grid\">${g.items.map((e) => `<button type=\"button\" title=\"${this.escapeAttr(e.name)}\" aria-label=\"${this.escapeAttr(e.name)}\" data-ch=\"${this.escapeAttr(e.ch)}\">${e.ch}</button>`).join('')}</div>\n </div>`).join('');\n if (groups.length === 0) html = '<span class=\"emoji-empty\" style=\"display:flex\"><span class=\"h\">No emoji match that</span><span class=\"s\">Try a shorter word, like smile or call.</span></span>';\n this.emojiListEl.innerHTML = html;\n this.emojiListEl.querySelectorAll<HTMLButtonElement>('button[data-ch]').forEach((btn) => {\n btn.addEventListener('click', () => {\n this.textareaEl.value += btn.getAttribute('data-ch') ?? '';\n this.emojiOpen = false;\n this.autoGrow();\n this.updateClasses();\n this.textareaEl.focus();\n });\n });\n }\n\n // ── Bubble rendering ──────────────────────────────────────────────────────────────────────────\n private turnHtml(m: ChatMessage, isLastBot: boolean): string {\n const role = m.role === 'user' ? 'user' : m.role === 'human' ? 'human' : 'bot';\n const atts = (m.attachments ?? []).map((a) => this.renderAttachment(a)).join('');\n let content: string;\n if (m.role === 'assistant') {\n // Only the AI's text renders markdown; cache finalized turns, re-render only the live one.\n let rendered = m.streaming ? undefined : this.mdCache.get(m.id);\n if (rendered === undefined) { rendered = renderMarkdown(m.text || ''); if (!m.streaming) this.mdCache.set(m.id, rendered); }\n content = `<span class=\"b\">${atts}<span class=\"md\">${rendered}</span></span>`;\n } else {\n const label = m.role === 'human' ? '<div class=\"human-label\">Support</div>' : '';\n content = `<span class=\"b\">${label}${atts}${escapeHtml(m.text)}</span>`;\n }\n\n const src = (m.sources && m.sources.length > 0)\n ? `<span class=\"src\">${ICON.book}<span class=\"t\">${escapeHtml('From ' + (m.sources[0]?.title ?? ''))}</span></span>`\n : '';\n const byline = (role === 'bot' && isLastBot)\n ? `<span class=\"byline\">${escapeHtml((this.agentName ?? 'OyeHello') + ' · AI agent · ' + this.relTime(m.id))}</span>`\n : '';\n return `<span class=\"turn ${role}\">${content}${src}${byline}</span>`;\n }\n\n private relTime(id: string): string {\n const t = this.receivedAt.get(id);\n if (!t) return 'just now';\n const mins = Math.floor((Date.now() - t) / 60000);\n return mins <= 0 ? 'just now' : `${mins} min ago`;\n }\n\n private renderAttachment(a: ChatAttachmentDescriptor): string {\n if (a.contentType.startsWith('image/')) {\n const cached = (a.name ? this.imagePreviewCache.get(a.name) : undefined) ?? this.resolvedUrlCache.get(a.storageRef);\n const srcAttr = cached ? ` src=\"${cached}\"` : '';\n return `<img class=\"att-thumb\" data-oc-ref=\"${this.escapeAttr(a.storageRef)}\"${srcAttr} alt=\"${this.escapeAttr(a.name ?? 'image')}\"/>`;\n }\n return `<div class=\"att-chip\">📎 ${escapeHtml(a.name ?? a.contentType)}</div>`;\n }\n\n private hydrateAttachmentImages() {\n if (!this.client) return;\n this.shadowRoot!.querySelectorAll<HTMLImageElement>('img.att-thumb[data-oc-ref]').forEach((img) => {\n if (img.hasAttribute('src')) return;\n const ref = img.getAttribute('data-oc-ref');\n if (!ref) return;\n void this.client!.getAttachmentUrl(ref)\n .then((url) => { this.resolvedUrlCache.set(ref, url); img.src = url; })\n .catch(() => { /* no thumbnail is an acceptable degrade */ });\n });\n }\n\n private escapeAttr(s: string) { return s.replace(/[&<>\"]/g, (c) => ({ '&': '&', '<': '<', '>': '>', '\"': '"' }[c]!)); }\n}\n\nfunction escapeHtml(s: string) { return s.replace(/[&<>\"]/g, (c) => ({ '&': '&', '<': '<', '>': '>', '\"': '"' }[c]!)); }\n","export { ChatApiError } from './errors';\nexport type { ChatEvent, OpenSessionResponse, ChatClientOptions, ChatAttachmentDescriptor, WidgetConfig } from './protocol';\nexport { createChatClient } from './client';\nexport type { ChatClient, ChatMessage, ChatClientState, ChatClientEvent, ChatToolHandler } from './client';\nexport { OyehelloChatElement } from './element';\n\nimport { OyehelloChatElement } from './element';\n// Side effect: registering the element is why the package is sideEffects:true.\nif (typeof customElements !== 'undefined' && !customElements.get('oyehello-chat')) {\n customElements.define('oyehello-chat', OyehelloChatElement);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/protocol.ts","../src/transport.ts","../src/fingerprint.ts","../src/journey.ts","../src/client.ts","../src/page-theme.ts","../src/markdown.ts","../src/styles.ts","../src/icons.ts","../src/emoji.ts","../src/element.ts","../src/index.ts"],"names":["store","history"],"mappings":"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","file":"index.js","sourcesContent":["export class ChatApiError extends Error {\n constructor(message: string, readonly status: number, readonly code?: string, readonly meta?: Record<string, unknown>) {\n super(message);\n this.name = 'ChatApiError';\n }\n}\n","// SDK↔server wire-protocol version. Sent in the session-open request BODY (a custom header would need\n// a /chat/* CORS allowedHeaders entry); the server echoes its own version in the open response so the\n// SDK can warn (in the browser console) when an embed is out of date. Bump when the wire shape changes.\nexport const CHAT_PROTOCOL_VERSION = 1;\n\n// Mirrors the backend ChatEvent union (apps/api/src/telemetry/chat-event-sink.ts) EXACTLY.\nexport type ChatEvent =\n | { type: 'token'; text: string }\n | { type: 'message'; turnId: string; text: string }\n | { type: 'state'; state: string }\n | { type: 'done' }\n | { type: 'error'; message: string }\n | { type: 'tool_call'; callId: string; name: string; args: Record<string, unknown> }\n // Echoes a visitor's message attachments back over SSE (Phase 5 uploads) so the widget can render\n // the upload against the turn even on a reconnect/replay, without keeping its own optimistic state.\n | { type: 'attachment'; turnId?: string; items: { storageRef: string; contentType: string; name?: string }[] }\n // RAG source refs retrieved for this turn (Phase 6) - carries the same turnId as the `message`\n // event it follows. Absent KB / no retrieval this turn = no event.\n | { type: 'citations'; turnId: string; sources: { id: string; title: string; snippet: string }[] }\n // A human agent's reply, sent from the console inbox (Phase 7 handoff). The widget renders this\n // as a distinct \"human\" bubble.\n | { type: 'human_message'; turnId: string; text: string }\n // Echoes the visitor's own message back over SSE so the console inbox sees every visitor turn\n // live (Phase 7 handoff). The widget ignores this - it already renders its own message optimistically.\n | { type: 'visitor_message'; turnId: string; text: string }\n // A human agent is (or stopped) typing in the console during a handoff (Phase 7 followups). The\n // widget surfaces a transient \"agent is typing…\" affordance - never pushed as a message.\n | { type: 'agent_typing'; active: boolean }\n // Flow-derived follow-up quick-reply chips for the turn (same turnId as its `message`). The widget\n // renders them as chips; the next turn's event replaces them; an empty list clears them.\n | { type: 'suggestions'; turnId: string; items: string[] };\n\n// Pre-session widget config (GET /chat/widget-config) — read before the visitor opens the panel to\n// theme the launcher and show the teaser. brand is null unless the workspace has white-label branding.\nexport interface WidgetConfig {\n teaser: string;\n brand: { name: string | null; logoUrl: string | null; accentColor: string | null } | null;\n // Staffed-hours: when true the agent is outside its business hours - the widget shows offlineMessage\n // and a session-open attempt is refused server-side (code: agent_offline).\n offline?: boolean;\n offlineMessage?: string;\n}\n\nexport interface OpenSessionResponse {\n sessionId: string;\n sessionToken: string;\n expiresAt: string;\n agent: { id: string; name: string };\n // The server's wire-protocol version (see CHAT_PROTOCOL_VERSION). Absent from older servers.\n protocol?: number;\n}\n\nexport interface StreamTicket { ticket: string; expiresAt: string }\n\nexport interface ChatClientOptions {\n apiKey: string; // ohk_pub_… publishable key (created in the console)\n agentId: string;\n baseUrl: string; // the oyehello API origin, e.g. https://api.oyehello.ai\n user?: { id?: string };\n fetch?: typeof fetch; // injectable for tests\n eventSource?: typeof EventSource; // injectable for tests\n // SDK-side cap on files passed to a single sendMessage() call, enforced before any network call.\n // Mirrors the server's CHAT_ATTACHMENT_MAX_PER_MESSAGE default (apps/api/src/config/env.ts) so a\n // visitor gets an immediate error instead of a round-trip 400 on the message post.\n maxAttachments?: number;\n // SDK-side cap (bytes) on each file passed to a single sendMessage() call, enforced before any\n // upload. Mirrors the server's CHAT_ATTACHMENT_MAX_BYTES default (apps/api/src/config/env.ts).\n // This is UX-only - the server enforces the real limit (message-time HeadObject size check), so a\n // visitor just gets an immediate error instead of uploading a file that will be rejected anyway.\n maxAttachmentBytes?: number;\n}\n\n// A resolved attachment reference, shared shape between a message post body and the `attachment`\n// ChatEvent's items (protocol.ts's ChatEvent union above is the source of truth for the SSE shape;\n// this alias exists only so client.ts/transport.ts/element.ts don't repeat the inline object type).\nexport interface ChatAttachmentDescriptor { storageRef: string; contentType: string; name?: string }\n","import { ChatApiError } from './errors';\nimport { CHAT_PROTOCOL_VERSION } from './protocol';\nimport type { ChatAttachmentDescriptor, OpenSessionResponse, StreamTicket, WidgetConfig } from './protocol';\nimport type { JourneyView } from './journey';\n\nasync function asError(res: Response, fallbackCode?: string): Promise<ChatApiError> {\n let body: { error?: string; code?: string; meta?: Record<string, unknown> } = {};\n try { body = (await res.json()) as { error?: string; code?: string; meta?: Record<string, unknown> }; } catch { /* non-json */ }\n return new ChatApiError(body.error ?? `HTTP ${res.status}`, res.status, body.code ?? fallbackCode, body.meta);\n}\n\nexport async function openSession(opts: { baseUrl: string; apiKey: string; agentId: string; user?: { id?: string }; clientTools?: string[]; fingerprint?: string; fetchImpl: typeof fetch }): Promise<OpenSessionResponse> {\n // Protocol version rides in the BODY, not a custom header - a custom request header would have to be\n // added to the /chat/* CORS allowedHeaders allowlist or every browser preflight fails. The body is\n // already sent as application/json, which needs no extra CORS allowance.\n const body: Record<string, unknown> = { agentId: opts.agentId, protocol: CHAT_PROTOCOL_VERSION };\n if (opts.user) body.user = opts.user;\n if (opts.clientTools && opts.clientTools.length > 0) body.clientTools = opts.clientTools;\n if (opts.fingerprint) body.fingerprint = opts.fingerprint;\n const res = await opts.fetchImpl(`${opts.baseUrl}/chat/sessions`, {\n method: 'POST', credentials: 'omit',\n headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${opts.apiKey}` },\n body: JSON.stringify(body),\n });\n if (!res.ok) throw await asError(res);\n return (await res.json()) as OpenSessionResponse;\n}\n\n// Pre-session widget config (brand + teaser). Publishable-key auth, no session opened. A failure is\n// non-fatal for the widget — the caller falls back to defaults — so callers catch and ignore.\nexport async function getWidgetConfig(opts: { baseUrl: string; apiKey: string; agentId: string; fetchImpl: typeof fetch }): Promise<WidgetConfig> {\n const res = await opts.fetchImpl(`${opts.baseUrl}/chat/widget-config?agentId=${encodeURIComponent(opts.agentId)}`, {\n method: 'GET', credentials: 'omit',\n headers: { Authorization: `Bearer ${opts.apiKey}` },\n });\n if (!res.ok) throw await asError(res);\n return (await res.json()) as WidgetConfig;\n}\n\nexport async function postMessage(opts: { baseUrl: string; sessionId: string; sessionToken: string; text: string; attachments?: ChatAttachmentDescriptor[]; fetchImpl: typeof fetch }): Promise<void> {\n const body: Record<string, unknown> = { text: opts.text };\n if (opts.attachments && opts.attachments.length > 0) body.attachments = opts.attachments;\n const res = await opts.fetchImpl(`${opts.baseUrl}/chat/sessions/${opts.sessionId}/messages`, {\n method: 'POST', credentials: 'omit',\n headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${opts.sessionToken}` },\n body: JSON.stringify(body),\n });\n // A 401 here means the 15-min session token expired (no refresh endpoint) — surface a stable code\n // so the client can transparently re-open a session and retry.\n if (!res.ok) throw await asError(res, res.status === 401 ? 'session_expired' : undefined);\n}\n\n// GET /chat/sessions/:id/messages - history restore (resume-on-reload). Mirrors postMessage's auth\n// shape (Bearer session token) but as a GET; a 401 maps to 'session_expired' like the other transport\n// fns so the client's resume path can decide whether to fall back gracefully.\nexport async function getHistory(opts: { baseUrl: string; sessionId: string; sessionToken: string; fetchImpl: typeof fetch }): Promise<{ turnId?: string; role: 'user' | 'assistant' | 'human'; text: string }[]> {\n const res = await opts.fetchImpl(`${opts.baseUrl}/chat/sessions/${opts.sessionId}/messages`, {\n method: 'GET', credentials: 'omit',\n headers: { Authorization: `Bearer ${opts.sessionToken}` },\n });\n if (!res.ok) throw await asError(res, res.status === 401 ? 'session_expired' : undefined);\n const body = (await res.json()) as { messages: { turnId?: string; role: 'user' | 'assistant' | 'human'; text: string }[] };\n return body.messages;\n}\n\n// POST /chat/sessions/:id/page-views — visitor-journey ingest (Task 21 SDK side / Task 20 server\n// route). Session-token auth, mirrors postMessage's shape. Fire-and-forget-friendly: the caller\n// (client.ts) guards this and only advances its local high-water mark on a resolved (2xx) response,\n// so a network failure just leaves the views unsent for the next flush — never thrown into the host\n// page from here beyond a normal rejected promise.\nexport async function postPageViews(opts: { baseUrl: string; sessionId: string; sessionToken: string; views: JourneyView[]; fetchImpl: typeof fetch }): Promise<void> {\n const res = await opts.fetchImpl(`${opts.baseUrl}/chat/sessions/${opts.sessionId}/page-views`, {\n method: 'POST', credentials: 'omit',\n headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${opts.sessionToken}` },\n body: JSON.stringify({ views: opts.views }),\n });\n if (!res.ok) throw await asError(res, res.status === 401 ? 'session_expired' : undefined);\n}\n\nexport async function endSession(opts: { baseUrl: string; sessionId: string; sessionToken: string; fetchImpl: typeof fetch }): Promise<void> {\n await opts.fetchImpl(`${opts.baseUrl}/chat/sessions/${opts.sessionId}/end`, {\n method: 'POST', credentials: 'omit',\n headers: { Authorization: `Bearer ${opts.sessionToken}` },\n }).catch(() => {}); // best-effort teardown\n}\n\nexport async function postToolResult(opts: { baseUrl: string; sessionId: string; sessionToken: string; callId: string; ok: boolean; result: unknown; fetchImpl: typeof fetch }): Promise<void> {\n await opts.fetchImpl(`${opts.baseUrl}/chat/sessions/${opts.sessionId}/tool-results`, {\n method: 'POST', credentials: 'omit',\n headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${opts.sessionToken}` },\n body: JSON.stringify({ callId: opts.callId, ok: opts.ok, result: opts.result }),\n }).catch(() => {}); // best-effort; a dropped result times out server-side and the model recovers\n}\n\n// Re-mint a fresh session token for the SAME session before the current one expires, so a long,\n// actively-used conversation stays on one session (one chat in the console) instead of the message\n// path reopening a new session on token expiry. Auth is the current (still-valid) token.\nexport async function refreshSessionToken(opts: { baseUrl: string; sessionId: string; sessionToken: string; fetchImpl: typeof fetch }): Promise<{ sessionToken: string; expiresAt: string }> {\n const res = await opts.fetchImpl(`${opts.baseUrl}/chat/sessions/${opts.sessionId}/refresh-token`, {\n method: 'POST', credentials: 'omit',\n headers: { Authorization: `Bearer ${opts.sessionToken}` },\n });\n if (!res.ok) throw await asError(res, res.status === 401 ? 'session_expired' : undefined);\n return (await res.json()) as { sessionToken: string; expiresAt: string };\n}\n\nexport async function mintStreamTicket(opts: { baseUrl: string; sessionId: string; sessionToken: string; fetchImpl: typeof fetch }): Promise<StreamTicket> {\n const res = await opts.fetchImpl(`${opts.baseUrl}/chat/sessions/${opts.sessionId}/stream-ticket`, {\n method: 'POST', credentials: 'omit',\n headers: { Authorization: `Bearer ${opts.sessionToken}` },\n });\n // A 401 here means the session token is invalid/expired — surface a stable code so the client\n // can distinguish this from a transient failure (mirrors postMessage's 401 mapping).\n if (!res.ok) throw await asError(res, res.status === 401 ? 'session_expired' : undefined);\n return (await res.json()) as StreamTicket;\n}\n\nexport function streamUrl(baseUrl: string, sessionId: string, ticket: string): string {\n return `${baseUrl}/chat/sessions/${sessionId}/stream?ticket=${encodeURIComponent(ticket)}`;\n}\n\n// POST /chat/sessions/:id/attachments — mints a presigned S3 PUT for a visitor upload. Bearer session\n// token auth, mirrors mintStreamTicket's shape/error-mapping exactly.\n// Server-proxied upload (the default): POST the file to OUR API as multipart/form-data; the server\n// streams it to storage and returns the storageRef. No direct browser→bucket PUT, so no bucket CORS to\n// configure. Only Authorization is a custom header (allowed by /chat/* CORS); the browser sets the\n// multipart Content-Type/boundary itself.\nexport async function uploadAttachment(opts: { baseUrl: string; sessionId: string; sessionToken: string; file: File; fetchImpl: typeof fetch }): Promise<ChatAttachmentDescriptor> {\n const form = new FormData();\n form.append('file', opts.file, opts.file.name);\n const res = await opts.fetchImpl(`${opts.baseUrl}/chat/sessions/${opts.sessionId}/upload`, {\n method: 'POST', credentials: 'omit',\n headers: { Authorization: `Bearer ${opts.sessionToken}` },\n body: form,\n });\n if (!res.ok) throw await asError(res, res.status === 401 ? 'session_expired' : undefined);\n const j = (await res.json()) as { storageRef: string; contentType: string; name?: string };\n return { storageRef: j.storageRef, contentType: j.contentType, name: j.name };\n}\n\nexport async function presignAttachment(opts: { baseUrl: string; sessionId: string; sessionToken: string; contentType: string; fetchImpl: typeof fetch }): Promise<{ storageRef: string; uploadUrl: string }> {\n const res = await opts.fetchImpl(`${opts.baseUrl}/chat/sessions/${opts.sessionId}/attachments`, {\n method: 'POST', credentials: 'omit',\n headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${opts.sessionToken}` },\n body: JSON.stringify({ contentType: opts.contentType }),\n });\n // A 401 here means the session token is invalid/expired — surface a stable code so the client\n // can distinguish this from a transient failure (mirrors postMessage's 401 mapping).\n if (!res.ok) throw await asError(res, res.status === 401 ? 'session_expired' : undefined);\n return (await res.json()) as { storageRef: string; uploadUrl: string };\n}\n\n// POST /chat/sessions/:id/attachment-url — mints a presigned S3 GET so an already-uploaded\n// attachment can be read back (e.g. rendering an image thumbnail on reconnect, when no local blob\n// is cached). Bearer session token auth, mirrors presignAttachment's shape/error-mapping exactly.\nexport async function getAttachmentUrl(opts: { baseUrl: string; sessionId: string; sessionToken: string; storageRef: string; fetchImpl: typeof fetch }): Promise<string> {\n const res = await opts.fetchImpl(`${opts.baseUrl}/chat/sessions/${opts.sessionId}/attachment-url`, {\n method: 'POST', credentials: 'omit',\n headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${opts.sessionToken}` },\n body: JSON.stringify({ storageRef: opts.storageRef }),\n });\n // A 401 here means the session token is invalid/expired — surface a stable code so the client\n // can distinguish this from a transient failure (mirrors postMessage's 401 mapping).\n if (!res.ok) throw await asError(res, res.status === 401 ? 'session_expired' : undefined);\n return ((await res.json()) as { url: string }).url;\n}\n\n// Uploads a file directly to the presigned S3 URL. The URL is already absolute and fully signed —\n// NO baseUrl prefix, NO Authorization header (would break the signature), just a bare PUT with the\n// file's own content type (Task 4 dropped SSE from the presign so this needs no extra headers).\nexport async function uploadToPresigned(uploadUrl: string, file: File, fetchImpl: typeof fetch): Promise<void> {\n const res = await fetchImpl(uploadUrl, { method: 'PUT', body: file, headers: { 'Content-Type': file.type } });\n if (!res.ok) throw new ChatApiError(`attachment upload failed with HTTP ${res.status}`, res.status);\n}\n","// A lightweight, dependency-free device fingerprint: a stable hash of a handful of browser/device\n// signals, sent on session-open so the backend can flag abuse / recognise a returning device. NOT a\n// hardened anti-fraud fingerprint (no canvas/WebGL probing) — deliberately modest and privacy-lighter.\n// Returns null outside a browser (no navigator) or on any error, so it never blocks opening a session.\n\nasync function sha256Hex(input: string): Promise<string | null> {\n const g = globalThis as unknown as { crypto?: { subtle?: SubtleCrypto }; TextEncoder?: typeof TextEncoder };\n try {\n if (g.crypto?.subtle && typeof TextEncoder !== 'undefined') {\n const buf = await g.crypto.subtle.digest('SHA-256', new TextEncoder().encode(input));\n return Array.from(new Uint8Array(buf)).map((b) => b.toString(16).padStart(2, '0')).join('').slice(0, 32);\n }\n } catch { /* fall through to the non-crypto hash */ }\n // djb2 fallback (older/insecure contexts where SubtleCrypto is unavailable).\n let h = 5381;\n for (let i = 0; i < input.length; i++) h = ((h << 5) + h + input.charCodeAt(i)) >>> 0;\n return h.toString(16).padStart(8, '0');\n}\n\nexport async function computeDeviceFingerprint(): Promise<string | null> {\n try {\n const nav = typeof navigator !== 'undefined' ? (navigator as Navigator & { deviceMemory?: number }) : null;\n if (!nav) return null;\n const scr = typeof screen !== 'undefined' ? screen : null;\n const tz = (() => { try { return Intl.DateTimeFormat().resolvedOptions().timeZone; } catch { return ''; } })();\n const dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : '';\n const signals = [\n nav.userAgent,\n Array.isArray(nav.languages) ? nav.languages.join(',') : '',\n nav.language,\n (nav as Navigator & { platform?: string }).platform,\n nav.hardwareConcurrency,\n nav.deviceMemory,\n scr ? `${scr.width}x${scr.height}x${scr.colorDepth}` : '',\n dpr,\n tz,\n ].map((v) => String(v ?? '')).join('|');\n return await sha256Hex(signals);\n } catch {\n return null;\n }\n}\n","// Visitor-journey page-view tracking (Task 21). Buffered in sessionStorage from page load so\n// pre-chat browsing is captured even on Astro multi-page (full-reload) navigation — a session isn't\n// open yet when the visitor is just browsing, so there's nowhere to POST to until one is. The buffer\n// is flushed once a chat session exists (client.ts: on open() success, and live on every\n// recordPageView() call while a session is already open).\n//\n// Storage shape per agent, keyed `oyehello-chat:journey:<agentId>`:\n// { views: [{ path, at }, ...], flushed: number }\n// `flushed` is a high-water mark into `views` — everything before it has already been POSTed and\n// acknowledged by the server; unsentViews() returns the tail past it, markFlushed() advances it.\n// All sessionStorage access is guarded (try/catch) — it may throw (privacy mode, quota) or be\n// entirely unavailable, and this module must never throw into the host page.\n\nexport interface JourneyView { path: string; at: string }\ninterface JourneyStore { views: JourneyView[]; flushed: number }\n\nconst MAX_BUFFER = 25;\n\nconst storageKey = (agentId: string) => `oyehello-chat:journey:${agentId}`;\n\nconst store = (): Storage | null => {\n try { return globalThis.sessionStorage ?? null; } catch { return null; }\n};\n\nfunction load(agentId: string): JourneyStore {\n const s = store();\n if (!s) return { views: [], flushed: 0 };\n try {\n const raw = s.getItem(storageKey(agentId));\n if (!raw) return { views: [], flushed: 0 };\n const parsed = JSON.parse(raw) as Partial<JourneyStore> | null;\n const views = Array.isArray(parsed?.views)\n ? parsed!.views.filter((v): v is JourneyView => !!v && typeof v.path === 'string' && typeof v.at === 'string')\n : [];\n const flushedRaw = typeof parsed?.flushed === 'number' && parsed!.flushed >= 0 ? parsed!.flushed : 0;\n return { views, flushed: Math.min(flushedRaw, views.length) };\n } catch { return { views: [], flushed: 0 }; }\n}\n\nfunction save(agentId: string, data: JourneyStore): void {\n const s = store();\n if (!s) return;\n try { s.setItem(storageKey(agentId), JSON.stringify(data)); } catch { /* storage blocked/full */ }\n}\n\n// Strip query + hash (the caller passes `location.pathname` for the current-page case, so this\n// mainly protects installSpaHooks' `location.pathname` reads and any other caller that hands in a\n// fuller path string).\nconst sanitizePath = (raw: string): string => (raw || '/').split('?')[0]!.split('#')[0]!;\n\n// Append a view for `path` to the capped buffer, deduped against the immediately-previous entry\n// (so re-recording the same page — e.g. a redundant replaceState — doesn't spam the journey).\nexport function recordView(agentId: string, path: string): void {\n try {\n const p = sanitizePath(path);\n const data = load(agentId);\n const last = data.views[data.views.length - 1];\n if (last && last.path === p) return;\n data.views.push({ path: p, at: new Date().toISOString() });\n if (data.views.length > MAX_BUFFER) {\n const drop = data.views.length - MAX_BUFFER;\n data.views = data.views.slice(drop);\n data.flushed = Math.max(0, data.flushed - drop);\n }\n save(agentId, data);\n } catch { /* never throw into the host page */ }\n}\n\n// Views recorded but not yet acknowledged by the server (past the flushed high-water mark).\nexport function unsentViews(agentId: string): JourneyView[] {\n try {\n const data = load(agentId);\n return data.views.slice(data.flushed);\n } catch { return []; }\n}\n\n// Advance the flushed high-water mark by `count` (called after a successful POST of that many\n// unsent views) so they aren't resent on the next flush.\nexport function markFlushed(agentId: string, count: number): void {\n if (count <= 0) return;\n try {\n const data = load(agentId);\n data.flushed = Math.min(data.views.length, data.flushed + count);\n save(agentId, data);\n } catch { /* ignore */ }\n}\n\n// SPA support: Astro MPA navigation is already covered by a fresh recordView() on each full-page\n// connectedCallback, but a client-routed site never remounts the element — so patch history's\n// navigation entry points and notify on every push/replace/back-forward. Returns an uninstaller that\n// restores the originals and removes the popstate listener (call from disconnectedCallback).\nexport function installSpaHooks(onNav: () => void): () => void {\n const originalPush = history.pushState;\n const originalReplace = history.replaceState;\n // Reassigning history.pushState/replaceState can throw — some privacy/security tooling freezes\n // `history` (Object.defineProperty(..., { writable: false })) to stop exactly this kind of\n // monkey-patch. Guard each assignment independently so a frozen pushState doesn't stop replaceState\n // or the popstate listener from installing, and track what actually got installed so the uninstaller\n // only restores/removes what this call put in place.\n let pushInstalled = false;\n let replaceInstalled = false;\n try {\n history.pushState = function (this: History, ...args: Parameters<History['pushState']>) {\n const ret = originalPush.apply(this, args);\n try { onNav(); } catch { /* ignore */ }\n return ret;\n };\n pushInstalled = true;\n } catch { /* frozen/non-writable history.pushState — fall back to popstate-only below */ }\n try {\n history.replaceState = function (this: History, ...args: Parameters<History['replaceState']>) {\n const ret = originalReplace.apply(this, args);\n try { onNav(); } catch { /* ignore */ }\n return ret;\n };\n replaceInstalled = true;\n } catch { /* frozen/non-writable history.replaceState — fall back to popstate-only below */ }\n const onPopState = () => { try { onNav(); } catch { /* ignore */ } };\n let popstateInstalled = false;\n try { window.addEventListener('popstate', onPopState); popstateInstalled = true; } catch { /* ignore */ }\n return () => {\n if (pushInstalled) { try { history.pushState = originalPush; } catch { /* ignore */ } }\n if (replaceInstalled) { try { history.replaceState = originalReplace; } catch { /* ignore */ } }\n if (popstateInstalled) { try { window.removeEventListener('popstate', onPopState); } catch { /* ignore */ } }\n };\n}\n","import { openSession, postMessage, endSession, streamUrl, mintStreamTicket, refreshSessionToken, postToolResult, uploadAttachment, getAttachmentUrl, getWidgetConfig, postPageViews, getHistory } from './transport';\nimport { ChatApiError } from './errors';\nimport { CHAT_PROTOCOL_VERSION } from './protocol';\nimport { computeDeviceFingerprint } from './fingerprint';\nimport { recordView, unsentViews, markFlushed } from './journey';\nimport type { ChatAttachmentDescriptor, ChatClientOptions, ChatEvent, OpenSessionResponse, WidgetConfig } from './protocol';\n\nexport interface ChatMessage { id: string; role: 'user' | 'assistant' | 'human'; text: string; streaming: boolean; attachments?: ChatAttachmentDescriptor[]; sources?: { id: string; title: string; snippet: string }[]; turnId?: string }\nexport type ChatClientState = 'idle' | 'opening' | 'ready' | 'ended' | 'error';\n// Handoff status of the session, driven by the backend's `state` SSE event (Phase 7). 'ai' = the\n// AI is answering (default/no handoff), 'awaiting_human' = a handoff was requested and no human\n// has taken over yet, 'human' = a human agent is answering.\nexport type HandoffState = 'ai' | 'awaiting_human' | 'human';\nexport type ChatClientEvent =\n | { type: 'state'; state: ChatClientState }\n | { type: 'messages'; messages: ChatMessage[] }\n | { type: 'error'; error: Error }\n | { type: 'agent'; agent: { id: string; name: string } }\n // Handoff status changed (Phase 7) - the widget uses this to show a status line.\n | { type: 'handoff'; state: HandoffState }\n // A human agent is (or stopped) typing in the console during a handoff (Phase 7 followups). The\n // widget uses this to show a transient \"agent is typing…\" affordance - never a message.\n | { type: 'agentTyping'; active: boolean }\n // Flow-derived follow-up chips for the latest turn; a later turn replaces them, an empty list clears.\n | { type: 'suggestions'; items: string[] };\nexport type ChatToolHandler = (args: Record<string, unknown>) => unknown | Promise<unknown>;\nexport interface ChatClient {\n start(): Promise<void>;\n sendMessage(text: string, files?: File[]): Promise<void>;\n end(): Promise<void>;\n // Detach the transport (close the SSE stream + timers) WITHOUT ending the server session or clearing\n // the persisted session. For a transient DOM unmount (framework navigation / Astro View Transitions):\n // the element re-mounts and resumes the same conversation instead of killing it + opening a new chat.\n detach(): void;\n // Clear the conversation thread (messages + dedup + handoff state) back to a blank slate, without\n // opening a session. Call before start() to begin a genuinely fresh conversation (e.g. the widget's\n // \"New message\" after a session ended).\n reset(): void;\n getMessages(): ChatMessage[];\n getState(): ChatClientState;\n on(listener: (e: ChatClientEvent) => void): () => void;\n // Register browser-side tool handlers the server may call mid-conversation. Register BEFORE\n // start() — the handler names are sent as `clientTools` on session open so the server knows\n // which tools this session can execute.\n registerTools(handlers: Record<string, ChatToolHandler>): void;\n // Resolves a read-back URL for an already-uploaded attachment (e.g. an image thumbnail with no\n // local blob cached — a reconnect, or an `attachment` SSE echo). Requires start() to have been\n // called (a live session).\n getAttachmentUrl(storageRef: string): Promise<string>;\n // Pre-session widget config (brand + teaser). Safe to call before start(); no session is opened.\n getWidgetConfig(): Promise<WidgetConfig>;\n // Record a visitor page view for the CRM journey timeline (Task 21). Buffers via journey.ts\n // (survives an Astro full-page reload) and, if a session is already open, also flushes the newly\n // unsent views to the server immediately - never throws into the host page.\n recordPageView(path: string): void;\n}\n\nlet seq = 0;\nconst uid = (p: string) => `${p}_${Date.now().toString(36)}_${(seq++).toString(36)}`;\n\n// navigate is intra-app only — a bare, non-protocol-relative path (rules out `javascript:`, `data:`,\n// `//evil.com`, absolute URLs, etc.).\nconst isSafeRelativePath = (p: string) => p.startsWith('/') && !p.startsWith('//');\n// openUrl is the absolute-URL escape hatch — restrict to http(s) so `javascript:`/`data:`/`vbscript:`\n// etc. can never reach window.open.\nconst isSafeHttpUrl = (u: string) => {\n try { const parsed = new URL(u, window.location.origin); return parsed.protocol === 'http:' || parsed.protocol === 'https:'; }\n catch { return false; }\n};\n\n// Built-in client tools the SDK executes itself with zero host integration — the server already\n// validates/allowlists their arguments (navigate's `path`, openUrl's `url`) against the agent's\n// navigate allowlist before dispatching the tool_call. The scheme checks below are defense-in-depth\n// at the DOM sink, independent of that server-side check — a model-supplied `javascript:`/`data:`\n// target must never reach location.assign/window.open even if some future server path skipped\n// validation. A host-registered handler for the same name (registerTools) takes priority over these —\n// see the tool_call dispatch below.\n// A built-in handler may return this key with a function to run once its result has been posted (navigation).\nconst AFTER_RESULT = '__ohAfterResult';\n\nconst BUILTIN_TOOL_HANDLERS: Record<string, ChatToolHandler> = {\n navigate: (args) => {\n const path = String(args.path ?? '');\n if (!isSafeRelativePath(path)) return { ok: false, error: 'unsafe navigate path' };\n // Already on that page: reloading it would only drop the visitor's place (and used to feed the reload loop).\n const here = window.location.pathname + window.location.search + window.location.hash;\n const target = new URL(path, window.location.href);\n if (target.pathname + target.search + target.hash === here) return { ok: true, note: 'already on this page' };\n // The page change happens only AFTER the result is posted (see the tool_call dispatch), so the server never keeps\n // a navigate it already got pending across the reload.\n return { ok: true, [AFTER_RESULT]: () => window.location.assign(path) };\n },\n openUrl: (args) => {\n const url = String(args.url ?? '');\n if (!isSafeHttpUrl(url)) return { ok: false, error: 'unsafe url' };\n // Tab target is decided HERE from the domain relationship — never by a model-supplied arg (the\n // model has no say over how its own link opens). The server already restricted `url` to the\n // agent's navigate allowlist base domain or one of its subdomains before this tool_call was ever\n // sent (isNavigationAllowed in build-brain.ts) - any other domain never reaches this handler. So:\n // the exact same host as the embedding page -> same tab (feels like an in-app link); anything\n // else that got this far is by construction a (sub)domain of an allowed base domain -> new tab,\n // so navigating away never strands the visitor off the page they were chatting from.\n const sameHost = new URL(url, window.location.origin).hostname === window.location.hostname;\n // 'noopener,noreferrer' prevents reverse-tabnabbing (the opened page getting a `window.opener`\n // handle back to this one).\n window.open(url, sameHost ? '_self' : '_blank', 'noopener,noreferrer');\n return { ok: true };\n },\n};\n\nexport function createChatClient(options: ChatClientOptions): ChatClient {\n // Native fetch must be invoked with `this === window`; the transport calls this as\n // `opts.fetchImpl(...)`, so a bare `globalThis.fetch` reference throws \"Illegal invocation\".\n // Bind the default to the global. A caller-supplied fetch is used as-is.\n const fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis);\n const ES = options.eventSource ?? globalThis.EventSource;\n // Mirrors the server's CHAT_ATTACHMENT_MAX_PER_MESSAGE default (apps/api/src/config/env.ts).\n const maxAttachments = options.maxAttachments ?? 4;\n // Mirrors the server's CHAT_ATTACHMENT_MAX_BYTES default (apps/api/src/config/env.ts). UX-only\n // fast pre-check - the server is authoritative (message-time HeadObject size enforcement).\n const maxAttachmentBytes = options.maxAttachmentBytes ?? 10_000_000;\n const listeners = new Set<(e: ChatClientEvent) => void>();\n let state: ChatClientState = 'idle';\n const messages: ChatMessage[] = [];\n let streamingId: string | null = null;\n let session: OpenSessionResponse | null = null;\n let es: EventSource | null = null;\n const seenTurnIds = new Set<string>();\n const seenCallIds = new Set<string>();\n let handoffState: HandoffState = 'ai';\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n let reconnectAttempts = 0;\n let closed = false;\n let warnedProtocol = false;\n // Device fingerprint: computed once (undefined = not yet computed, null = unavailable), reused across\n // reconnects/reopens so the same device reports a stable id.\n let deviceFingerprint: string | null | undefined;\n let refreshTimer: ReturnType<typeof setTimeout> | null = null;\n const toolHandlers = new Map<string, ChatToolHandler>();\n // Flush any journey.ts-buffered page views (recorded before a session existed, or since the last\n // flush) to the now-open session. Best-effort: a failed POST leaves the views unsent - the flushed\n // high-water mark only advances on a resolved response, so they're retried on the next open()/\n // recordPageView() rather than lost.\n //\n // Serialized via journeyFlushChain/journeyFlushQueued so two flushes triggered close together (e.g.\n // open()'s post-session flush racing a live recordPageView() call) never both read unsentViews()\n // before either markFlushed runs - that would POST the same pending views twice (bulkInsert has no\n // idempotency, so duplicate rows). At most one POST is ever in flight; a flushJourney() call that\n // arrives while one is running just sets a \"run once more\" flag (coalescing any number of calls\n // during that window into a single follow-up round), which re-reads unsentViews() AFTER the\n // in-flight POST's markFlushed has run, so it only sends what's genuinely still unsent.\n let journeyFlushChain: Promise<void> = Promise.resolve();\n let journeyFlushQueued = false;\n const flushJourney = () => {\n if (!session) return;\n if (journeyFlushQueued) return; // a follow-up round is already queued behind the in-flight flush\n journeyFlushQueued = true;\n journeyFlushChain = journeyFlushChain.then(async () => {\n journeyFlushQueued = false;\n if (!session) return;\n const pending = unsentViews(options.agentId);\n if (pending.length === 0) return;\n const s = session;\n try {\n await postPageViews({ baseUrl: options.baseUrl, sessionId: s.sessionId, sessionToken: s.sessionToken, views: pending, fetchImpl });\n markFlushed(options.agentId, pending.length);\n } catch { /* left unsent; retried on the next flush */ }\n });\n };\n const clearReconnect = () => { if (reconnectTimer) { clearTimeout(reconnectTimer); reconnectTimer = null; } };\n const clearRefresh = () => { if (refreshTimer) { clearTimeout(refreshTimer); refreshTimer = null; } };\n // Proactively re-mint the session token ~60s before it expires so a long active conversation stays on\n // ONE session (a token lapse would otherwise make the next message reopen a fresh session = a new\n // console chat). On failure (session ended/expired) the stored session is dropped and the normal\n // session_expired path opens a fresh one.\n const scheduleRefresh = () => {\n clearRefresh();\n if (closed || !session) return;\n const untilExpiry = Date.parse(session.expiresAt) - Date.now();\n const delay = Number.isNaN(untilExpiry) ? 10 * 60_000 : Math.max(5_000, untilExpiry - 60_000);\n refreshTimer = setTimeout(async () => {\n if (closed || !session) return;\n try {\n const r = await refreshSessionToken({ baseUrl: options.baseUrl, sessionId: session.sessionId, sessionToken: session.sessionToken, fetchImpl });\n session = { ...session, sessionToken: r.sessionToken, expiresAt: r.expiresAt };\n persistSession(session);\n scheduleRefresh();\n } catch (err) {\n // Only drop the session if it's definitively gone. A transient/404 (e.g. an API not yet\n // redeployed with the refresh route) leaves the still-valid session intact - it stays usable\n // until its original expiry, and the message path's session_expired handling covers the lapse.\n const code = (err as ChatApiError | undefined)?.code;\n if (code === 'session_ended' || code === 'session_expired') clearStoredSession();\n }\n }, delay);\n (refreshTimer as { unref?: () => void }).unref?.();\n };\n\n // Persist the open session per-tab so a page RELOAD resumes the SAME server session instead of\n // opening a new one (which would spawn a fresh chat in the console on every reload). Keyed by agent\n // and scoped to sessionStorage: a reload keeps it, a new tab starts fresh. Resume is driven by the\n // session TOKEN we minted (an unguessable bearer secret owned by this device) - NOT the device\n // fingerprint, which is spoofable and collides across identical devices (keying reuse on it would let\n // one visitor resume another's chat). The fingerprint stays a server-side analytics/abuse signal only.\n const sessKey = `oyehello-chat-sess:${options.agentId}`;\n const store = (() => { try { return globalThis.sessionStorage ?? null; } catch { return null; } })();\n const loadStoredSession = (): OpenSessionResponse | null => {\n if (!store) return null;\n try {\n const raw = store.getItem(sessKey);\n if (!raw) return null;\n const s = JSON.parse(raw) as OpenSessionResponse;\n if (!s?.sessionId || !s?.sessionToken || !s?.expiresAt || !s?.agent) return null;\n const exp = Date.parse(s.expiresAt);\n if (Number.isNaN(exp) || Date.now() >= exp - 5_000) { store.removeItem(sessKey); return null; } // bad or (near-)expired token\n return s;\n } catch { return null; }\n };\n const persistSession = (s: OpenSessionResponse) => {\n try { store?.setItem(sessKey, JSON.stringify({ sessionId: s.sessionId, sessionToken: s.sessionToken, expiresAt: s.expiresAt, agent: s.agent })); } catch { /* storage blocked */ }\n };\n const clearStoredSession = () => { try { store?.removeItem(sessKey); } catch { /* storage blocked */ } };\n // Tool calls already handled in this tab, per session (survives the reload a navigate causes). Last 50 only.\n const callsKey = `oyehello-chat-calls:${options.agentId}`;\n const handledCallIds = (): string[] => {\n try {\n const raw = store?.getItem(callsKey);\n const v = raw ? (JSON.parse(raw) as { sessionId?: string; ids?: string[] }) : null;\n return v && session && v.sessionId === session.sessionId && Array.isArray(v.ids) ? v.ids : [];\n } catch { return []; }\n };\n const rememberHandledCall = (callId: string) => {\n if (!session) return;\n try { store?.setItem(callsKey, JSON.stringify({ sessionId: session.sessionId, ids: [...handledCallIds(), callId].slice(-50) })); } catch { /* storage blocked */ }\n };\n\n const emit = (e: ChatClientEvent) => { for (const l of listeners) l(e); };\n const setState = (s: ChatClientState) => { state = s; emit({ type: 'state', state: s }); };\n const emitMessages = () => emit({ type: 'messages', messages: messages.slice() });\n\n const onEvent = (ev: ChatEvent) => {\n if (ev.type === 'token') {\n // `token` carries no turnId (see protocol.ts) so it can't be deduped against seenTurnIds here\n // directly — but that's fine: a buffer-replay of tokens for a turn already in seenTurnIds (e.g.\n // history-seeded on resume, or a normal live reconnect) only ever builds a transient streaming\n // bubble, which the `message` branch below discards wholesale the instant its own (deduped)\n // finalize event for that same turn arrives. So a seen turn's replayed tokens never survive into\n // a rendered duplicate, even though this branch itself doesn't check seenTurnIds.\n let m = streamingId ? messages.find((x) => x.id === streamingId) : undefined;\n if (!m) { m = { id: uid('m'), role: 'assistant', text: '', streaming: true }; messages.push(m); streamingId = m.id; }\n m.text += ev.text; emitMessages();\n } else if (ev.type === 'message') {\n if (seenTurnIds.has(ev.turnId)) {\n // Replay of an already-finalized turn (EventSource reconnect replays the session's event\n // buffer) OR a turn restored from history on resume (seenTurnIds seeded in open()). Discard\n // it, and drop any partial streaming bubble its replayed tokens built up, without emitting a\n // duplicate assistant message.\n if (streamingId) {\n const idx = messages.findIndex((x) => x.id === streamingId);\n if (idx !== -1) messages.splice(idx, 1);\n streamingId = null;\n emitMessages();\n }\n return;\n }\n seenTurnIds.add(ev.turnId);\n const m = streamingId ? messages.find((x) => x.id === streamingId) : undefined;\n // Keep the streamed text if the finalize carries none: a streaming turn's `message` event may\n // arrive with an empty `text` (the text was delivered via tokens), and overwriting with '' would\n // blank the just-streamed bubble.\n if (m) { m.text = ev.text || m.text; m.streaming = false; m.turnId = ev.turnId; } else { messages.push({ id: uid('m'), role: 'assistant', text: ev.text, streaming: false, turnId: ev.turnId }); }\n streamingId = null; emitMessages();\n } else if (ev.type === 'citations') {\n // Arrives AFTER `message` (streamingId already cleared) so the target message is located by\n // the turnId stamped above, not by streamingId. Ignore an unknown turnId (reconnect-safe: a\n // stale/duplicate citations replay for a turn we don't have never crashes or creates a bubble).\n const m = messages.find((x) => x.turnId === ev.turnId);\n if (m) { m.sources = ev.sources; emitMessages(); }\n } else if (ev.type === 'error') {\n emit({ type: 'error', error: new Error(ev.message) });\n } else if (ev.type === 'tool_call') {\n // Dispatch once, even across a page reload: a navigate reloads the page, the remounted widget resumes this\n // session and the server replays the buffered tool_call - running it again was an endless reload loop.\n if (seenCallIds.has(ev.callId) || handledCallIds().includes(ev.callId)) return;\n seenCallIds.add(ev.callId);\n rememberHandledCall(ev.callId);\n // Host-registered handler wins (lets a host override the built-ins); otherwise fall back to the\n // SDK's own navigate/openUrl implementation.\n const handler = toolHandlers.get(ev.name) ?? BUILTIN_TOOL_HANDLERS[ev.name];\n void (async () => {\n if (!session) return;\n const base = { baseUrl: options.baseUrl, sessionId: session.sessionId, sessionToken: session.sessionToken, callId: ev.callId, fetchImpl };\n if (!handler) {\n await postToolResult({ ...base, ok: false, result: `no handler registered for ${ev.name}` });\n return;\n }\n try {\n const raw = await handler(ev.args);\n let after: (() => void) | null = null;\n let out: unknown = raw;\n if (raw && typeof raw === 'object' && typeof (raw as Record<string, unknown>)[AFTER_RESULT] === 'function') {\n const { [AFTER_RESULT]: run, ...rest } = raw as Record<string, unknown>;\n after = run as () => void;\n out = rest;\n }\n await postToolResult({ ...base, ok: true, result: typeof out === 'string' ? out : JSON.stringify(out ?? { ok: true }) });\n after?.();\n } catch (err) {\n await postToolResult({ ...base, ok: false, result: (err as Error).message });\n }\n })();\n } else if (ev.type === 'attachment') {\n // The runtime re-publishes a visitor's message attachments over this event (Phase 5\n // follow-up) so a reconnecting client (buffer replay) or a future second viewer can render\n // them, now that a read-back URL exists (getAttachmentUrl / element.ts's lazy image src).\n // Hardened so it can never double-render on the SENDING client itself, which already rendered\n // these optimistically from its own sendMessage(): if any existing message already carries an\n // attachment with one of these storageRefs, the event is a stale/duplicate echo of something\n // already rendered — ignore it entirely instead of guessing which message to attach to (a\n // \"most recent attachment-less user message\" heuristic misattaches when a second image-first\n // message is sent before the echo of the first one arrives).\n const items = ev.items;\n const alreadyRendered = messages.some((m) => m.attachments?.some((a) => items.some((i) => i.storageRef === a.storageRef)));\n if (alreadyRendered) return;\n const target = [...messages].reverse().find((m) => m.role === 'user' && !m.attachments);\n if (target) target.attachments = items;\n else messages.push({ id: uid('u'), role: 'user', text: '', streaming: false, attachments: items });\n emitMessages();\n } else if (ev.type === 'human_message') {\n // A human agent's reply from the console inbox (Phase 7 handoff) - render as a distinct bubble.\n // Dedup by turnId (shared with the `message` branch's seenTurnIds) - EventSource reconnect\n // replays the session's buffered events, and human_message turnIds (newId('tn')) are distinct\n // from message turnIds, so sharing the Set is safe.\n if (seenTurnIds.has(ev.turnId)) return;\n seenTurnIds.add(ev.turnId);\n messages.push({ id: uid('m'), role: 'human', text: ev.text, streaming: false });\n emitMessages();\n } else if (ev.type === 'visitor_message') {\n // Echo of the visitor's own message, published so the console inbox sees it live. The widget\n // already rendered this optimistically in sendMessage() - ignore the echo entirely.\n } else if (ev.type === 'state') {\n // Handoff status transition (Phase 7): 'ai' | 'awaiting_human' | 'human'. Ignore any other/\n // future state string - forward-compat, no status line for an unrecognized value.\n if (ev.state === 'ai' || ev.state === 'awaiting_human' || ev.state === 'human') {\n handoffState = ev.state;\n emit({ type: 'handoff', state: handoffState });\n }\n } else if (ev.type === 'agent_typing') {\n // Transient signal only - never pushed as a message, never touches dedup/streaming state.\n emit({ type: 'agentTyping', active: !!ev.active });\n } else if (ev.type === 'suggestions') {\n // Flow-derived quick-reply chips for the latest turn - forwarded verbatim to the widget.\n emit({ type: 'suggestions', items: Array.isArray(ev.items) ? ev.items : [] });\n } else if (ev.type === 'done') {\n // The session ended (flow finished, idle sweep, or a console close). Terminal: stop the stream\n // and reconnection, and surface 'ended' so the widget can offer a fresh start. Drop the persisted\n // session so a reload doesn't resume the dead one (it opens a fresh chat instead).\n closed = true; clearReconnect(); clearRefresh(); es?.close(); es = null;\n clearStoredSession();\n setState('ended');\n }\n // Unknown/future event types are ignored (forward-compat).\n };\n\n // Tickets are single-use and short-lived: a fresh one must be minted for every (re)connect.\n // Native EventSource auto-reconnect would retry the SAME url whose ticket is already consumed\n // (→ 401 forever), so on error we close it ourselves and drive reconnection here instead.\n const openStream = async () => {\n if (!session || closed) return;\n es?.close();\n const { ticket } = await mintStreamTicket({ baseUrl: options.baseUrl, sessionId: session.sessionId, sessionToken: session.sessionToken, fetchImpl });\n if (closed) return;\n es = new ES(streamUrl(options.baseUrl, session.sessionId, ticket));\n es.onopen = () => { reconnectAttempts = 0; };\n es.onmessage = (e: MessageEvent) => { try { onEvent(JSON.parse(e.data) as ChatEvent); } catch { /* ignore malformed */ } };\n es.onerror = () => { es?.close(); es = null; scheduleReconnect(); };\n };\n\n const scheduleReconnect = () => {\n if (closed) return;\n clearReconnect();\n const delay = Math.min(30_000, 500 * 2 ** reconnectAttempts);\n reconnectAttempts += 1;\n reconnectTimer = setTimeout(() => {\n openStream().catch((err) => {\n if (err instanceof ChatApiError && (err as ChatApiError).code === 'session_expired') {\n clearStoredSession(); // don't resume the expired session - force a fresh open\n open().catch((e) => { emit({ type: 'error', error: e as Error }); scheduleReconnect(); });\n } else {\n scheduleReconnect();\n }\n });\n }, delay);\n };\n\n const open = async () => {\n // Resume the existing session on reload (no new /chat/sessions → no new chat in the console). If the\n // resumed session turns out ended/gone server-side, the first message hits the session_expired path,\n // which clears the stored session and opens a fresh one.\n const resumed = loadStoredSession();\n if (resumed) {\n session = resumed;\n emit({ type: 'agent', agent: resumed.agent });\n // History restore (resume-on-reload ONLY — never on a brand-new session below): repaint the\n // full durable transcript before the SSE stream (re)connects, and seed `seenTurnIds` with every\n // restored turn so the buffer-replay's `message`/`token` events for those SAME turns are deduped\n // instead of double-rendered (see onEvent's `message` branch, which already discards a dangling\n // streaming bubble for a turnId it's already seen - seeding here just makes every restored turn\n // \"already seen\" ahead of the replay). Best-effort: a failure (network blip, expired session,\n // or an older server with no endpoint) must never block/break resume — it just falls back to\n // today's behavior (blank transcript + whatever the buffer replay still delivers).\n try {\n const history = await getHistory({ baseUrl: options.baseUrl, sessionId: resumed.sessionId, sessionToken: resumed.sessionToken, fetchImpl });\n for (const h of history) {\n // Only stamp `.turnId` onto assistant/human bubbles. A visitor's own turn shares its\n // turnId with the assistant reply that answered it (see ChatSessionRuntime), and the\n // `citations` handler locates its target by `messages.find(x => x.turnId === ev.turnId)`\n // with no role filter - if the (earlier, user-role) restored bubble also carried that\n // turnId, a replayed citations event would land on the visitor bubble instead of the\n // assistant one. Leaving the user bubble's turnId undefined means nothing can find it by\n // turnId, so citations always resolve to the assistant/human bubble as intended.\n const turnId = h.role === 'assistant' || h.role === 'human' ? h.turnId : undefined;\n messages.push({ id: uid('m'), role: h.role, text: h.text, streaming: false, turnId });\n // Still seed seenTurnIds for EVERY history entry that has one (regardless of role) so the\n // SSE buffer-replay's message/token/visitor_message events for these turns stay deduped.\n if (h.turnId) seenTurnIds.add(h.turnId);\n }\n emitMessages();\n } catch { /* best-effort — resume proceeds exactly as it did before this feature */ }\n await openStream();\n scheduleRefresh();\n flushJourney();\n return;\n }\n if (deviceFingerprint === undefined) deviceFingerprint = await computeDeviceFingerprint().catch(() => null);\n // Advertise the union of host-registered tool names and the SDK's built-ins (navigate, openUrl) —\n // the built-ins run even on a plain embed with no registerTools() call. The server still\n // intersects this with the agent's enabled tools + allowlist, so per-agent gating is unaffected.\n const advertisedTools = new Set([...toolHandlers.keys(), ...Object.keys(BUILTIN_TOOL_HANDLERS)]);\n session = await openSession({ baseUrl: options.baseUrl, apiKey: options.apiKey, agentId: options.agentId, user: options.user, clientTools: Array.from(advertisedTools), fingerprint: deviceFingerprint ?? undefined, fetchImpl });\n persistSession(session);\n // Surface a version drift to the integrator (browser console only, non-fatal) so a stale embed is\n // noticeable when the server contract has moved on.\n if (!warnedProtocol && typeof session.protocol === 'number' && session.protocol !== CHAT_PROTOCOL_VERSION) {\n warnedProtocol = true;\n try { console.warn(`[oyehello-chat] SDK protocol v${CHAT_PROTOCOL_VERSION} vs server v${session.protocol} - update @oyehello/chat to the latest version.`); } catch { /* no console */ }\n }\n emit({ type: 'agent', agent: session.agent });\n await openStream();\n scheduleRefresh();\n flushJourney();\n };\n\n // Presign + PUT every file against the CURRENT session. Called from the main sendMessage path and,\n // after a session_expired reopen, from the retry — a storageRef presigned against the old\n // interactionId is rejected cross-session (403 attachment_cross_session) if reused post-reopen.\n const uploadFiles = async (files: File[]): Promise<ChatAttachmentDescriptor[]> => {\n // Server-proxied: the file goes to OUR API, which streams it to storage (no direct browser→bucket\n // PUT, so no bucket CORS). A storageRef presigned/created against the old interactionId is rejected\n // cross-session if reused post-reopen, so this is re-run from the session_expired retry too.\n return Promise.all(files.map((file) =>\n uploadAttachment({ baseUrl: options.baseUrl, sessionId: session!.sessionId, sessionToken: session!.sessionToken, file, fetchImpl })));\n };\n\n return {\n getMessages: () => messages.slice(),\n getState: () => state,\n on(listener) { listeners.add(listener); return () => listeners.delete(listener); },\n registerTools(handlers) { for (const [name, fn] of Object.entries(handlers)) toolHandlers.set(name, fn); },\n async getAttachmentUrl(storageRef) {\n if (!session) throw new Error('call start() before getAttachmentUrl');\n return getAttachmentUrl({ baseUrl: options.baseUrl, sessionId: session.sessionId, sessionToken: session.sessionToken, storageRef, fetchImpl });\n },\n getWidgetConfig() {\n return getWidgetConfig({ baseUrl: options.baseUrl, apiKey: options.apiKey, agentId: options.agentId, fetchImpl });\n },\n recordPageView(path) {\n try {\n recordView(options.agentId, path);\n flushJourney(); // no-op if no session yet - open()'s flush covers it once one exists\n } catch { /* never throw into the host page */ }\n },\n async start() {\n // Ignore only while a connect is in flight or already live; allow a (re)start from idle, error,\n // or ended so a transient failure is recoverable (e.g. the widget's Retry button) without a page\n // reload. Reset closed/backoff so a restart genuinely reconnects.\n if (state === 'opening' || state === 'ready') return;\n closed = false;\n clearReconnect();\n reconnectAttempts = 0;\n setState('opening');\n try { await open(); setState('ready'); }\n catch (err) { setState('error'); emit({ type: 'error', error: err as Error }); }\n },\n async sendMessage(text, files) {\n if (!session) { emit({ type: 'error', error: new Error('call start() before sendMessage') }); return; }\n const fileList = files ?? [];\n if (fileList.length > maxAttachments) {\n emit({ type: 'error', error: new Error(`too many attachments: max ${maxAttachments} per message`) });\n return;\n }\n const oversized = fileList.find((f) => f.size > maxAttachmentBytes);\n if (oversized) {\n emit({ type: 'error', error: new Error(`attachment too large: ${oversized.name} exceeds ${maxAttachmentBytes} bytes`) });\n return;\n }\n // Upload every file BEFORE posting the message or pushing the optimistic bubble — a failed\n // upload must never leave a broken/partial message in the thread.\n let attachments: ChatAttachmentDescriptor[] = [];\n if (fileList.length > 0) {\n try {\n attachments = await uploadFiles(fileList);\n } catch (err) {\n emit({ type: 'error', error: err as Error });\n return;\n }\n }\n messages.push({ id: uid('u'), role: 'user', text, streaming: false, attachments: attachments.length > 0 ? attachments : undefined }); emitMessages();\n try {\n await postMessage({ baseUrl: options.baseUrl, sessionId: session.sessionId, sessionToken: session.sessionToken, text, attachments, fetchImpl });\n } catch (err) {\n if (err instanceof ChatApiError && err.code === 'session_expired') {\n try {\n clearStoredSession(); // the stored session just expired - don't resume it, open fresh\n await open(); // fresh backend session, same UI thread\n // Re-upload against the NEW session — the old attachments' storageRefs are bound to the\n // stale interactionId and would 403 (attachment_cross_session) if re-posted as-is.\n const freshAttachments = fileList.length ? await uploadFiles(fileList) : [];\n await postMessage({ baseUrl: options.baseUrl, sessionId: session!.sessionId, sessionToken: session!.sessionToken, text, attachments: freshAttachments, fetchImpl });\n } catch (retryErr) {\n emit({ type: 'error', error: retryErr as Error });\n }\n } else { emit({ type: 'error', error: err as Error }); }\n }\n },\n detach() {\n // Stop the transport but keep the server session + stored session alive (see interface note).\n closed = true; clearReconnect(); clearRefresh();\n es?.close(); es = null;\n },\n async end() {\n closed = true; clearReconnect(); clearRefresh(); clearStoredSession();\n if (session) await endSession({ baseUrl: options.baseUrl, sessionId: session.sessionId, sessionToken: session.sessionToken, fetchImpl });\n es?.close(); es = null; setState('ended');\n },\n reset() {\n // Blank slate for a new conversation. start() (allowed from 'ended'/'idle') opens a fresh session.\n // Drop the persisted session so start() doesn't resume the old one.\n clearStoredSession();\n es?.close(); es = null; clearReconnect(); clearRefresh();\n session = null; streamingId = null; handoffState = 'ai';\n messages.length = 0; seenTurnIds.clear(); seenCallIds.clear();\n emit({ type: 'messages', messages: [] });\n emit({ type: 'handoff', state: 'ai' });\n setState('idle');\n },\n };\n}\n","// The host page's own light/dark theme, so `theme=\"auto\"` follows the site the widget is embedded in instead of the\n// visitor's OS. Signals, nearest ancestor first (an app container can be dark inside a light page): a\n// data-theme / data-mode attribute of \"dark\" or \"light\", or a `dark` / `light` class (shadcn, next-themes, Tailwind).\n// Then a single-value `color-scheme` on <html>. null = the page declares nothing, so the OS preference applies.\nexport type PageTheme = 'dark' | 'light';\n\nconst WATCHED = ['class', 'data-theme', 'data-mode', 'style'];\n\nfunction themeOf(node: Element): PageTheme | null {\n for (const attr of ['data-theme', 'data-mode']) {\n const v = node.getAttribute(attr);\n if (v === 'dark' || v === 'light') return v;\n }\n if (node.classList.contains('dark')) return 'dark';\n if (node.classList.contains('light')) return 'light';\n return null;\n}\n\nexport function resolvePageTheme(el: Element): PageTheme | null {\n for (let node: Element | null = el.parentElement; node; node = node.parentElement) {\n const t = themeOf(node);\n if (t) return t;\n }\n const scheme = (document.documentElement.style.colorScheme || getComputedStyle(document.documentElement).colorScheme || '').trim();\n return scheme === 'dark' || scheme === 'light' ? scheme : null;\n}\n\n// Calls onChange now and whenever an ancestor's theme signal changes (a site's theme toggle). Returns a stop function.\nexport function watchPageTheme(el: Element, onChange: (theme: PageTheme | null) => void): () => void {\n let last: PageTheme | null | undefined;\n const check = () => {\n const t = resolvePageTheme(el);\n if (t !== last) { last = t; onChange(t); }\n };\n check();\n if (typeof MutationObserver === 'undefined') return () => {};\n const mo = new MutationObserver(check);\n for (let node: Element | null = el.parentElement; node; node = node.parentElement) {\n mo.observe(node, { attributes: true, attributeFilter: WATCHED });\n }\n return () => mo.disconnect();\n}\n","import { marked } from 'marked';\nimport DOMPurify from 'dompurify';\n\n// GitHub-flavored markdown with single-newline line breaks (chat text rarely uses the two-space\n// hard-break convention). Set once at module load.\nmarked.setOptions({ gfm: true, breaks: true });\n\nlet hookInstalled = false;\nfunction installLinkHook(): void {\n if (hookInstalled) return;\n // Every surviving link opens in a new tab and drops referrer/opener; nofollow since the content is\n // model-generated and visitor-influenced.\n DOMPurify.addHook('afterSanitizeAttributes', (node) => {\n if (node.nodeName === 'A') {\n node.setAttribute('target', '_blank');\n node.setAttribute('rel', 'noopener noreferrer nofollow');\n }\n });\n hookInstalled = true;\n}\n\n// Tags/attributes a chat message may render. Everything else (script, style, iframe, event handlers,\n// inline styles, data-*) is stripped by DOMPurify. javascript:/data: URLs are rejected by the URI\n// regexp, so no link can execute script.\nconst ALLOWED_TAGS = ['p', 'br', 'strong', 'em', 'b', 'i', 'del', 's', 'code', 'pre', 'blockquote',\n 'ul', 'ol', 'li', 'a', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr',\n 'table', 'thead', 'tbody', 'tr', 'th', 'td', 'span'];\nconst ALLOWED_ATTR = ['href', 'target', 'rel', 'class'];\n\n// Render a markdown string to sanitized HTML safe to inject into the widget's shadow DOM. The input\n// is model-generated (and a visitor can influence the conversation), so the output is ALWAYS run\n// through DOMPurify — marked itself passes raw HTML through untouched.\nexport function renderMarkdown(text: string): string {\n installLinkHook();\n const raw = marked.parse(text, { async: false }) as string;\n return DOMPurify.sanitize(raw, {\n ALLOWED_TAGS,\n ALLOWED_ATTR,\n ALLOW_DATA_ATTR: false,\n ALLOWED_URI_REGEXP: /^(?:https?:|mailto:)/i,\n });\n}\n","// Widget CSS, injected once into the shadow root. Ported from the Oyehello Chat Widget design.\n// Every token is namespaced --oc-* so a host page's own custom properties can't bleed across the\n// shadow boundary (custom properties inherit through it). The accent reads the public --oc-accent\n// override (default #096DD9). State is driven by classes on the `.oc` wrapper (open/max/emoji/\n// show-teaser/away/focus/ready/unread/show-ring), so the element toggles classes rather than\n// restyling nodes. NB: state classes are prefixed (show-teaser/show-ring) where a same-named element\n// class exists (.teaser/.ring) — a bare `.teaser{display:none}` would otherwise also match `.oc.teaser`\n// and hide the whole widget (equal specificity, later rule wins).\nexport const STYLES = `\n :host {\n /* accent (consumer-overridable via --oc-accent) + its derivations */\n --oc-ac: var(--oc-accent, #096DD9);\n --oc-btn-rim: color-mix(in oklab, var(--oc-ac) 70%, black);\n --oc-btn-edge: 0 6px 16px -10px color-mix(in oklab, var(--oc-ac) 55%, transparent);\n --oc-danger: #D92D20;\n --oc-ease: cubic-bezier(0.16,1,0.3,1);\n --oc-bounce: cubic-bezier(0.18,0.89,0.32,1.13);\n --oc-mono: 'Geist Mono', ui-monospace, monospace;\n --oc-r-full: 999px;\n\n /* light palette (base) */\n --oc-bg: #FFFFFF; --oc-bg-sunk: #F6F8FB;\n --oc-fg: #0A0D12; --oc-fg-muted: rgba(10,13,18,0.66); --oc-fg-dim: rgba(10,13,18,0.44);\n --oc-border: rgba(9,13,20,0.10);\n --oc-accent-text: color-mix(in oklab, var(--oc-ac) 88%, black);\n --oc-tint-1: rgba(9,13,20,0.025); --oc-tint-2: rgba(9,13,20,0.04); --oc-tint-3: rgba(9,13,20,0.055);\n --oc-field-bg: #FFFFFF; --oc-field-border: rgba(9,13,20,0.22);\n --oc-glass-border: rgba(9,13,20,0.12);\n\n position: fixed; right: 24px; bottom: 24px; z-index: 2147483000;\n /* Explicit display/visibility so a host-page reset or consent/privacy tool that blanket-hides\n * body children (oyehello-chat { display:none }) can't silently kill the widget. Also pinned\n * inline with !important at mount (see element.ts) to beat an external !important rule. */\n display: block; visibility: visible; opacity: 1;\n /* The closed panel still takes up its full size in the layout (it fades, it is not removed), so\n * the host box covers ~384x620px of the page. The host and its wrapper must not catch clicks;\n * only the visible parts opt back in (launcher, teaser while shown, panel while open). */\n pointer-events: none;\n font-family: 'Geist', system-ui, -apple-system, 'Helvetica Neue', sans-serif;\n -webkit-font-smoothing: antialiased;\n }\n @media (prefers-color-scheme: dark) {\n :host(:not([theme=\"light\"]):not([data-oc-page-theme=\"light\"])) {\n --oc-bg: #000000; --oc-bg-sunk: #000000;\n --oc-fg: #FFFFFF; --oc-fg-muted: rgba(255,255,255,0.68); --oc-fg-dim: rgba(255,255,255,0.42);\n --oc-border: rgba(255,255,255,0.09);\n --oc-accent-text: color-mix(in oklab, var(--oc-ac) 62%, white);\n --oc-tint-1: rgba(255,255,255,0.03); --oc-tint-2: rgba(255,255,255,0.05); --oc-tint-3: rgba(255,255,255,0.07);\n --oc-field-bg: rgba(255,255,255,0.045); --oc-field-border: rgba(255,255,255,0.20);\n --oc-glass-border: rgba(255,255,255,0.12);\n }\n }\n /* Explicit dark, or auto on a page that declares dark (data-oc-page-theme, set by page-theme.ts). The OS rule above\n * only applies when the page declares nothing; a page that declares light keeps the light base. */\n :host([theme=\"dark\"]), :host(:not([theme=\"light\"])[data-oc-page-theme=\"dark\"]) {\n --oc-bg: #000000; --oc-bg-sunk: #000000;\n --oc-fg: #FFFFFF; --oc-fg-muted: rgba(255,255,255,0.68); --oc-fg-dim: rgba(255,255,255,0.42);\n --oc-border: rgba(255,255,255,0.09);\n --oc-accent-text: color-mix(in oklab, var(--oc-ac) 62%, white);\n --oc-tint-1: rgba(255,255,255,0.03); --oc-tint-2: rgba(255,255,255,0.05); --oc-tint-3: rgba(255,255,255,0.07);\n --oc-field-bg: rgba(255,255,255,0.045); --oc-field-border: rgba(255,255,255,0.20);\n --oc-glass-border: rgba(255,255,255,0.12);\n }\n * { box-sizing: border-box; }\n button { font-family: inherit; }\n\n .oc { display: flex; flex-direction: column; align-items: flex-end; gap: 14px; pointer-events: none; }\n\n /* ── Launcher ─────────────────────────────────────────────────────────────── */\n .launcher {\n position: relative; flex: none; width: 46px; height: 46px; border-radius: var(--oc-r-full);\n border: 1px solid var(--oc-btn-rim); background: var(--oc-ac);\n box-shadow: 0 8px 22px -8px color-mix(in oklab, var(--oc-ac) 70%, transparent), 0 18px 48px -18px rgba(0,0,0,0.6);\n color: #fff; display: flex; align-items: center; justify-content: center; cursor: pointer;\n transition: transform .26s var(--oc-bounce), filter .2s var(--oc-ease); align-self: flex-end;\n pointer-events: auto;\n }\n .launcher:hover { transform: scale(1.06); }\n .launcher:active { transform: scale(0.93); }\n .ring { pointer-events: none; position: absolute; inset: -1px; border-radius: var(--oc-r-full); border: 2px solid var(--oc-ac); opacity: 0; }\n .oc.show-ring:not(.open) .ring { animation: w-ring 2.4s ease-out 1.1s 3; }\n .ic-chat, .ic-close { position: absolute; display: flex; align-items: center; justify-content: center; transition: all .3s var(--oc-bounce); }\n .ic-chat { width: 28px; height: 28px; opacity: 1; transform: rotate(0) scale(1); }\n .ic-close { opacity: 0; transform: rotate(90deg) scale(0.6); }\n .oc.open .ic-chat { opacity: 0; transform: rotate(-90deg) scale(0.6); }\n .oc.open .ic-close { opacity: 1; transform: rotate(0) scale(1); }\n .badge {\n position: absolute; top: -2px; right: -2px; min-width: 17px; height: 17px; padding: 0 5px;\n border-radius: var(--oc-r-full); border: 2px solid var(--oc-bg-sunk); background: var(--oc-danger);\n color: #fff; font-family: var(--oc-mono); font-size: 10px; font-weight: 700;\n display: flex; align-items: center; justify-content: center; opacity: 0; transform: scale(0.4);\n transition: all .26s var(--oc-bounce);\n }\n .oc.unread:not(.open) .badge { opacity: 1; transform: scale(1); }\n\n /* ── Teaser ───────────────────────────────────────────────────────────────── */\n .teaser {\n position: absolute; right: 0; bottom: 60px; display: none; align-items: center; gap: 11px;\n opacity: 0; transform: translateY(8px) scale(0.94); pointer-events: none;\n transition: opacity .3s var(--oc-ease), transform .38s var(--oc-bounce);\n }\n .oc.has-teaser .teaser { display: flex; }\n .oc.show-teaser:not(.open) .teaser { opacity: 1; transform: none; pointer-events: auto; }\n .teaser-btn {\n max-width: 250px; display: flex; align-items: center; gap: 10px; padding: 11px 15px;\n border-radius: 16px 16px 5px 16px; border: 1px solid var(--oc-glass-border); background: var(--oc-bg);\n box-shadow: 0 10px 30px -14px rgba(0,0,0,0.5); color: var(--oc-fg); font-size: 13.5px; line-height: 1.45;\n text-align: left; cursor: pointer; transition: transform .2s var(--oc-ease);\n }\n .teaser-btn:hover { transform: translateY(-1px); }\n .teaser-btn .logo { flex: none; width: 24px; height: 24px; border-radius: 6px; overflow: hidden; color: var(--oc-ac); }\n .teaser-x {\n flex: none; width: 22px; height: 22px; border-radius: var(--oc-r-full); border: 1px solid var(--oc-border);\n background: var(--oc-bg); color: var(--oc-fg-dim); display: flex; align-items: center; justify-content: center; cursor: pointer;\n }\n .teaser-x:hover { color: var(--oc-fg); }\n\n /* ── Panel ────────────────────────────────────────────────────────────────── */\n .panel {\n position: relative; width: min(384px, calc(100vw - 40px)); height: min(560px, calc(100vh - 108px));\n display: flex; flex-direction: column; border-radius: 20px; border: 1px solid var(--oc-glass-border);\n background: var(--oc-bg); box-shadow: 0 12px 28px -12px rgba(0,0,0,0.28), 0 40px 90px -30px rgba(0,0,0,0.55);\n overflow: hidden; transform-origin: bottom right;\n opacity: 0; transform: translateY(16px) scale(0.94); pointer-events: none; visibility: hidden;\n transition: opacity .24s var(--oc-ease), transform .34s var(--oc-bounce), visibility .34s, width .3s var(--oc-ease), height .3s var(--oc-ease);\n }\n .oc.open .panel { opacity: 1; transform: none; pointer-events: auto; visibility: visible; }\n .oc.max .panel { width: min(720px, calc(100vw - 40px)); height: calc(100vh - 108px); }\n\n .hd { position: relative; flex: none; display: flex; align-items: center; gap: 12px; padding: 13px 14px 12px; background: var(--oc-ac); color: #fff; overflow: hidden; }\n .hd-grid { pointer-events: none; position: absolute; inset: 0; background-image: linear-gradient(90deg, rgba(255,255,255,0.11) 1px, transparent 1px), linear-gradient(180deg, rgba(255,255,255,0.11) 1px, transparent 1px); background-size: 26px 26px; }\n .hd .logo { position: relative; flex: none; width: 32px; height: 32px; border-radius: 7px; overflow: hidden; color: rgba(255,255,255,0.22); }\n .hd-txt { position: relative; flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }\n .hd-title { font-size: 14.5px; font-weight: 600; letter-spacing: -0.015em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n .hd-status { display: flex; align-items: center; gap: 6px; font-size: 11.5px; opacity: 0.9; }\n .hd-status .dot { width: 6px; height: 6px; border-radius: var(--oc-r-full); background: #7BE3A6; flex: none; }\n .hd-status .t { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n .hd-btn { position: relative; flex: none; width: 28px; height: 28px; border-radius: 8px; border: none; background: rgba(255,255,255,0.16); color: #fff; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: background .18s var(--oc-ease); }\n .hd-btn:hover { background: rgba(255,255,255,0.28); }\n .hd-btn .i { position: absolute; display: flex; transition: opacity .2s var(--oc-ease); }\n .i-expand { opacity: 1; } .i-shrink { opacity: 0; }\n .oc.max .i-expand { opacity: 0; } .oc.max .i-shrink { opacity: 1; }\n\n /* Inline connection error, shown inside the chat window (no banner) */\n .oc-err { margin: auto; display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 24px 16px; text-align: center; }\n .oc-err-t { font-size: 13px; line-height: 1.5; color: var(--oc-fg-muted); text-wrap: pretty; }\n .oc-err-retry { padding: 7px 15px; font-size: 12.5px; font-weight: 500; border-radius: var(--oc-r-full); border: 1px solid var(--oc-border); background: var(--oc-tint-2); color: var(--oc-fg); cursor: pointer; transition: background .18s var(--oc-ease); }\n .oc-err-retry:hover { background: var(--oc-tint-3); }\n\n /* Session-ended state, inside the chat window */\n .oc-ended { margin: auto; display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 24px 16px; text-align: center; }\n .oc-ended-t { font-size: 13.5px; line-height: 1.5; color: var(--oc-fg-muted); text-wrap: pretty; }\n .oc-newmsg { padding: 9px 18px; font-size: 13px; font-weight: 600; border-radius: var(--oc-r-full); border: 1px solid var(--oc-btn-rim); background: var(--oc-ac); color: #fff; box-shadow: var(--oc-btn-edge); cursor: pointer; transition: filter .18s var(--oc-ease); }\n .oc-newmsg:hover { filter: brightness(1.08); }\n\n /* ── Message list ─────────────────────────────────────────────────────────── */\n .body { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 16px; padding: 16px 16px 26px; background: var(--oc-bg); scroll-behavior: smooth; }\n .turn { display: flex; flex-direction: column; gap: 6px; animation: w-in .42s var(--oc-ease) both; }\n .turn.bot { align-items: flex-start; } .turn.user { align-items: flex-end; }\n .b { font-size: 13.5px; line-height: 1.55; text-wrap: pretty; word-break: break-word; }\n .turn.bot .b { max-width: 86%; padding: 13px 15px; border-radius: 20px; background: var(--oc-tint-2); color: var(--oc-fg); }\n .turn.user .b { max-width: 82%; padding: 11px 15px; border-radius: var(--oc-r-full); background: var(--oc-ac); color: #fff; }\n .turn.human .b { max-width: 86%; padding: 13px 15px; border-radius: 20px; background: color-mix(in oklab, var(--oc-ac) 16%, transparent); color: var(--oc-fg); }\n .src { display: inline-flex; align-items: center; gap: 7px; padding: 5px 10px 5px 8px; border-radius: var(--oc-r-full); border: 1px solid var(--oc-border); background: var(--oc-tint-1); max-width: 100%; }\n .src .t { min-width: 0; font-size: 11.5px; color: var(--oc-fg-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .byline { display: flex; align-items: center; gap: 6px; padding: 0 4px; font-size: 11.5px; color: var(--oc-fg-dim); }\n .human-label { font-size: 11px; font-weight: 600; opacity: .7; margin-bottom: 2px; }\n\n /* markdown inside a bot bubble */\n .md > :first-child { margin-top: 0; } .md > :last-child { margin-bottom: 0; }\n .md p { margin: 0 0 8px; } .md ul, .md ol { margin: 0 0 8px; padding-left: 20px; } .md li { margin: 2px 0; }\n .md a { color: var(--oc-accent-text); text-decoration: underline; text-underline-offset: 2px; }\n .md code { font-family: var(--oc-mono); font-size: 12.5px; background: var(--oc-tint-3); padding: 1px 5px; border-radius: 5px; }\n .md pre { background: color-mix(in oklab, var(--oc-fg) 10%, transparent); padding: 10px 12px; border-radius: 8px; overflow-x: auto; margin: 0 0 8px; }\n .md pre code { background: none; padding: 0; }\n .md blockquote { margin: 0 0 8px; padding-left: 10px; border-left: 3px solid var(--oc-border); color: var(--oc-fg-muted); }\n .md h1, .md h2, .md h3, .md h4 { margin: 8px 0 6px; font-size: 15px; }\n .md table { border-collapse: collapse; font-size: 13px; margin: 0 0 8px; display: block; overflow-x: auto; }\n .md th, .md td { border: 1px solid var(--oc-border); padding: 4px 8px; }\n .att-thumb { display: block; max-width: 180px; max-height: 180px; border-radius: 8px; margin-bottom: 6px; }\n .att-chip { display: inline-block; font-size: 12px; background: var(--oc-tint-3); border-radius: 6px; padding: 2px 8px; margin: 0 0 6px; }\n .turn.user .att-chip { background: rgba(255,255,255,0.25); }\n\n .typing { align-self: flex-start; display: flex; align-items: center; gap: 5px; padding: 13px 16px; border-radius: 20px; background: var(--oc-tint-2); animation: w-in .3s var(--oc-ease) both; }\n .typing span { width: 6px; height: 6px; border-radius: var(--oc-r-full); background: var(--oc-fg-muted); animation: w-dot 1.2s ease-in-out infinite; }\n .typing span:nth-child(2) { animation-delay: .15s; } .typing span:nth-child(3) { animation-delay: .3s; }\n\n .chips { display: flex; flex-wrap: wrap; gap: 7px; padding-top: 2px; animation: w-in .42s var(--oc-ease) both; animation-delay: .3s; }\n .chip { padding: 8px 13px; border-radius: var(--oc-r-full); border: 1px solid color-mix(in oklab, var(--oc-ac) 34%, transparent); background: color-mix(in oklab, var(--oc-ac) 10%, transparent); color: var(--oc-accent-text); font-size: 12px; font-weight: 500; cursor: pointer; white-space: nowrap; transition: all .18s var(--oc-ease); }\n .chip:hover { background: color-mix(in oklab, var(--oc-ac) 18%, transparent); }\n\n /* ── Jump to latest ───────────────────────────────────────────────────────── */\n .jump-wrap { position: relative; flex: none; height: 0; z-index: 2; display: flex; justify-content: center; }\n .jump { position: absolute; bottom: 8px; width: 34px; height: 34px; border-radius: var(--oc-r-full); border: 1px solid var(--oc-border); background: var(--oc-bg); box-shadow: 0 8px 20px -10px rgba(0,0,0,0.5); color: var(--oc-fg-muted); display: flex; align-items: center; justify-content: center; cursor: pointer; opacity: 0; transform: translateY(6px) scale(0.8); pointer-events: none; transition: all .22s var(--oc-ease); }\n .oc.away .jump { opacity: 1; transform: none; pointer-events: auto; }\n .jump:hover { color: var(--oc-fg); border-color: var(--oc-fg-dim); }\n\n /* ── Composer ─────────────────────────────────────────────────────────────── */\n .composer { flex: none; display: flex; flex-direction: column; gap: 9px; padding: 12px 14px 13px; background: var(--oc-bg); }\n .composer[hidden] { display: none; }\n .field { display: flex; flex-direction: column; gap: 11px; padding: 13px 14px 11px; border-radius: 18px; border: 1px solid var(--oc-field-border); background: var(--oc-field-bg); transition: border-color .18s var(--oc-ease); }\n .oc.focus .field { border-color: var(--oc-ac); }\n .input { width: 100%; border: none; background: transparent; color: var(--oc-fg); font-size: 13.5px; line-height: 1.4; outline: none; padding: 0; resize: none; max-height: 108px; font-family: inherit; }\n .input::placeholder { color: var(--oc-fg-dim); }\n .acts { display: flex; align-items: center; gap: 16px; }\n .act { flex: none; display: flex; border: none; background: transparent; padding: 4px; margin: -4px; color: var(--oc-fg-dim); cursor: pointer; transition: color .18s var(--oc-ease); }\n .act:hover { color: var(--oc-fg-muted); }\n .oc.emoji .act.emoji-btn { color: var(--oc-accent-text); }\n .send { flex: none; margin-left: auto; width: 34px; height: 34px; border-radius: var(--oc-r-full); border: 1px solid var(--oc-border); background: var(--oc-tint-3); color: var(--oc-fg-dim); box-shadow: none; display: flex; align-items: center; justify-content: center; cursor: default; transition: all .22s var(--oc-ease); }\n .oc.ready .send { border-color: var(--oc-btn-rim); background: var(--oc-ac); color: #fff; box-shadow: var(--oc-btn-edge); cursor: pointer; }\n .oc.ready .send:hover { filter: brightness(1.1); }\n .send:active { transform: scale(0.92); }\n\n .foot { position: relative; display: none; text-align: center; font-size: 11.5px; line-height: 1.5; color: var(--oc-fg-dim); }\n .oc.has-privacy .foot { display: block; }\n .foot .priv { color: var(--oc-fg-muted); text-decoration: underline; text-underline-offset: 2px; cursor: default; }\n .foot .tip { position: absolute; left: 0; right: 0; bottom: 16px; padding-bottom: 8px; z-index: 7; display: flex; justify-content: flex-end; pointer-events: none; opacity: 0; transition: opacity .18s var(--oc-ease); }\n .oc.max .foot .tip { right: 188px; }\n .foot:hover .tip { opacity: 1; }\n .foot .tip-card { max-width: 100%; width: 262px; padding: 13px 15px; border-radius: 14px; border: 1px solid var(--oc-border); background: var(--oc-bg); box-shadow: 0 8px 22px -12px rgba(0,0,0,0.32); text-align: left; font-size: 11.5px; line-height: 1.55; color: var(--oc-fg-muted); text-wrap: pretty; transform: translateY(6px); transition: transform .24s var(--oc-bounce); }\n .foot:hover .tip-card { transform: none; }\n .foot .tip-card a { color: var(--oc-fg); text-decoration: underline; text-underline-offset: 2px; }\n\n /* ── Emoji picker ─────────────────────────────────────────────────────────── */\n .emoji-scrim { position: absolute; inset: 0; z-index: 3; display: none; }\n .oc.emoji .emoji-scrim { display: block; }\n .emoji-panel { position: absolute; left: 10px; right: 10px; bottom: 96px; z-index: 4; max-height: min(340px, 58%); display: flex; flex-direction: column; border-radius: 18px; border: 1px solid var(--oc-border); background: var(--oc-bg); box-shadow: 0 18px 46px -18px rgba(0,0,0,0.6); overflow: hidden; opacity: 0; transform: translateY(10px) scale(0.96); transform-origin: bottom center; pointer-events: none; visibility: hidden; transition: opacity .18s var(--oc-ease), transform .26s var(--oc-bounce), visibility .26s; }\n .oc.emoji .emoji-panel { opacity: 1; transform: none; pointer-events: auto; visibility: visible; }\n .emoji-search { flex: none; display: flex; align-items: center; gap: 11px; padding: 13px 16px; border-bottom: 1px solid var(--oc-border); color: var(--oc-fg-dim); }\n .emoji-search input { flex: 1 1 auto; min-width: 0; border: none; background: transparent; color: var(--oc-fg); font-size: 14.5px; outline: none; font-family: inherit; }\n .emoji-search input::placeholder { color: var(--oc-fg-dim); }\n .emoji-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; padding: 12px 14px 16px; }\n .emoji-grp { display: flex; flex-direction: column; gap: 6px; }\n .emoji-grp + .emoji-grp { padding-top: 8px; }\n .emoji-grp-name { font-family: var(--oc-mono); font-size: 9.5px; font-weight: 600; letter-spacing: 0.15em; text-transform: uppercase; color: var(--oc-fg-dim); }\n .emoji-grid { display: grid; grid-template-columns: repeat(7, minmax(0,1fr)); gap: 2px; }\n .emoji-grid button { display: flex; align-items: center; justify-content: center; height: 34px; border-radius: 8px; border: none; background: transparent; font-size: 20px; line-height: 1; cursor: pointer; transition: background .14s var(--oc-ease); }\n .emoji-grid button:hover { background: var(--oc-tint-3); }\n .emoji-empty { display: none; flex-direction: column; align-items: center; gap: 5px; padding: 26px 10px; text-align: center; }\n .emoji-empty .h { font-size: 14px; color: var(--oc-fg); } .emoji-empty .s { font-size: 12.5px; color: var(--oc-fg-dim); }\n\n @media (max-width: 480px) {\n :host { right: 0; bottom: 0; }\n .oc { padding: 0 16px 16px; }\n .panel { position: fixed; inset: 0; width: 100vw; height: 100dvh; border-radius: 0; }\n .oc.max .panel { width: 100vw; height: 100dvh; }\n }\n @media (prefers-reduced-motion: reduce) {\n .launcher, .panel, .teaser, .turn, .jump, .emoji-panel { transition: none; animation: none; }\n .ring { animation: none; } .body { scroll-behavior: auto; }\n }\n\n @keyframes w-in { from { opacity: 0; transform: translateY(10px) scale(0.97); } to { opacity: 1; transform: none; } }\n @keyframes w-dot { 0%,60%,100% { transform: translateY(0); opacity: .45; } 30% { transform: translateY(-4px); opacity: 1; } }\n @keyframes w-ring { 0% { transform: scale(1); opacity: .5; } 70%,100% { transform: scale(1.7); opacity: 0; } }\n`;\n","// SVG markup used across the widget, extracted from the design. Kept as strings so the element can\n// inline them into its shadow DOM without a dependency.\n\n// The OyeHello brand mark. `rectFill` colors the rounded-square backdrop; the glyph is always white.\nexport const logoMark = (rectFill: string) =>\n `<svg viewBox=\"0 0 1032 1024\" fill=\"none\" style=\"display:block;width:100%;height:100%\"><rect x=\"4\" width=\"1024\" height=\"1024\" rx=\"150\" fill=\"${rectFill}\"></rect><path d=\"M430.924 831.644C270.203 859.983 138.14 760.606 111.329 608.551C84.5174 456.497 174.627 317.945 335.348 289.605C496.068 261.266 628.131 360.643 654.943 512.698C681.754 664.752 591.644 803.304 430.924 831.644ZM406.613 693.77C488.549 679.323 518.727 615.513 505.252 539.092C491.777 462.671 441.594 413.031 359.658 427.478C277.722 441.926 247.544 505.736 261.02 582.157C274.495 658.578 324.677 708.218 406.613 693.77ZM870.337 558.389L744.281 580.616C727.055 482.923 674.565 369.515 652.06 241.884L841.143 208.543C863.509 335.387 853.111 460.696 870.337 558.389ZM910.583 740.568L768.771 765.573L745.016 630.852L886.828 605.846L910.583 740.568Z\" fill=\"#fff\"></path></svg>`;\n\nconst stroke = (w: number, path: string, size = 24) =>\n `<svg width=\"${size}\" height=\"${size}\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"${w}\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"display:block;flex:none\">${path}</svg>`;\n\nexport const ICON = {\n close: (size = 19) => stroke(2.4, '<path d=\"M18 6 6 18M6 6l12 12\"/>', size),\n minus: stroke(2, '<path d=\"M6 12h12\"/>', 15),\n expand: stroke(2, '<path d=\"M15 4h5v5M20 4l-6.5 6.5M9 20H4v-5M4 20l6.5-6.5\"/>', 15),\n shrink: stroke(2, '<path d=\"M20 9h-5V4M15 9l5.5-5.5M4 15h5v5M9 15l-5.5 5.5\"/>', 15),\n chevronDown: stroke(2.1, '<path d=\"m6 9 6 6 6-6\"/>', 16),\n send: stroke(2.2, '<path d=\"M12 19V5M6 11l6-6 6 6\"/>', 16),\n paperclip: stroke(1.7, '<path d=\"M21 11.5 12.5 20a5.5 5.5 0 0 1-7.8-7.8l8.5-8.5a3.7 3.7 0 0 1 5.2 5.2l-8.5 8.5a1.8 1.8 0 0 1-2.6-2.6l7.9-7.8\"/>', 17),\n emoji: stroke(1.7, '<circle cx=\"12\" cy=\"12\" r=\"9\"/><path d=\"M8.5 14.5a4.5 4.5 0 0 0 7 0M9 9.5h.01M15 9.5h.01\"/>', 17),\n mic: stroke(1.7, '<rect x=\"9\" y=\"3\" width=\"6\" height=\"11\" rx=\"3\"/><path d=\"M5 11a7 7 0 0 0 14 0M12 18v3\"/>', 17),\n search: stroke(1.9, '<circle cx=\"11\" cy=\"11\" r=\"7.5\"/><path d=\"m21 21-4.3-4.3\"/>', 17),\n clear: stroke(2.2, '<path d=\"M18 6 6 18M6 6l12 12\"/>', 15),\n // Two-page \"source\" glyph for citation chips.\n book: `<svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.7\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"display:block;flex:none;color:var(--oc-accent-text)\"><path d=\"M3 5.5A2.5 2.5 0 0 1 5.5 3H11v18H5.5A2.5 2.5 0 0 1 3 18.5Z\"/><path d=\"M21 5.5A2.5 2.5 0 0 0 18.5 3H13v18h5.5a2.5 2.5 0 0 0 2.5-2.5Z\"/></svg>`,\n teaserDismiss: stroke(2.4, '<path d=\"M18 6 6 18M6 6l12 12\"/>', 12),\n};\n","// Emoji catalogue + search for the composer's picker, ported from the design. Each entry is\n// [character, keyword]; the keyword is what the search box matches against.\nexport interface EmojiGroup { name: string; items: { ch: string; name: string }[] }\n\nconst CATS: { name: string; items: [string, string][] }[] = [\n { name: 'Frequently used', items: [\n ['👍', 'thumbs up'], ['🙏', 'thanks'], ['👋', 'wave'], ['✅', 'done'], ['📞', 'call'], ['😊', 'smile'], ['❤️', 'heart'],\n ] },\n { name: 'Smileys and emotion', items: [\n ['😀', 'grinning'], ['😃', 'smiley'], ['😄', 'grin'], ['😁', 'beaming'], ['😆', 'squinting'], ['😅', 'relief'], ['🤣', 'rolling'],\n ['😂', 'tears of joy'], ['🙂', 'slightly smiling'], ['🙃', 'upside down'], ['😉', 'wink'], ['😇', 'halo'], ['🥰', 'smiling hearts'], ['😍', 'heart eyes'],\n ['😘', 'kiss'], ['😋', 'yum'], ['🤔', 'thinking'], ['🤨', 'raised brow'], ['😐', 'neutral'], ['🙄', 'eye roll'], ['😬', 'grimace'],\n ['😥', 'sad'], ['😢', 'crying'], ['😭', 'sobbing'], ['😠', 'angry'], ['😳', 'flushed'], ['🤩', 'star struck'], ['😴', 'sleeping'],\n ] },\n { name: 'Gestures', items: [\n ['👎', 'thumbs down'], ['👏', 'clap'], ['🙌', 'raised hands'], ['🤝', 'handshake'], ['👌', 'ok hand'], ['✌️', 'victory'], ['💪', 'strong'],\n ['👀', 'eyes'], ['🧠', 'brain'], ['🤟', 'love you'], ['☝️', 'point up'], ['👇', 'point down'], ['🤚', 'raised back'], ['🤞', 'fingers crossed'],\n ] },\n { name: 'Work and travel', items: [\n ['📅', 'calendar'], ['📄', 'document'], ['💰', 'money'], ['📊', 'chart'], ['📦', 'package'], ['🏥', 'hospital'], ['🏦', 'bank'],\n ['🚚', 'truck'], ['✈️', 'plane'], ['📱', 'phone'], ['💻', 'laptop'], ['🔍', 'search'], ['📌', 'pin'], ['🔔', 'bell'],\n ] },\n { name: 'Symbols', items: [\n ['🔥', 'fire'], ['✨', 'sparkles'], ['🎉', 'celebrate'], ['💯', 'hundred'], ['⚠️', 'warning'], ['❌', 'cross'], ['⭐', 'star'],\n ['🚀', 'launch'], ['💚', 'green heart'], ['💙', 'blue heart'], ['🕒', 'clock'], ['💡', 'idea'], ['🔒', 'lock'], ['🎯', 'target'],\n ] },\n];\n\nconst toGroup = (name: string, items: [string, string][]): EmojiGroup => ({\n name,\n items: items.map(([ch, kw]) => ({ ch, name: kw })),\n});\n\n// No query → all categories. With a query → a single group of de-duped keyword matches (mirrors the\n// design's search behaviour), or an empty array when nothing matches (the caller shows an empty state).\nexport function emojiGroups(query: string): EmojiGroup[] {\n const q = query.trim().toLowerCase();\n if (!q) return CATS.map((c) => toGroup(c.name, c.items));\n const hits: [string, string][] = [];\n for (const c of CATS) for (const e of c.items) {\n if (e[1].indexOf(q) >= 0 && !hits.some((h) => h[0] === e[0])) hits.push(e);\n }\n if (!hits.length) return [];\n return [toGroup(`${hits.length} result${hits.length === 1 ? '' : 's'}`, hits)];\n}\n","import { watchPageTheme } from './page-theme';\nimport { createChatClient, type ChatClient, type ChatClientEvent, type ChatMessage, type ChatClientState, type ChatToolHandler, type HandoffState } from './client';\nimport { recordView, installSpaHooks } from './journey';\nimport type { ChatAttachmentDescriptor } from './protocol';\nimport { renderMarkdown } from './markdown';\nimport { STYLES } from './styles';\nimport { ICON, logoMark } from './icons';\nimport { emojiGroups } from './emoji';\n\nconst AGENT_TYPING_TEXT = 'The agent is typing…';\nconst DEFAULT_STATUS = 'Replies in a few seconds';\nconst ATTACHMENT_ACCEPT = 'image/*,application/pdf,text/plain,text/csv';\n// Distance (px) from the bottom past which we treat the reader as scrolled-up (\"away\").\nconst AWAY_THRESHOLD = 60;\n\nconst HANDOFF_STATUS: Record<HandoffState, string | null> = {\n ai: null,\n awaiting_human: 'Connecting you to a person…',\n human: \"You're chatting with a person\",\n};\n\nexport class OyehelloChatElement extends HTMLElement {\n static observedAttributes = ['api-key', 'agent-id', 'base-url', 'title', 'theme'];\n\n // ── live client state ──\n private client: ChatClient | null = null;\n private off: (() => void) | null = null;\n private messages: ChatMessage[] = [];\n private state: ChatClientState = 'idle';\n private agentName: string | null = null;\n private handoffState: HandoffState = 'ai';\n private agentTyping = false;\n private lastError: string | null = null;\n private pendingTools: Record<string, ChatToolHandler> = {};\n private pendingFiles: File[] = [];\n private imagePreviewCache = new Map<string, string>();\n private resolvedUrlCache = new Map<string, string>();\n private mdCache = new Map<string, string>();\n private receivedAt = new Map<string, number>();\n\n // ── widget UI state ──\n private uiOpen = false;\n private started = false;\n private uiMax = false;\n private emojiOpen = false;\n private emojiQuery = '';\n private away = false; // reader scrolled up\n private unseen = 0;\n private focused = false;\n private teaserActive = false;\n private renderedCount = 0;\n private renderedBotFinal = 0;\n private timers: ReturnType<typeof setTimeout>[] = [];\n // Server (flow) suggestions for the latest turn; null until the first `suggestions` event, then the\n // widget prefers these over the static `suggestions` attribute.\n private serverSuggestions: string[] | null = null;\n // The live streaming assistant bubble's markdown element + message id — so growing tokens patch just\n // that element in place instead of rebuilding the whole message list on every token.\n private streamId: string | null = null;\n private streamEl: HTMLElement | null = null;\n private audioCtx: AudioContext | null = null;\n private teaserText = 'Need a hand? Ask me anything.';\n private teaserShownOnce = false;\n // Staffed-hours: set from widget-config. When offline, the panel shows offlineMessage and the\n // composer is disabled (opening a session is refused server-side anyway).\n private offline = false;\n private offlineMessage = \"We're offline right now. Please check back during business hours.\";\n private configLoaded = false; // widget-config resolved (so we know online/offline before starting)\n private idleTimer: ReturnType<typeof setTimeout> | null = null;\n private idleReset: (() => void) | null = null;\n // Uninstaller for the SPA history-navigation hooks (journey tracking), installed in\n // connectedCallback and torn down in disconnectedCallback alongside everything else.\n private uninstallSpaHooks: (() => void) | null = null;\n private unwatchPageTheme: (() => void) | null = null;\n\n // ── shadow refs ──\n private oc!: HTMLElement;\n private bodyEl!: HTMLElement;\n private textareaEl!: HTMLTextAreaElement;\n private composerEl!: HTMLElement;\n private fileEl!: HTMLInputElement;\n private titleEl!: HTMLElement;\n private statusEl!: HTMLElement;\n private emojiListEl!: HTMLElement;\n private emojiSearchEl!: HTMLInputElement;\n\n connectedCallback() {\n if (!this.shadowRoot) this.attachShadow({ mode: 'open' });\n const apiKey = this.getAttribute('api-key');\n const agentId = this.getAttribute('agent-id');\n const baseUrl = this.getAttribute('base-url');\n if (!apiKey || !agentId || !baseUrl) { this.renderError('oyehello-chat: api-key, agent-id and base-url are required'); return; }\n // A `teaser` attribute overrides the server/default text; otherwise the config endpoint supplies it.\n this.teaserText = this.getAttribute('teaser') || this.teaserText;\n this.client = createChatClient({ apiKey, agentId, baseUrl });\n if (Object.keys(this.pendingTools).length > 0) { this.client.registerTools(this.pendingTools); this.pendingTools = {}; }\n this.off = this.client.on((e) => this.onClientEvent(e));\n // Visitor-journey tracking (Task 21): record the current page on every mount - this is what makes\n // Astro's multi-page (full-reload) navigation work, since the element re-mounts fresh on each load.\n // installSpaHooks covers client-routed sites, where the element stays mounted across navigation.\n recordView(agentId, location.pathname);\n // installSpaHooks is written to never throw, but this call site is guarded too - defense in\n // depth, so a host page that manages to make it throw anyway can never abort connectedCallback\n // before renderShell() runs (which would leave the widget entirely unrendered).\n try { this.uninstallSpaHooks = installSpaHooks(() => this.client?.recordPageView(location.pathname)); }\n catch { this.uninstallSpaHooks = null; }\n this.renderShell();\n // theme=\"auto\" (or no theme) follows the host page's own light/dark theme, live; the CSS reads data-oc-page-theme\n // and falls back to the OS preference when the page declares none. An explicit light/dark theme still wins.\n this.unwatchPageTheme?.();\n this.unwatchPageTheme = watchPageTheme(this, (t) => {\n if (t) this.setAttribute('data-oc-page-theme', t); else this.removeAttribute('data-oc-page-theme');\n });\n // Pin the critical visibility inline with !important so a host-page stylesheet (a reset, or a\n // consent/privacy tool that hides body children) can't blank the widget - inline !important beats\n // any external rule, even !important. Positioning stays in the shadow :host rule.\n this.style.setProperty('display', 'block', 'important');\n this.style.setProperty('visibility', 'visible', 'important');\n this.style.setProperty('opacity', '1', 'important');\n this.renderMessages();\n this.updateHeader();\n this.updateStatus();\n this.updateClasses();\n void this.loadWidgetConfig();\n\n let wasOpen = false;\n try { wasOpen = sessionStorage.getItem(this.key('open')) === '1'; } catch { /* blocked */ }\n if (wasOpen) { this.openPanel(); return; }\n\n // Launcher ring (a few pulses to draw the eye) + a teaser nudge after the visitor sits idle.\n this.updateClasses(true);\n this.timers.push(setTimeout(() => { this.oc?.classList.remove('show-ring'); }, 6000));\n this.armIdleTeaser();\n }\n\n // Show the teaser once the visitor has been idle (no page interaction) for 10s — unless the panel\n // is already open or the teaser was dismissed this session. Fires at most once.\n private armIdleTeaser() {\n let dismissed = false;\n try { dismissed = sessionStorage.getItem(this.key('teaser')) === '0'; } catch { /* ignore */ }\n if (dismissed) return;\n const reset = () => {\n if (this.idleTimer) clearTimeout(this.idleTimer);\n this.idleTimer = setTimeout(() => {\n if (!this.uiOpen && !this.teaserShownOnce) { this.teaserActive = true; this.teaserShownOnce = true; this.updateClasses(); this.teardownIdle(); }\n }, 10000);\n };\n this.idleReset = reset;\n for (const ev of ['mousemove', 'keydown', 'scroll', 'touchstart', 'click']) document.addEventListener(ev, reset, { passive: true });\n reset();\n }\n private teardownIdle() {\n if (this.idleTimer) { clearTimeout(this.idleTimer); this.idleTimer = null; }\n if (this.idleReset) { for (const ev of ['mousemove', 'keydown', 'scroll', 'touchstart', 'click']) document.removeEventListener(ev, this.idleReset); this.idleReset = null; }\n }\n\n private async loadWidgetConfig() {\n try {\n const cfg = await this.client!.getWidgetConfig();\n if (!this.getAttribute('teaser') && cfg.teaser) { this.teaserText = cfg.teaser; this.applyTeaserText(); }\n if (cfg.brand) {\n if (cfg.brand.accentColor) this.style.setProperty('--oc-accent', cfg.brand.accentColor);\n if (cfg.brand.name && !this.getAttribute('title')) { this.agentName = cfg.brand.name; this.updateHeader(); }\n if (cfg.brand.logoUrl) this.applyBrandLogo(cfg.brand.logoUrl);\n }\n if (cfg.offline) {\n this.offline = true;\n if (cfg.offlineMessage) this.offlineMessage = cfg.offlineMessage;\n this.renderMessages();\n this.updateStatus();\n }\n } catch { /* non-fatal: defaults stand */ }\n finally {\n // Config is now known. If the panel was opened before it resolved (restore path / a fast click),\n // openPanel deferred the session start to avoid opening one the server would refuse while offline;\n // start it now, unless we're offline.\n this.configLoaded = true;\n if (this.uiOpen && !this.started && !this.offline && this.client) { this.started = true; void this.client.start(); }\n }\n }\n private applyTeaserText() {\n const el = this.shadowRoot?.querySelector('.teaser-btn span:last-child');\n if (el) el.textContent = this.teaserText;\n }\n private applyBrandLogo(url: string) {\n // Set via DOM (img.src property, not innerHTML) so the URL can't be an HTML-injection vector.\n const set = (host: Element | null | undefined) => {\n if (!host) return;\n host.textContent = '';\n const img = document.createElement('img');\n img.src = url; img.alt = '';\n img.style.cssText = 'width:100%;height:100%;object-fit:contain';\n host.appendChild(img);\n };\n set(this.shadowRoot?.querySelector('.hd .logo'));\n set(this.shadowRoot?.querySelector('.teaser-btn .logo'));\n }\n\n disconnectedCallback() {\n // Detach, do NOT end: a transient unmount (framework nav / Astro View Transitions) then re-mounts\n // and resumes the same session, instead of the widget killing the chat + opening a new one on every\n // navigation (the \"launcher comes and goes / new chat each time\" symptom). A real page close leaves\n // the session for the idle sweep.\n this.off?.(); this.client?.detach();\n this.teardownIdle();\n this.uninstallSpaHooks?.(); this.uninstallSpaHooks = null;\n this.unwatchPageTheme?.(); this.unwatchPageTheme = null;\n for (const t of this.timers) clearTimeout(t);\n for (const url of this.imagePreviewCache.values()) { if (typeof URL.revokeObjectURL === 'function') URL.revokeObjectURL(url); }\n this.imagePreviewCache.clear();\n }\n\n registerTools(handlers: Record<string, ChatToolHandler>) {\n if (this.client) this.client.registerTools(handlers);\n else Object.assign(this.pendingTools, handlers);\n }\n\n /** Open the chat window, exactly as a launcher click does. No-op if already open or not rendered. */\n open() {\n if (!this.oc || this.uiOpen) return;\n this.openPanel();\n }\n\n private key(k: string) { return `oyehello-chat:${k}:${this.getAttribute('agent-id') ?? ''}`; }\n // Static fallback chips from the `suggestions` attribute (for embedders without flow-driven ones).\n private get attrSuggestions(): string[] {\n return (this.getAttribute('suggestions') ?? '').split(',').map((s) => s.trim()).filter(Boolean);\n }\n // Effective chips: server (flow) suggestions once received, else the static attribute fallback.\n private get chipLabels(): string[] {\n return this.serverSuggestions ?? this.attrSuggestions;\n }\n\n // ── Shell (built once) ─────────────────────────────────────────────────────────────────────────\n private renderShell() {\n const root = this.shadowRoot!;\n const hasPrivacy = !!this.getAttribute('privacy-url');\n const teaserText = this.teaserText;\n root.innerHTML = `\n <style>${STYLES}</style>\n <div class=\"oc has-teaser${hasPrivacy ? ' has-privacy' : ''}\">\n <div class=\"panel\" role=\"dialog\" aria-label=\"Chat\">\n <div class=\"hd\">\n <span class=\"hd-grid\"></span>\n <span class=\"logo\">${logoMark('currentColor')}</span>\n <span class=\"hd-txt\"><span class=\"hd-title\">Chat</span><span class=\"hd-status\"><span class=\"dot\"></span><span class=\"t\"></span></span></span>\n <button type=\"button\" class=\"hd-btn max\" aria-label=\"Expand\"><span class=\"i i-expand\">${ICON.expand}</span><span class=\"i i-shrink\">${ICON.shrink}</span></button>\n <button type=\"button\" class=\"hd-btn min\" aria-label=\"Minimise\">${ICON.minus}</button>\n </div>\n <div class=\"body\"></div>\n <span class=\"emoji-scrim\"></span>\n <div class=\"emoji-panel\">\n <div class=\"emoji-search\">${ICON.search}<input type=\"text\" placeholder=\"Search emoji…\" aria-label=\"Search emoji\" /></div>\n <div class=\"emoji-list\"></div>\n </div>\n <div class=\"jump-wrap\"><button type=\"button\" class=\"jump\" aria-label=\"Jump to latest\">${ICON.chevronDown}</button></div>\n <div class=\"composer\">\n <form class=\"field\">\n <textarea class=\"input\" rows=\"1\" aria-label=\"message\" placeholder=\"Ask a question…\"></textarea>\n <div class=\"acts\">\n <button type=\"button\" class=\"act attach\" aria-label=\"Attach a file\">${ICON.paperclip}</button>\n <input type=\"file\" accept=\"${ATTACHMENT_ACCEPT}\" multiple hidden />\n <button type=\"button\" class=\"act emoji-btn\" aria-label=\"Insert emoji\">${ICON.emoji}</button>\n <button type=\"button\" class=\"act mic\" aria-label=\"Send a voice note\">${ICON.mic}</button>\n <button type=\"submit\" class=\"send\" aria-label=\"Send\">${ICON.send}</button>\n </div>\n </form>\n <div class=\"foot\">\n <span>By chatting with us, you agree to our </span><span class=\"priv\">Privacy Policy</span>\n <span class=\"tip\"><span class=\"tip-card\">By chatting with us, you agree to the monitoring and recording of this chat to deliver our services and processing of your personal data in accordance with our Privacy Policy. <a href=\"${this.escapeAttr(this.getAttribute('privacy-url') ?? '#')}\" target=\"_blank\" rel=\"noopener noreferrer\">See our Privacy Policy</a>.</span></span>\n </div>\n </div>\n </div>\n\n <div class=\"teaser\">\n <button type=\"button\" class=\"teaser-btn\"><span class=\"logo\">${logoMark('currentColor')}</span><span>${escapeHtml(teaserText)}</span></button>\n <button type=\"button\" class=\"teaser-x\" aria-label=\"Dismiss\">${ICON.teaserDismiss}</button>\n </div>\n\n <button type=\"button\" class=\"launcher\" aria-label=\"Open chat\">\n <span class=\"ring\"></span>\n <span class=\"ic-chat\">${logoMark('var(--oc-ac)')}</span>\n <span class=\"ic-close\">${ICON.close(19)}</span>\n <span class=\"badge\"></span>\n </button>\n </div>`;\n\n this.oc = root.querySelector('.oc')!;\n this.bodyEl = root.querySelector('.body')!;\n this.textareaEl = root.querySelector('textarea.input')!;\n this.composerEl = root.querySelector('.composer')!;\n this.fileEl = root.querySelector('input[type=\"file\"]')!;\n this.titleEl = root.querySelector('.hd-title')!;\n this.statusEl = root.querySelector('.hd-status .t')!;\n this.emojiListEl = root.querySelector('.emoji-list')!;\n this.emojiSearchEl = root.querySelector('.emoji-search input')!;\n\n root.querySelector('.launcher')!.addEventListener('click', () => this.toggle());\n root.querySelector('.hd-btn.min')!.addEventListener('click', () => this.closePanel());\n root.querySelector('.hd-btn.max')!.addEventListener('click', () => { this.uiMax = !this.uiMax; this.updateClasses(); });\n root.querySelector('.teaser-btn')!.addEventListener('click', () => this.openPanel());\n root.querySelector('.teaser-x')!.addEventListener('click', () => this.dismissTeaser());\n root.querySelector('.jump')!.addEventListener('click', () => this.scrollToBottom());\n root.querySelector('.attach')!.addEventListener('click', () => this.fileEl.click());\n this.fileEl.addEventListener('change', () => { this.pendingFiles = this.fileEl.files ? Array.from(this.fileEl.files) : []; });\n root.querySelector('.emoji-btn')!.addEventListener('click', () => this.toggleEmoji());\n root.querySelector('.emoji-scrim')!.addEventListener('click', () => this.closeEmoji());\n this.emojiSearchEl.addEventListener('input', () => { this.emojiQuery = this.emojiSearchEl.value; this.renderEmoji(); });\n this.bodyEl.addEventListener('scroll', () => this.onScroll());\n root.querySelector('form.field')!.addEventListener('submit', (e) => { e.preventDefault(); this.doSend(); });\n this.textareaEl.addEventListener('input', () => { this.autoGrow(); this.updateClasses(); });\n this.textareaEl.addEventListener('focus', () => { this.focused = true; this.updateClasses(); });\n this.textareaEl.addEventListener('blur', () => { this.focused = false; this.updateClasses(); });\n this.textareaEl.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey && !e.isComposing) { e.preventDefault(); this.doSend(); }\n if (e.key === 'Escape') { if (this.emojiOpen) this.closeEmoji(); else this.closePanel(); }\n });\n }\n\n private renderError(msg: string) {\n if (!this.shadowRoot) this.attachShadow({ mode: 'open' });\n // eslint-disable-next-line no-console\n console.error(msg);\n this.shadowRoot!.innerHTML = `<div style=\"position:fixed;right:16px;bottom:16px;color:#b91c1c;font:12px system-ui;background:#fef2f2;border:1px solid #fecaca;padding:8px 12px;border-radius:8px\">${escapeHtml(msg)}</div>`;\n }\n\n // ── State-class sync ──────────────────────────────────────────────────────────────────────────\n // State classes on `.oc` MUST NOT share a name with any element class that has a bare base rule\n // (e.g. `.teaser`, `.ring`): the bare selector would also match `.oc.<state>` and, tying `.oc`'s\n // own rule on specificity, win on source order — e.g. `.teaser{display:none}` would hide the whole\n // widget. Hence the `show-` prefix on the teaser/ring state classes.\n private updateClasses(initialRing = false) {\n if (!this.oc) return;\n const c = this.oc.classList;\n c.toggle('open', this.uiOpen);\n c.toggle('max', this.uiMax);\n c.toggle('emoji', this.emojiOpen);\n c.toggle('show-teaser', this.teaserActive);\n c.toggle('away', this.away);\n c.toggle('focus', this.focused);\n c.toggle('ready', (this.textareaEl?.value.trim().length ?? 0) > 0);\n c.toggle('unread', this.unseen > 0);\n if (initialRing) c.add('show-ring');\n const badge = this.oc.querySelector('.badge');\n if (badge) badge.textContent = this.unseen > 9 ? '9+' : String(this.unseen);\n const launcher = this.oc.querySelector('.launcher');\n if (launcher) launcher.setAttribute('aria-label', this.uiOpen ? 'Close chat' : 'Open chat');\n }\n\n // ── Open / close ───────────────────────────────────────────────────────────────────────────────\n private toggle() { this.uiOpen ? this.closePanel() : this.openPanel(); }\n private openPanel() {\n this.uiOpen = true; this.teaserActive = false; this.unseen = 0;\n this.teardownIdle();\n try { sessionStorage.setItem(this.key('open'), '1'); } catch { /* ignore */ }\n // Don't open a session before widget-config has resolved (we might be offline, and the server would\n // refuse it → the widget would show an error instead of the offline message). If the panel opens\n // first, loadWidgetConfig's finally starts the session once config is known (and not offline).\n if (!this.started && this.client && this.configLoaded && !this.offline) { this.started = true; void this.client.start(); }\n this.updateClasses();\n this.renderMessages();\n this.scrollToBottom();\n if (!this.textareaEl.disabled) setTimeout(() => this.textareaEl.focus(), 60);\n }\n private closePanel() {\n this.uiOpen = false; this.uiMax = false; this.emojiOpen = false;\n try { sessionStorage.setItem(this.key('open'), '0'); } catch { /* ignore */ }\n this.updateClasses();\n }\n private dismissTeaser() {\n this.teaserActive = false;\n try { sessionStorage.setItem(this.key('teaser'), '0'); } catch { /* ignore */ }\n this.updateClasses();\n }\n\n // ── Client events ─────────────────────────────────────────────────────────────────────────────\n private onClientEvent(e: ChatClientEvent) {\n if (e.type === 'messages') this.messages = e.messages;\n else if (e.type === 'state') { this.state = e.state; if (e.state === 'ready' || e.state === 'opening') this.lastError = null; }\n else if (e.type === 'agent') { this.agentName = e.agent.name; this.updateHeader(); }\n else if (e.type === 'handoff') this.handoffState = e.state;\n else if (e.type === 'agentTyping') this.agentTyping = e.active;\n else if (e.type === 'suggestions') this.serverSuggestions = e.items;\n else if (e.type === 'error') this.lastError = e.error.message;\n this.updateStatus();\n this.renderMessages();\n }\n\n private updateHeader() {\n if (this.titleEl) this.titleEl.textContent = this.getAttribute('title') ?? this.agentName ?? 'Chat';\n }\n\n private updateStatus() {\n if (!this.textareaEl) return;\n const disabled = this.state !== 'ready' || this.offline;\n this.textareaEl.disabled = disabled;\n // Once the conversation has ended, hide the composer entirely (not just disable it) - the \"New\n // message\" button in the body is the only way forward. Also hidden while offline (no session).\n if (this.composerEl) this.composerEl.hidden = this.state === 'ended' || this.offline;\n const handoff = HANDOFF_STATUS[this.handoffState];\n const text = this.offline ? 'Offline' : this.state === 'opening' ? 'Connecting…' : handoff ?? (this.getAttribute('status') ?? DEFAULT_STATUS);\n if (this.statusEl) this.statusEl.textContent = text;\n // A connection error is shown inline inside the chat window (see renderMessages), not as a banner.\n }\n\n // ── Message list + scroll ─────────────────────────────────────────────────────────────────────\n private renderMessages() {\n if (!this.bodyEl) return;\n const body = this.bodyEl;\n const last = this.messages[this.messages.length - 1];\n\n // Fast path — the streaming assistant reply grew: patch ONLY its bubble's text instead of\n // rebuilding the whole list (no per-token flicker, other bubbles untouched, scroll preserved).\n if (this.uiOpen && this.streamEl && last && last.id === this.streamId\n && last.role === 'assistant' && last.streaming && this.messages.length === this.renderedCount) {\n this.streamEl.innerHTML = renderMarkdown(last.text || '');\n if (!this.away) this.scrollToBottom();\n return;\n }\n\n const prevTop = body.scrollTop;\n const added = this.messages.length - this.renderedCount;\n const botFinal = this.messages.filter((m) => m.role === 'assistant' && !m.streaming).length;\n const newBotFinal = botFinal > this.renderedBotFinal;\n\n const now = Date.now();\n for (const m of this.messages) if (!this.receivedAt.has(m.id)) this.receivedAt.set(m.id, now);\n\n const lastBot = (() => { for (let i = this.messages.length - 1; i >= 0; i--) if (this.messages[i]?.role === 'assistant') return i; return -1; })();\n let html = this.messages.map((m, i) => this.turnHtml(m, i === lastBot && !this.agentTyping)).join('');\n if (this.agentTyping) html += '<span class=\"typing\"><span></span><span></span><span></span></span>';\n const sugg = this.chipLabels;\n if (sugg.length > 0 && !this.agentTyping && this.state === 'ready') {\n html += `<span class=\"chips\">${sugg.map((s, i) => `<button type=\"button\" class=\"chip\" data-chip=\"${i}\">${escapeHtml(s)}</button>`).join('')}</span>`;\n }\n // Connection error, inline inside the chat window (subtle — no red banner), only when present.\n if (this.state === 'error' && this.lastError) {\n html += `<div class=\"oc-err\"><span class=\"oc-err-t\">${escapeHtml(this.lastError)}</span><button type=\"button\" class=\"oc-err-retry\">Try again</button></div>`;\n }\n // Session ended (flow finished, idle sweep, or a console close): offer a fresh conversation.\n if (this.state === 'ended') {\n html += `<div class=\"oc-ended\"><span class=\"oc-ended-t\">Your conversation has ended.</span><button type=\"button\" class=\"oc-newmsg\">New message</button></div>`;\n }\n // Outside staffed hours: show the offline message (no session has been opened; server refuses one).\n if (this.offline && this.messages.length === 0 && this.state !== 'ended') {\n html += `<div class=\"oc-ended\"><span class=\"oc-ended-t\">${escapeHtml(this.offlineMessage)}</span></div>`;\n }\n body.innerHTML = html;\n this.hydrateAttachmentImages();\n this.bindChips();\n this.renderedCount = this.messages.length;\n this.renderedBotFinal = botFinal;\n\n // Capture the streaming bubble so subsequent token growth hits the fast path above.\n this.streamId = null;\n this.streamEl = null;\n if (last && last.role === 'assistant' && last.streaming) {\n const mds = this.bodyEl.querySelectorAll<HTMLElement>('.turn.bot .md');\n this.streamEl = mds[mds.length - 1] ?? null;\n if (this.streamEl) this.streamId = last.id;\n }\n\n if (!this.uiOpen) { if (added > 0) { this.unseen += added; this.maybeChime(); } this.updateClasses(); return; }\n if (newBotFinal && !this.away) this.parkLastQuestion();\n else if (!this.away) this.scrollToBottom();\n else { body.scrollTop = prevTop; if (added > 0) { this.unseen += added; this.maybeChime(); } }\n this.updateClasses();\n }\n\n // After a reply lands, float the question that prompted it to the top so the answer reads from its\n // first line rather than its last (the design's behaviour).\n private parkLastQuestion() {\n const users = this.bodyEl.querySelectorAll<HTMLElement>('.turn.user');\n const last = users[users.length - 1];\n if (!last) { this.scrollToBottom(); return; }\n const top = Math.max(0, Math.min(last.offsetTop - 22, this.bodyEl.scrollHeight - this.bodyEl.clientHeight));\n this.bodyEl.scrollTo({ top, behavior: 'smooth' });\n }\n\n private onScroll() {\n const b = this.bodyEl;\n const away = b.scrollHeight - b.scrollTop - b.clientHeight > AWAY_THRESHOLD;\n if (away !== this.away) { this.away = away; if (!away) this.unseen = 0; this.updateClasses(); }\n }\n private scrollToBottom() {\n if (!this.bodyEl) return;\n this.bodyEl.scrollTop = this.bodyEl.scrollHeight;\n this.away = false; this.unseen = 0;\n this.updateClasses();\n }\n\n // ── Composer ──────────────────────────────────────────────────────────────────────────────────\n private autoGrow() {\n const ta = this.textareaEl;\n ta.style.height = 'auto';\n ta.style.height = `${Math.min(ta.scrollHeight, 108)}px`;\n }\n private doSend() {\n const text = this.textareaEl.value;\n if (!text.trim()) return;\n const files = this.pendingFiles; this.pendingFiles = []; this.fileEl.value = '';\n for (const f of files) {\n if (f.type.startsWith('image/') && typeof URL.createObjectURL === 'function' && !this.imagePreviewCache.has(f.name)) {\n this.imagePreviewCache.set(f.name, URL.createObjectURL(f));\n }\n }\n this.away = false; this.emojiOpen = false; this.serverSuggestions = []; // hide chips until the next turn's arrive\n void this.client?.sendMessage(text, files.length > 0 ? files : undefined);\n this.textareaEl.value = ''; this.textareaEl.style.height = 'auto';\n this.updateClasses();\n }\n private sendChip(text: string) {\n this.away = false; this.emojiOpen = false; this.serverSuggestions = []; // hide chips until the next turn's arrive\n void this.client?.sendMessage(text);\n this.updateClasses();\n }\n private bindChips() {\n const sugg = this.chipLabels;\n this.bodyEl.querySelectorAll<HTMLButtonElement>('.chip[data-chip]').forEach((btn) => {\n const i = Number(btn.getAttribute('data-chip'));\n const text = sugg[i];\n if (text) btn.addEventListener('click', () => this.sendChip(text));\n });\n // Inline connection-error retry (rendered in the body, not a banner).\n this.bodyEl.querySelector('.oc-err-retry')?.addEventListener('click', () => { void this.client?.start(); });\n // \"New message\" after a session ended → fresh conversation.\n this.bodyEl.querySelector('.oc-newmsg')?.addEventListener('click', () => this.startFresh());\n }\n\n // Reset the thread and open a brand-new session (the widget's \"New message\" after a session ended).\n private startFresh() {\n this.serverSuggestions = null;\n this.receivedAt.clear();\n this.mdCache.clear();\n this.streamId = null; this.streamEl = null;\n this.renderedCount = 0; this.renderedBotFinal = 0;\n this.away = false; this.unseen = 0;\n this.client?.reset();\n this.started = true;\n void this.client?.start();\n setTimeout(() => this.textareaEl?.focus(), 60);\n }\n\n // A short two-tone chime for an incoming message the visitor hasn't seen (panel closed or scrolled\n // up). Off when the `sound=\"off\"` attribute is set. Uses WebAudio (no asset); silent if unavailable\n // or the browser hasn't allowed audio yet.\n private maybeChime() {\n const last = this.messages[this.messages.length - 1];\n if (last && (last.role === 'assistant' || last.role === 'human')) this.playChime();\n }\n private playChime() {\n if (this.getAttribute('sound') === 'off') return;\n try {\n const Ctx = window.AudioContext ?? (window as unknown as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;\n if (!Ctx) return;\n if (!this.audioCtx) this.audioCtx = new Ctx();\n const ctx = this.audioCtx;\n if (ctx.state === 'suspended') void ctx.resume();\n const now = ctx.currentTime;\n [880, 1174.66].forEach((freq, i) => {\n const osc = ctx.createOscillator();\n const gain = ctx.createGain();\n osc.type = 'sine';\n osc.frequency.value = freq;\n const t = now + i * 0.11;\n gain.gain.setValueAtTime(0.0001, t);\n gain.gain.exponentialRampToValueAtTime(0.12, t + 0.02);\n gain.gain.exponentialRampToValueAtTime(0.0001, t + 0.18);\n osc.connect(gain);\n gain.connect(ctx.destination);\n osc.start(t);\n osc.stop(t + 0.2);\n });\n } catch { /* audio unavailable */ }\n }\n\n // ── Emoji ─────────────────────────────────────────────────────────────────────────────────────\n private toggleEmoji() { this.emojiOpen = !this.emojiOpen; this.emojiQuery = ''; this.emojiSearchEl.value = ''; this.renderEmoji(); this.updateClasses(); if (this.emojiOpen) setTimeout(() => this.emojiSearchEl.focus(), 60); }\n private closeEmoji() { this.emojiOpen = false; this.emojiQuery = ''; this.updateClasses(); }\n private renderEmoji() {\n const groups = emojiGroups(this.emojiQuery);\n let html = groups.map((g) => `\n <div class=\"emoji-grp\"><span class=\"emoji-grp-name\">${escapeHtml(g.name)}</span>\n <div class=\"emoji-grid\">${g.items.map((e) => `<button type=\"button\" title=\"${this.escapeAttr(e.name)}\" aria-label=\"${this.escapeAttr(e.name)}\" data-ch=\"${this.escapeAttr(e.ch)}\">${e.ch}</button>`).join('')}</div>\n </div>`).join('');\n if (groups.length === 0) html = '<span class=\"emoji-empty\" style=\"display:flex\"><span class=\"h\">No emoji match that</span><span class=\"s\">Try a shorter word, like smile or call.</span></span>';\n this.emojiListEl.innerHTML = html;\n this.emojiListEl.querySelectorAll<HTMLButtonElement>('button[data-ch]').forEach((btn) => {\n btn.addEventListener('click', () => {\n this.textareaEl.value += btn.getAttribute('data-ch') ?? '';\n this.emojiOpen = false;\n this.autoGrow();\n this.updateClasses();\n this.textareaEl.focus();\n });\n });\n }\n\n // ── Bubble rendering ──────────────────────────────────────────────────────────────────────────\n private turnHtml(m: ChatMessage, isLastBot: boolean): string {\n const role = m.role === 'user' ? 'user' : m.role === 'human' ? 'human' : 'bot';\n const atts = (m.attachments ?? []).map((a) => this.renderAttachment(a)).join('');\n let content: string;\n if (m.role === 'assistant') {\n // Only the AI's text renders markdown; cache finalized turns, re-render only the live one.\n let rendered = m.streaming ? undefined : this.mdCache.get(m.id);\n if (rendered === undefined) { rendered = renderMarkdown(m.text || ''); if (!m.streaming) this.mdCache.set(m.id, rendered); }\n content = `<span class=\"b\">${atts}<span class=\"md\">${rendered}</span></span>`;\n } else {\n const label = m.role === 'human' ? '<div class=\"human-label\">Support</div>' : '';\n content = `<span class=\"b\">${label}${atts}${escapeHtml(m.text)}</span>`;\n }\n\n const src = (m.sources && m.sources.length > 0)\n ? `<span class=\"src\">${ICON.book}<span class=\"t\">${escapeHtml('From ' + (m.sources[0]?.title ?? ''))}</span></span>`\n : '';\n const byline = (role === 'bot' && isLastBot)\n ? `<span class=\"byline\">${escapeHtml((this.agentName ?? 'OyeHello') + ' · AI agent · ' + this.relTime(m.id))}</span>`\n : '';\n return `<span class=\"turn ${role}\">${content}${src}${byline}</span>`;\n }\n\n private relTime(id: string): string {\n const t = this.receivedAt.get(id);\n if (!t) return 'just now';\n const mins = Math.floor((Date.now() - t) / 60000);\n return mins <= 0 ? 'just now' : `${mins} min ago`;\n }\n\n private renderAttachment(a: ChatAttachmentDescriptor): string {\n if (a.contentType.startsWith('image/')) {\n const cached = (a.name ? this.imagePreviewCache.get(a.name) : undefined) ?? this.resolvedUrlCache.get(a.storageRef);\n const srcAttr = cached ? ` src=\"${cached}\"` : '';\n return `<img class=\"att-thumb\" data-oc-ref=\"${this.escapeAttr(a.storageRef)}\"${srcAttr} alt=\"${this.escapeAttr(a.name ?? 'image')}\"/>`;\n }\n return `<div class=\"att-chip\">📎 ${escapeHtml(a.name ?? a.contentType)}</div>`;\n }\n\n private hydrateAttachmentImages() {\n if (!this.client) return;\n this.shadowRoot!.querySelectorAll<HTMLImageElement>('img.att-thumb[data-oc-ref]').forEach((img) => {\n if (img.hasAttribute('src')) return;\n const ref = img.getAttribute('data-oc-ref');\n if (!ref) return;\n void this.client!.getAttachmentUrl(ref)\n .then((url) => { this.resolvedUrlCache.set(ref, url); img.src = url; })\n .catch(() => { /* no thumbnail is an acceptable degrade */ });\n });\n }\n\n private escapeAttr(s: string) { return s.replace(/[&<>\"]/g, (c) => ({ '&': '&', '<': '<', '>': '>', '\"': '"' }[c]!)); }\n}\n\nfunction escapeHtml(s: string) { return s.replace(/[&<>\"]/g, (c) => ({ '&': '&', '<': '<', '>': '>', '\"': '"' }[c]!)); }\n","export { ChatApiError } from './errors';\nexport type { ChatEvent, OpenSessionResponse, ChatClientOptions, ChatAttachmentDescriptor, WidgetConfig } from './protocol';\nexport { createChatClient } from './client';\nexport type { ChatClient, ChatMessage, ChatClientState, ChatClientEvent, ChatToolHandler } from './client';\nexport { OyehelloChatElement } from './element';\n\nimport { OyehelloChatElement } from './element';\n// Side effect: registering the element is why the package is sideEffects:true.\nif (typeof customElements !== 'undefined' && !customElements.get('oyehello-chat')) {\n customElements.define('oyehello-chat', OyehelloChatElement);\n}\n"]}
|