@paramms/chat-widget 1.0.36 → 1.0.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -1
- package/dist/chatlist.js +135 -72
- package/dist/chatlist.js.map +1 -1
- package/dist/codec.js +1135 -0
- package/dist/codec.js.map +1 -0
- package/dist/core.js +14 -14
- package/dist/core.js.map +1 -1
- package/dist/embed.js +32 -14
- package/dist/embed.js.map +1 -1
- package/dist/hooks.js +1 -1
- package/dist/index.js +452 -393
- package/dist/index.js.map +1 -1
- package/dist/outbox.js +170 -1210
- package/dist/outbox.js.map +1 -1
- package/dist/protocol/frames.d.ts +5 -0
- package/dist/react.d.ts +11 -3
- package/dist/react.js +317 -258
- package/dist/react.js.map +1 -1
- package/dist/renderer.d.ts +9 -7
- package/package.json +1 -1
- package/dist/uid.js +0 -91
- package/dist/uid.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec.js","sources":["../src/history.ts","../src/uid.ts","../node_modules/@msgpack/msgpack/dist.esm/utils/utf8.mjs","../node_modules/@msgpack/msgpack/dist.esm/ExtData.mjs","../node_modules/@msgpack/msgpack/dist.esm/DecodeError.mjs","../node_modules/@msgpack/msgpack/dist.esm/utils/int.mjs","../node_modules/@msgpack/msgpack/dist.esm/timestamp.mjs","../node_modules/@msgpack/msgpack/dist.esm/ExtensionCodec.mjs","../node_modules/@msgpack/msgpack/dist.esm/utils/typedArrays.mjs","../node_modules/@msgpack/msgpack/dist.esm/Encoder.mjs","../node_modules/@msgpack/msgpack/dist.esm/encode.mjs","../node_modules/@msgpack/msgpack/dist.esm/utils/prettyByte.mjs","../node_modules/@msgpack/msgpack/dist.esm/CachedKeyDecoder.mjs","../node_modules/@msgpack/msgpack/dist.esm/Decoder.mjs","../node_modules/@msgpack/msgpack/dist.esm/decode.mjs","../src/protocol/codec.ts"],"sourcesContent":["// history.ts — shared REST history-fetch logic for both the guest widget\n// (index.ts) and the agent dashboard (operate.ts).\n//\n// Strategy:\n// • On open: fetch the latest 20 messages. Fast, cheap, covers most chats.\n// • hasMore=true → show a sentinel div at the top of the scroll area.\n// • When the sentinel scrolls into view (IntersectionObserver) fetch the\n// next 20 older messages and prepend — no button click required.\n// • This is the same infinite-scroll-upward pattern used by WhatsApp/Telegram.\n\nimport type { ChatStore } from './store.js'\nimport type { Message, ConversationId } from './protocol/index.js'\nimport type { Renderer } from './renderer.js'\n\nconst PAGE = 20 // messages per fetch — fast first load, smooth pagination\n\n/** Resolve a single user-supplied relay URL into the concrete WebSocket URL and\n * HTTP(S) base the client needs.\n *\n * Accepts any scheme — `https://`, `http://`, `wss://`, or `ws://` — and any of\n * these shapes: bare origin (`https://api.example.com`), origin with `/ws`\n * (`wss://api.example.com/ws`), or a sub-path (`https://api.example.com/relay`).\n *\n * https://api.example.com → ws wss://api.example.com/ws · http https://api.example.com\n * wss://api.example.com/ws → ws wss://api.example.com/ws · http https://api.example.com\n * http://localhost:3000 → ws ws://localhost:3000/ws · http http://localhost:3000\n *\n * `https`/`wss` map to a secure socket (`wss`); `http`/`ws` map to `ws`. A bare\n * host with no scheme is assumed secure. Pass `apiBaseOverride` only when the\n * REST API lives on a different origin than the socket. */\nexport function resolveRelayUrls(input: string, apiBaseOverride?: string): { wsUrl: string; httpBase: string } {\n const trimmed = input.trim().replace(/\\/+$/, '')\n const scheme = trimmed.match(/^(https|http|wss|ws):\\/\\//)?.[1]\n const secure = scheme ? scheme === 'https' || scheme === 'wss' : true\n const authorityAndPath = (scheme ? trimmed.slice(scheme.length + 3) : trimmed).replace(/\\/ws$/, '')\n const httpBase = apiBaseOverride\n ? apiBaseOverride.trim().replace(/\\/+$/, '')\n : `${secure ? 'https' : 'http'}://${authorityAndPath}`\n const wsUrl = `${secure ? 'wss' : 'ws'}://${authorityAndPath}/ws`\n return { wsUrl, httpBase }\n}\n\n/** Derive the HTTP(S) base origin from a ws(s):// URL.\n * @deprecated prefer {@link resolveRelayUrls}; kept for back-compat. */\nexport function httpBaseFromWsUrl(wsUrl: string): string {\n return resolveRelayUrls(wsUrl).httpBase\n}\n\n/** Build the best history URL for the given token context.\n * Staff tokens use /messages (full access); guest tokens use /history. */\nfunction historyUrl(httpBase: string, conversationId: string, beforeSeq: number, limit: number): string[] {\n const qs = `beforeSeq=${beforeSeq}&limit=${limit}`\n return [\n `${httpBase}/conversations/${conversationId}/messages?${qs}`,\n `${httpBase}/conversations/${conversationId}/history?${qs}`,\n ]\n}\n\n/** Fetch one page of history. Tries staff endpoint first, falls back to guest. */\nasync function fetchPage(\n httpBase: string,\n conversationId: string,\n token: string,\n beforeSeq: number,\n limit = PAGE,\n): Promise<{ messages: Message[]; hasMore: boolean } | null> {\n for (const url of historyUrl(httpBase, conversationId, beforeSeq, limit)) {\n try {\n const res = await fetch(url, { headers: { authorization: `Bearer ${token}` } })\n if (!res.ok) continue\n const data = await res.json() as { messages?: Message[]; hasMore?: boolean }\n return { messages: data.messages ?? [], hasMore: data.hasMore ?? false }\n } catch { /* try next */ }\n }\n return null\n}\n\n/** Initial history restore on conversation open.\n *\n * Fetches the latest PAGE messages and sets up scroll-triggered loading for\n * older messages via IntersectionObserver on a sentinel at the top of the\n * scroll container. No buttons — scrolling up loads more automatically.\n *\n * Returns a cleanup function — call it when the conversation is closed to\n * disconnect the observer and prevent stale updates. */\nexport async function restoreHistory(\n wsUrl: string,\n token: string,\n conversationId: ConversationId,\n store: ChatStore,\n renderer: Renderer,\n apiBase?: string,\n): Promise<void> {\n const httpBase = apiBase ? apiBase.replace(/\\/+$/, '') : httpBaseFromWsUrl(wsUrl)\n\n const page = await fetchPage(httpBase, conversationId as string, token, Number.MAX_SAFE_INTEGER)\n if (!page) return\n\n if (page.messages.length) {\n store.apply({ type: 'sync', conversationId, messages: page.messages })\n // Always set hasMore from the response\n store.apply({ type: 'history', conversationId, messages: [], hasMore: page.hasMore })\n renderer.render(store)\n } else {\n // No messages — still record hasMore=false so the sentinel doesn't show\n store.apply({ type: 'history', conversationId, messages: [], hasMore: false })\n }\n\n if (!page.hasMore) return\n\n // ── Scroll-triggered load-more ────────────────────────────────────────────\n // Watch the sentinel div (the \"↑ Load earlier messages\" button rendered by\n // the Renderer at the top of the scroll area). When it becomes visible,\n // fetch the next page of older messages.\n let loading = false\n\n const loadOlder = async () => {\n if (loading || !store.hasMoreHistory) return\n loading = true\n const oldest = store.messages()[0]\n if (!oldest) { loading = false; return }\n const page2 = await fetchPage(httpBase, conversationId as string, token, oldest.seq)\n if (page2) {\n store.apply({ type: 'history', conversationId, messages: page2.messages, hasMore: page2.hasMore })\n renderer.render(store)\n }\n loading = false\n }\n\n // Use IntersectionObserver to detect when the user scrolls to the top.\n // We observe the scroll container itself — when scrollTop < 40px, load more.\n const scrollEl = renderer.getScrollEl()\n if (!scrollEl) return\n\n // Wait 300ms before arming the scroll listener — the initial render scrolls\n // to the bottom, which briefly passes through scrollTop=0 and could trigger\n // a spurious load before the user actually scrolls up.\n let armed = false\n setTimeout(() => { armed = true }, 300)\n\n const onScroll = () => {\n if (!armed) return\n if (scrollEl.scrollTop < 80 && store.hasMoreHistory && !loading) {\n void loadOlder()\n }\n }\n scrollEl.addEventListener('scroll', onScroll, { passive: true })\n renderer.setScrollCleanup(() => scrollEl.removeEventListener('scroll', onScroll))\n}\n","/** Persistent anonymous identity, reused across reloads.\n *\n * Persists through BOTH localStorage and a first-party cookie. On a top-level\n * page (e.g. a standalone hosted widget at relay.example.com) the cookie\n * survives even if localStorage is unavailable or cleared, so a guest keeps\n * the same id across refreshes — which is what lets the server resolve their\n * existing conversation and load history. (In a cross-origin iframe both may\n * be partitioned; pass an explicit `userId`/`token` for that case.)\n */\nconst KEY = 'oc_uid'\n\nfunction readCookie(name: string): string | null {\n try {\n const m = document.cookie.match(new RegExp(`(?:^|; )${name}=([^;]*)`))\n return m ? decodeURIComponent(m[1]!) : null\n } catch { return null }\n}\n\nfunction writeCookie(name: string, value: string): void {\n try {\n const maxAge = 60 * 60 * 24 * 365 // 1 year\n const secure = location.protocol === 'https:' ? '; Secure' : ''\n document.cookie = `${name}=${encodeURIComponent(value)}; Max-Age=${maxAge}; Path=/; SameSite=Lax${secure}`\n } catch { /* cookies disabled — best effort */ }\n}\n\nfunction newId(): string {\n return `g_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`\n}\n\nexport function persistentUid(): string {\n let existing: string | null = null\n try { existing = localStorage.getItem(KEY) } catch { /* unavailable */ }\n if (!existing) existing = readCookie(KEY)\n\n const id = existing ?? newId()\n\n // Write through to both stores so whichever is available carries it forward.\n try { localStorage.setItem(KEY, id) } catch { /* unavailable */ }\n writeCookie(KEY, id)\n\n return id\n}\n","export function utf8Count(str) {\n const strLength = str.length;\n let byteLength = 0;\n let pos = 0;\n while (pos < strLength) {\n let value = str.charCodeAt(pos++);\n if ((value & 0xffffff80) === 0) {\n // 1-byte\n byteLength++;\n continue;\n }\n else if ((value & 0xfffff800) === 0) {\n // 2-bytes\n byteLength += 2;\n }\n else {\n // handle surrogate pair\n if (value >= 0xd800 && value <= 0xdbff) {\n // high surrogate\n if (pos < strLength) {\n const extra = str.charCodeAt(pos);\n if ((extra & 0xfc00) === 0xdc00) {\n ++pos;\n value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000;\n }\n }\n }\n if ((value & 0xffff0000) === 0) {\n // 3-byte\n byteLength += 3;\n }\n else {\n // 4-byte\n byteLength += 4;\n }\n }\n }\n return byteLength;\n}\nexport function utf8EncodeJs(str, output, outputOffset) {\n const strLength = str.length;\n let offset = outputOffset;\n let pos = 0;\n while (pos < strLength) {\n let value = str.charCodeAt(pos++);\n if ((value & 0xffffff80) === 0) {\n // 1-byte\n output[offset++] = value;\n continue;\n }\n else if ((value & 0xfffff800) === 0) {\n // 2-bytes\n output[offset++] = ((value >> 6) & 0x1f) | 0xc0;\n }\n else {\n // handle surrogate pair\n if (value >= 0xd800 && value <= 0xdbff) {\n // high surrogate\n if (pos < strLength) {\n const extra = str.charCodeAt(pos);\n if ((extra & 0xfc00) === 0xdc00) {\n ++pos;\n value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000;\n }\n }\n }\n if ((value & 0xffff0000) === 0) {\n // 3-byte\n output[offset++] = ((value >> 12) & 0x0f) | 0xe0;\n output[offset++] = ((value >> 6) & 0x3f) | 0x80;\n }\n else {\n // 4-byte\n output[offset++] = ((value >> 18) & 0x07) | 0xf0;\n output[offset++] = ((value >> 12) & 0x3f) | 0x80;\n output[offset++] = ((value >> 6) & 0x3f) | 0x80;\n }\n }\n output[offset++] = (value & 0x3f) | 0x80;\n }\n}\n// TextEncoder and TextDecoder are standardized in whatwg encoding:\n// https://encoding.spec.whatwg.org/\n// and available in all the modern browsers:\n// https://caniuse.com/textencoder\n// They are available in Node.js since v12 LTS as well:\n// https://nodejs.org/api/globals.html#textencoder\nconst sharedTextEncoder = new TextEncoder();\n// This threshold should be determined by benchmarking, which might vary in engines and input data.\n// Run `npx ts-node benchmark/encode-string.ts` for details.\nconst TEXT_ENCODER_THRESHOLD = 50;\nexport function utf8EncodeTE(str, output, outputOffset) {\n sharedTextEncoder.encodeInto(str, output.subarray(outputOffset));\n}\nexport function utf8Encode(str, output, outputOffset) {\n if (str.length > TEXT_ENCODER_THRESHOLD) {\n utf8EncodeTE(str, output, outputOffset);\n }\n else {\n utf8EncodeJs(str, output, outputOffset);\n }\n}\nconst CHUNK_SIZE = 4096;\nexport function utf8DecodeJs(bytes, inputOffset, byteLength) {\n let offset = inputOffset;\n const end = offset + byteLength;\n const units = [];\n let result = \"\";\n while (offset < end) {\n const byte1 = bytes[offset++];\n if ((byte1 & 0x80) === 0) {\n // 1 byte\n units.push(byte1);\n }\n else if ((byte1 & 0xe0) === 0xc0) {\n // 2 bytes\n const byte2 = bytes[offset++] & 0x3f;\n units.push(((byte1 & 0x1f) << 6) | byte2);\n }\n else if ((byte1 & 0xf0) === 0xe0) {\n // 3 bytes\n const byte2 = bytes[offset++] & 0x3f;\n const byte3 = bytes[offset++] & 0x3f;\n units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3);\n }\n else if ((byte1 & 0xf8) === 0xf0) {\n // 4 bytes\n const byte2 = bytes[offset++] & 0x3f;\n const byte3 = bytes[offset++] & 0x3f;\n const byte4 = bytes[offset++] & 0x3f;\n let unit = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4;\n if (unit > 0xffff) {\n unit -= 0x10000;\n units.push(((unit >>> 10) & 0x3ff) | 0xd800);\n unit = 0xdc00 | (unit & 0x3ff);\n }\n units.push(unit);\n }\n else {\n units.push(byte1);\n }\n if (units.length >= CHUNK_SIZE) {\n result += String.fromCharCode(...units);\n units.length = 0;\n }\n }\n if (units.length > 0) {\n result += String.fromCharCode(...units);\n }\n return result;\n}\nconst sharedTextDecoder = new TextDecoder();\n// This threshold should be determined by benchmarking, which might vary in engines and input data.\n// Run `npx ts-node benchmark/decode-string.ts` for details.\nconst TEXT_DECODER_THRESHOLD = 200;\nexport function utf8DecodeTD(bytes, inputOffset, byteLength) {\n const stringBytes = bytes.subarray(inputOffset, inputOffset + byteLength);\n return sharedTextDecoder.decode(stringBytes);\n}\nexport function utf8Decode(bytes, inputOffset, byteLength) {\n if (byteLength > TEXT_DECODER_THRESHOLD) {\n return utf8DecodeTD(bytes, inputOffset, byteLength);\n }\n else {\n return utf8DecodeJs(bytes, inputOffset, byteLength);\n }\n}\n//# sourceMappingURL=utf8.mjs.map","/**\n * ExtData is used to handle Extension Types that are not registered to ExtensionCodec.\n */\nexport class ExtData {\n type;\n data;\n constructor(type, data) {\n this.type = type;\n this.data = data;\n }\n}\n//# sourceMappingURL=ExtData.mjs.map","export class DecodeError extends Error {\n constructor(message) {\n super(message);\n // fix the prototype chain in a cross-platform way\n const proto = Object.create(DecodeError.prototype);\n Object.setPrototypeOf(this, proto);\n Object.defineProperty(this, \"name\", {\n configurable: true,\n enumerable: false,\n value: DecodeError.name,\n });\n }\n}\n//# sourceMappingURL=DecodeError.mjs.map","// Integer Utility\nexport const UINT32_MAX = 4294967295;\n// DataView extension to handle int64 / uint64,\n// where the actual range is 53-bits integer (a.k.a. safe integer)\nexport function setUint64(view, offset, value) {\n const high = value / 4294967296;\n const low = value; // high bits are truncated by DataView\n view.setUint32(offset, high);\n view.setUint32(offset + 4, low);\n}\nexport function setInt64(view, offset, value) {\n const high = Math.floor(value / 4294967296);\n const low = value; // high bits are truncated by DataView\n view.setUint32(offset, high);\n view.setUint32(offset + 4, low);\n}\nexport function getInt64(view, offset) {\n const high = view.getInt32(offset);\n const low = view.getUint32(offset + 4);\n return high * 4294967296 + low;\n}\nexport function getUint64(view, offset) {\n const high = view.getUint32(offset);\n const low = view.getUint32(offset + 4);\n return high * 4294967296 + low;\n}\n//# sourceMappingURL=int.mjs.map","// https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type\nimport { DecodeError } from \"./DecodeError.mjs\";\nimport { getInt64, setInt64 } from \"./utils/int.mjs\";\nexport const EXT_TIMESTAMP = -1;\nconst TIMESTAMP32_MAX_SEC = 0x100000000 - 1; // 32-bit unsigned int\nconst TIMESTAMP64_MAX_SEC = 0x400000000 - 1; // 34-bit unsigned int\nexport function encodeTimeSpecToTimestamp({ sec, nsec }) {\n if (sec >= 0 && nsec >= 0 && sec <= TIMESTAMP64_MAX_SEC) {\n // Here sec >= 0 && nsec >= 0\n if (nsec === 0 && sec <= TIMESTAMP32_MAX_SEC) {\n // timestamp 32 = { sec32 (unsigned) }\n const rv = new Uint8Array(4);\n const view = new DataView(rv.buffer);\n view.setUint32(0, sec);\n return rv;\n }\n else {\n // timestamp 64 = { nsec30 (unsigned), sec34 (unsigned) }\n const secHigh = sec / 0x100000000;\n const secLow = sec & 0xffffffff;\n const rv = new Uint8Array(8);\n const view = new DataView(rv.buffer);\n // nsec30 | secHigh2\n view.setUint32(0, (nsec << 2) | (secHigh & 0x3));\n // secLow32\n view.setUint32(4, secLow);\n return rv;\n }\n }\n else {\n // timestamp 96 = { nsec32 (unsigned), sec64 (signed) }\n const rv = new Uint8Array(12);\n const view = new DataView(rv.buffer);\n view.setUint32(0, nsec);\n setInt64(view, 4, sec);\n return rv;\n }\n}\nexport function encodeDateToTimeSpec(date) {\n const msec = date.getTime();\n const sec = Math.floor(msec / 1e3);\n const nsec = (msec - sec * 1e3) * 1e6;\n // Normalizes { sec, nsec } to ensure nsec is unsigned.\n const nsecInSec = Math.floor(nsec / 1e9);\n return {\n sec: sec + nsecInSec,\n nsec: nsec - nsecInSec * 1e9,\n };\n}\nexport function encodeTimestampExtension(object) {\n if (object instanceof Date) {\n const timeSpec = encodeDateToTimeSpec(object);\n return encodeTimeSpecToTimestamp(timeSpec);\n }\n else {\n return null;\n }\n}\nexport function decodeTimestampToTimeSpec(data) {\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n // data may be 32, 64, or 96 bits\n switch (data.byteLength) {\n case 4: {\n // timestamp 32 = { sec32 }\n const sec = view.getUint32(0);\n const nsec = 0;\n return { sec, nsec };\n }\n case 8: {\n // timestamp 64 = { nsec30, sec34 }\n const nsec30AndSecHigh2 = view.getUint32(0);\n const secLow32 = view.getUint32(4);\n const sec = (nsec30AndSecHigh2 & 0x3) * 0x100000000 + secLow32;\n const nsec = nsec30AndSecHigh2 >>> 2;\n return { sec, nsec };\n }\n case 12: {\n // timestamp 96 = { nsec32 (unsigned), sec64 (signed) }\n const sec = getInt64(view, 4);\n const nsec = view.getUint32(0);\n return { sec, nsec };\n }\n default:\n throw new DecodeError(`Unrecognized data size for timestamp (expected 4, 8, or 12): ${data.length}`);\n }\n}\nexport function decodeTimestampExtension(data) {\n const timeSpec = decodeTimestampToTimeSpec(data);\n return new Date(timeSpec.sec * 1e3 + timeSpec.nsec / 1e6);\n}\nexport const timestampExtension = {\n type: EXT_TIMESTAMP,\n encode: encodeTimestampExtension,\n decode: decodeTimestampExtension,\n};\n//# sourceMappingURL=timestamp.mjs.map","// ExtensionCodec to handle MessagePack extensions\nimport { ExtData } from \"./ExtData.mjs\";\nimport { timestampExtension } from \"./timestamp.mjs\";\nexport class ExtensionCodec {\n static defaultCodec = new ExtensionCodec();\n // ensures ExtensionCodecType<X> matches ExtensionCodec<X>\n // this will make type errors a lot more clear\n // eslint-disable-next-line @typescript-eslint/naming-convention\n __brand;\n // built-in extensions\n builtInEncoders = [];\n builtInDecoders = [];\n // custom extensions\n encoders = [];\n decoders = [];\n constructor() {\n this.register(timestampExtension);\n }\n register({ type, encode, decode, }) {\n if (type >= 0) {\n // custom extensions\n this.encoders[type] = encode;\n this.decoders[type] = decode;\n }\n else {\n // built-in extensions\n const index = -1 - type;\n this.builtInEncoders[index] = encode;\n this.builtInDecoders[index] = decode;\n }\n }\n tryToEncode(object, context) {\n // built-in extensions\n for (let i = 0; i < this.builtInEncoders.length; i++) {\n const encodeExt = this.builtInEncoders[i];\n if (encodeExt != null) {\n const data = encodeExt(object, context);\n if (data != null) {\n const type = -1 - i;\n return new ExtData(type, data);\n }\n }\n }\n // custom extensions\n for (let i = 0; i < this.encoders.length; i++) {\n const encodeExt = this.encoders[i];\n if (encodeExt != null) {\n const data = encodeExt(object, context);\n if (data != null) {\n const type = i;\n return new ExtData(type, data);\n }\n }\n }\n if (object instanceof ExtData) {\n // to keep ExtData as is\n return object;\n }\n return null;\n }\n decode(data, type, context) {\n const decodeExt = type < 0 ? this.builtInDecoders[-1 - type] : this.decoders[type];\n if (decodeExt) {\n return decodeExt(data, type, context);\n }\n else {\n // decode() does not fail, returns ExtData instead.\n return new ExtData(type, data);\n }\n }\n}\n//# sourceMappingURL=ExtensionCodec.mjs.map","function isArrayBufferLike(buffer) {\n return (buffer instanceof ArrayBuffer || (typeof SharedArrayBuffer !== \"undefined\" && buffer instanceof SharedArrayBuffer));\n}\nexport function ensureUint8Array(buffer) {\n if (buffer instanceof Uint8Array) {\n return buffer;\n }\n else if (ArrayBuffer.isView(buffer)) {\n return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);\n }\n else if (isArrayBufferLike(buffer)) {\n return new Uint8Array(buffer);\n }\n else {\n // ArrayLike<number>\n return Uint8Array.from(buffer);\n }\n}\n//# sourceMappingURL=typedArrays.mjs.map","import { utf8Count, utf8Encode } from \"./utils/utf8.mjs\";\nimport { ExtensionCodec } from \"./ExtensionCodec.mjs\";\nimport { setInt64, setUint64 } from \"./utils/int.mjs\";\nimport { ensureUint8Array } from \"./utils/typedArrays.mjs\";\nexport const DEFAULT_MAX_DEPTH = 100;\nexport const DEFAULT_INITIAL_BUFFER_SIZE = 2048;\nexport class Encoder {\n extensionCodec;\n context;\n useBigInt64;\n maxDepth;\n initialBufferSize;\n sortKeys;\n forceFloat32;\n ignoreUndefined;\n forceIntegerToFloat;\n pos;\n view;\n bytes;\n entered = false;\n constructor(options) {\n this.extensionCodec = options?.extensionCodec ?? ExtensionCodec.defaultCodec;\n this.context = options?.context; // needs a type assertion because EncoderOptions has no context property when ContextType is undefined\n this.useBigInt64 = options?.useBigInt64 ?? false;\n this.maxDepth = options?.maxDepth ?? DEFAULT_MAX_DEPTH;\n this.initialBufferSize = options?.initialBufferSize ?? DEFAULT_INITIAL_BUFFER_SIZE;\n this.sortKeys = options?.sortKeys ?? false;\n this.forceFloat32 = options?.forceFloat32 ?? false;\n this.ignoreUndefined = options?.ignoreUndefined ?? false;\n this.forceIntegerToFloat = options?.forceIntegerToFloat ?? false;\n this.pos = 0;\n this.view = new DataView(new ArrayBuffer(this.initialBufferSize));\n this.bytes = new Uint8Array(this.view.buffer);\n }\n clone() {\n // Because of slightly special argument `context`,\n // type assertion is needed.\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n return new Encoder({\n extensionCodec: this.extensionCodec,\n context: this.context,\n useBigInt64: this.useBigInt64,\n maxDepth: this.maxDepth,\n initialBufferSize: this.initialBufferSize,\n sortKeys: this.sortKeys,\n forceFloat32: this.forceFloat32,\n ignoreUndefined: this.ignoreUndefined,\n forceIntegerToFloat: this.forceIntegerToFloat,\n });\n }\n reinitializeState() {\n this.pos = 0;\n }\n /**\n * This is almost equivalent to {@link Encoder#encode}, but it returns an reference of the encoder's internal buffer and thus much faster than {@link Encoder#encode}.\n *\n * @returns Encodes the object and returns a shared reference the encoder's internal buffer.\n */\n encodeSharedRef(object) {\n if (this.entered) {\n const instance = this.clone();\n return instance.encodeSharedRef(object);\n }\n try {\n this.entered = true;\n this.reinitializeState();\n this.doEncode(object, 1);\n return this.bytes.subarray(0, this.pos);\n }\n finally {\n this.entered = false;\n }\n }\n /**\n * @returns Encodes the object and returns a copy of the encoder's internal buffer.\n */\n encode(object) {\n if (this.entered) {\n const instance = this.clone();\n return instance.encode(object);\n }\n try {\n this.entered = true;\n this.reinitializeState();\n this.doEncode(object, 1);\n return this.bytes.slice(0, this.pos);\n }\n finally {\n this.entered = false;\n }\n }\n doEncode(object, depth) {\n if (depth > this.maxDepth) {\n throw new Error(`Too deep objects in depth ${depth}`);\n }\n if (object == null) {\n this.encodeNil();\n }\n else if (typeof object === \"boolean\") {\n this.encodeBoolean(object);\n }\n else if (typeof object === \"number\") {\n if (!this.forceIntegerToFloat) {\n this.encodeNumber(object);\n }\n else {\n this.encodeNumberAsFloat(object);\n }\n }\n else if (typeof object === \"string\") {\n this.encodeString(object);\n }\n else if (this.useBigInt64 && typeof object === \"bigint\") {\n this.encodeBigInt64(object);\n }\n else {\n this.encodeObject(object, depth);\n }\n }\n ensureBufferSizeToWrite(sizeToWrite) {\n const requiredSize = this.pos + sizeToWrite;\n if (this.view.byteLength < requiredSize) {\n this.resizeBuffer(requiredSize * 2);\n }\n }\n resizeBuffer(newSize) {\n const newBuffer = new ArrayBuffer(newSize);\n const newBytes = new Uint8Array(newBuffer);\n const newView = new DataView(newBuffer);\n newBytes.set(this.bytes);\n this.view = newView;\n this.bytes = newBytes;\n }\n encodeNil() {\n this.writeU8(0xc0);\n }\n encodeBoolean(object) {\n if (object === false) {\n this.writeU8(0xc2);\n }\n else {\n this.writeU8(0xc3);\n }\n }\n encodeNumber(object) {\n if (!this.forceIntegerToFloat && Number.isSafeInteger(object)) {\n if (object >= 0) {\n if (object < 0x80) {\n // positive fixint\n this.writeU8(object);\n }\n else if (object < 0x100) {\n // uint 8\n this.writeU8(0xcc);\n this.writeU8(object);\n }\n else if (object < 0x10000) {\n // uint 16\n this.writeU8(0xcd);\n this.writeU16(object);\n }\n else if (object < 0x100000000) {\n // uint 32\n this.writeU8(0xce);\n this.writeU32(object);\n }\n else if (!this.useBigInt64) {\n // uint 64\n this.writeU8(0xcf);\n this.writeU64(object);\n }\n else {\n this.encodeNumberAsFloat(object);\n }\n }\n else {\n if (object >= -0x20) {\n // negative fixint\n this.writeU8(0xe0 | (object + 0x20));\n }\n else if (object >= -0x80) {\n // int 8\n this.writeU8(0xd0);\n this.writeI8(object);\n }\n else if (object >= -0x8000) {\n // int 16\n this.writeU8(0xd1);\n this.writeI16(object);\n }\n else if (object >= -0x80000000) {\n // int 32\n this.writeU8(0xd2);\n this.writeI32(object);\n }\n else if (!this.useBigInt64) {\n // int 64\n this.writeU8(0xd3);\n this.writeI64(object);\n }\n else {\n this.encodeNumberAsFloat(object);\n }\n }\n }\n else {\n this.encodeNumberAsFloat(object);\n }\n }\n encodeNumberAsFloat(object) {\n if (this.forceFloat32) {\n // float 32\n this.writeU8(0xca);\n this.writeF32(object);\n }\n else {\n // float 64\n this.writeU8(0xcb);\n this.writeF64(object);\n }\n }\n encodeBigInt64(object) {\n if (object >= BigInt(0)) {\n // uint 64\n this.writeU8(0xcf);\n this.writeBigUint64(object);\n }\n else {\n // int 64\n this.writeU8(0xd3);\n this.writeBigInt64(object);\n }\n }\n writeStringHeader(byteLength) {\n if (byteLength < 32) {\n // fixstr\n this.writeU8(0xa0 + byteLength);\n }\n else if (byteLength < 0x100) {\n // str 8\n this.writeU8(0xd9);\n this.writeU8(byteLength);\n }\n else if (byteLength < 0x10000) {\n // str 16\n this.writeU8(0xda);\n this.writeU16(byteLength);\n }\n else if (byteLength < 0x100000000) {\n // str 32\n this.writeU8(0xdb);\n this.writeU32(byteLength);\n }\n else {\n throw new Error(`Too long string: ${byteLength} bytes in UTF-8`);\n }\n }\n encodeString(object) {\n const maxHeaderSize = 1 + 4;\n const byteLength = utf8Count(object);\n this.ensureBufferSizeToWrite(maxHeaderSize + byteLength);\n this.writeStringHeader(byteLength);\n utf8Encode(object, this.bytes, this.pos);\n this.pos += byteLength;\n }\n encodeObject(object, depth) {\n // try to encode objects with custom codec first of non-primitives\n const ext = this.extensionCodec.tryToEncode(object, this.context);\n if (ext != null) {\n this.encodeExtension(ext);\n }\n else if (Array.isArray(object)) {\n this.encodeArray(object, depth);\n }\n else if (ArrayBuffer.isView(object)) {\n this.encodeBinary(object);\n }\n else if (typeof object === \"object\") {\n this.encodeMap(object, depth);\n }\n else {\n // symbol, function and other special object come here unless extensionCodec handles them.\n throw new Error(`Unrecognized object: ${Object.prototype.toString.apply(object)}`);\n }\n }\n encodeBinary(object) {\n const size = object.byteLength;\n if (size < 0x100) {\n // bin 8\n this.writeU8(0xc4);\n this.writeU8(size);\n }\n else if (size < 0x10000) {\n // bin 16\n this.writeU8(0xc5);\n this.writeU16(size);\n }\n else if (size < 0x100000000) {\n // bin 32\n this.writeU8(0xc6);\n this.writeU32(size);\n }\n else {\n throw new Error(`Too large binary: ${size}`);\n }\n const bytes = ensureUint8Array(object);\n this.writeU8a(bytes);\n }\n encodeArray(object, depth) {\n const size = object.length;\n if (size < 16) {\n // fixarray\n this.writeU8(0x90 + size);\n }\n else if (size < 0x10000) {\n // array 16\n this.writeU8(0xdc);\n this.writeU16(size);\n }\n else if (size < 0x100000000) {\n // array 32\n this.writeU8(0xdd);\n this.writeU32(size);\n }\n else {\n throw new Error(`Too large array: ${size}`);\n }\n for (const item of object) {\n this.doEncode(item, depth + 1);\n }\n }\n countWithoutUndefined(object, keys) {\n let count = 0;\n for (const key of keys) {\n if (object[key] !== undefined) {\n count++;\n }\n }\n return count;\n }\n encodeMap(object, depth) {\n const keys = Object.keys(object);\n if (this.sortKeys) {\n keys.sort();\n }\n const size = this.ignoreUndefined ? this.countWithoutUndefined(object, keys) : keys.length;\n if (size < 16) {\n // fixmap\n this.writeU8(0x80 + size);\n }\n else if (size < 0x10000) {\n // map 16\n this.writeU8(0xde);\n this.writeU16(size);\n }\n else if (size < 0x100000000) {\n // map 32\n this.writeU8(0xdf);\n this.writeU32(size);\n }\n else {\n throw new Error(`Too large map object: ${size}`);\n }\n for (const key of keys) {\n const value = object[key];\n if (!(this.ignoreUndefined && value === undefined)) {\n this.encodeString(key);\n this.doEncode(value, depth + 1);\n }\n }\n }\n encodeExtension(ext) {\n if (typeof ext.data === \"function\") {\n const data = ext.data(this.pos + 6);\n const size = data.length;\n if (size >= 0x100000000) {\n throw new Error(`Too large extension object: ${size}`);\n }\n this.writeU8(0xc9);\n this.writeU32(size);\n this.writeI8(ext.type);\n this.writeU8a(data);\n return;\n }\n const size = ext.data.length;\n if (size === 1) {\n // fixext 1\n this.writeU8(0xd4);\n }\n else if (size === 2) {\n // fixext 2\n this.writeU8(0xd5);\n }\n else if (size === 4) {\n // fixext 4\n this.writeU8(0xd6);\n }\n else if (size === 8) {\n // fixext 8\n this.writeU8(0xd7);\n }\n else if (size === 16) {\n // fixext 16\n this.writeU8(0xd8);\n }\n else if (size < 0x100) {\n // ext 8\n this.writeU8(0xc7);\n this.writeU8(size);\n }\n else if (size < 0x10000) {\n // ext 16\n this.writeU8(0xc8);\n this.writeU16(size);\n }\n else if (size < 0x100000000) {\n // ext 32\n this.writeU8(0xc9);\n this.writeU32(size);\n }\n else {\n throw new Error(`Too large extension object: ${size}`);\n }\n this.writeI8(ext.type);\n this.writeU8a(ext.data);\n }\n writeU8(value) {\n this.ensureBufferSizeToWrite(1);\n this.view.setUint8(this.pos, value);\n this.pos++;\n }\n writeU8a(values) {\n const size = values.length;\n this.ensureBufferSizeToWrite(size);\n this.bytes.set(values, this.pos);\n this.pos += size;\n }\n writeI8(value) {\n this.ensureBufferSizeToWrite(1);\n this.view.setInt8(this.pos, value);\n this.pos++;\n }\n writeU16(value) {\n this.ensureBufferSizeToWrite(2);\n this.view.setUint16(this.pos, value);\n this.pos += 2;\n }\n writeI16(value) {\n this.ensureBufferSizeToWrite(2);\n this.view.setInt16(this.pos, value);\n this.pos += 2;\n }\n writeU32(value) {\n this.ensureBufferSizeToWrite(4);\n this.view.setUint32(this.pos, value);\n this.pos += 4;\n }\n writeI32(value) {\n this.ensureBufferSizeToWrite(4);\n this.view.setInt32(this.pos, value);\n this.pos += 4;\n }\n writeF32(value) {\n this.ensureBufferSizeToWrite(4);\n this.view.setFloat32(this.pos, value);\n this.pos += 4;\n }\n writeF64(value) {\n this.ensureBufferSizeToWrite(8);\n this.view.setFloat64(this.pos, value);\n this.pos += 8;\n }\n writeU64(value) {\n this.ensureBufferSizeToWrite(8);\n setUint64(this.view, this.pos, value);\n this.pos += 8;\n }\n writeI64(value) {\n this.ensureBufferSizeToWrite(8);\n setInt64(this.view, this.pos, value);\n this.pos += 8;\n }\n writeBigUint64(value) {\n this.ensureBufferSizeToWrite(8);\n this.view.setBigUint64(this.pos, value);\n this.pos += 8;\n }\n writeBigInt64(value) {\n this.ensureBufferSizeToWrite(8);\n this.view.setBigInt64(this.pos, value);\n this.pos += 8;\n }\n}\n//# sourceMappingURL=Encoder.mjs.map","import { Encoder } from \"./Encoder.mjs\";\n/**\n * It encodes `value` in the MessagePack format and\n * returns a byte buffer.\n *\n * The returned buffer is a slice of a larger `ArrayBuffer`, so you have to use its `#byteOffset` and `#byteLength` in order to convert it to another typed arrays including NodeJS `Buffer`.\n */\nexport function encode(value, options) {\n const encoder = new Encoder(options);\n return encoder.encodeSharedRef(value);\n}\n//# sourceMappingURL=encode.mjs.map","export function prettyByte(byte) {\n return `${byte < 0 ? \"-\" : \"\"}0x${Math.abs(byte).toString(16).padStart(2, \"0\")}`;\n}\n//# sourceMappingURL=prettyByte.mjs.map","import { utf8DecodeJs } from \"./utils/utf8.mjs\";\nconst DEFAULT_MAX_KEY_LENGTH = 16;\nconst DEFAULT_MAX_LENGTH_PER_KEY = 16;\nexport class CachedKeyDecoder {\n hit = 0;\n miss = 0;\n caches;\n maxKeyLength;\n maxLengthPerKey;\n constructor(maxKeyLength = DEFAULT_MAX_KEY_LENGTH, maxLengthPerKey = DEFAULT_MAX_LENGTH_PER_KEY) {\n this.maxKeyLength = maxKeyLength;\n this.maxLengthPerKey = maxLengthPerKey;\n // avoid `new Array(N)`, which makes a sparse array,\n // because a sparse array is typically slower than a non-sparse array.\n this.caches = [];\n for (let i = 0; i < this.maxKeyLength; i++) {\n this.caches.push([]);\n }\n }\n canBeCached(byteLength) {\n return byteLength > 0 && byteLength <= this.maxKeyLength;\n }\n find(bytes, inputOffset, byteLength) {\n const records = this.caches[byteLength - 1];\n FIND_CHUNK: for (const record of records) {\n const recordBytes = record.bytes;\n for (let j = 0; j < byteLength; j++) {\n if (recordBytes[j] !== bytes[inputOffset + j]) {\n continue FIND_CHUNK;\n }\n }\n return record.str;\n }\n return null;\n }\n store(bytes, value) {\n const records = this.caches[bytes.length - 1];\n const record = { bytes, str: value };\n if (records.length >= this.maxLengthPerKey) {\n // `records` are full!\n // Set `record` to an arbitrary position.\n records[(Math.random() * records.length) | 0] = record;\n }\n else {\n records.push(record);\n }\n }\n decode(bytes, inputOffset, byteLength) {\n const cachedValue = this.find(bytes, inputOffset, byteLength);\n if (cachedValue != null) {\n this.hit++;\n return cachedValue;\n }\n this.miss++;\n const str = utf8DecodeJs(bytes, inputOffset, byteLength);\n // Ensure to copy a slice of bytes because the bytes may be a NodeJS Buffer and Buffer#slice() returns a reference to its internal ArrayBuffer.\n const slicedCopyOfBytes = Uint8Array.prototype.slice.call(bytes, inputOffset, inputOffset + byteLength);\n this.store(slicedCopyOfBytes, str);\n return str;\n }\n}\n//# sourceMappingURL=CachedKeyDecoder.mjs.map","import { prettyByte } from \"./utils/prettyByte.mjs\";\nimport { ExtensionCodec } from \"./ExtensionCodec.mjs\";\nimport { getInt64, getUint64, UINT32_MAX } from \"./utils/int.mjs\";\nimport { utf8Decode } from \"./utils/utf8.mjs\";\nimport { ensureUint8Array } from \"./utils/typedArrays.mjs\";\nimport { CachedKeyDecoder } from \"./CachedKeyDecoder.mjs\";\nimport { DecodeError } from \"./DecodeError.mjs\";\nconst STATE_ARRAY = \"array\";\nconst STATE_MAP_KEY = \"map_key\";\nconst STATE_MAP_VALUE = \"map_value\";\nconst mapKeyConverter = (key) => {\n if (typeof key === \"string\" || typeof key === \"number\") {\n return key;\n }\n throw new DecodeError(\"The type of key must be string or number but \" + typeof key);\n};\nclass StackPool {\n stack = [];\n stackHeadPosition = -1;\n get length() {\n return this.stackHeadPosition + 1;\n }\n top() {\n return this.stack[this.stackHeadPosition];\n }\n pushArrayState(size) {\n const state = this.getUninitializedStateFromPool();\n state.type = STATE_ARRAY;\n state.position = 0;\n state.size = size;\n state.array = new Array(size);\n }\n pushMapState(size) {\n const state = this.getUninitializedStateFromPool();\n state.type = STATE_MAP_KEY;\n state.readCount = 0;\n state.size = size;\n state.map = {};\n }\n getUninitializedStateFromPool() {\n this.stackHeadPosition++;\n if (this.stackHeadPosition === this.stack.length) {\n const partialState = {\n type: undefined,\n size: 0,\n array: undefined,\n position: 0,\n readCount: 0,\n map: undefined,\n key: null,\n };\n this.stack.push(partialState);\n }\n return this.stack[this.stackHeadPosition];\n }\n release(state) {\n const topStackState = this.stack[this.stackHeadPosition];\n if (topStackState !== state) {\n throw new Error(\"Invalid stack state. Released state is not on top of the stack.\");\n }\n if (state.type === STATE_ARRAY) {\n const partialState = state;\n partialState.size = 0;\n partialState.array = undefined;\n partialState.position = 0;\n partialState.type = undefined;\n }\n if (state.type === STATE_MAP_KEY || state.type === STATE_MAP_VALUE) {\n const partialState = state;\n partialState.size = 0;\n partialState.map = undefined;\n partialState.readCount = 0;\n partialState.type = undefined;\n }\n this.stackHeadPosition--;\n }\n reset() {\n this.stack.length = 0;\n this.stackHeadPosition = -1;\n }\n}\nconst HEAD_BYTE_REQUIRED = -1;\nconst EMPTY_VIEW = new DataView(new ArrayBuffer(0));\nconst EMPTY_BYTES = new Uint8Array(EMPTY_VIEW.buffer);\ntry {\n // IE11: The spec says it should throw RangeError,\n // IE11: but in IE11 it throws TypeError.\n EMPTY_VIEW.getInt8(0);\n}\ncatch (e) {\n if (!(e instanceof RangeError)) {\n throw new Error(\"This module is not supported in the current JavaScript engine because DataView does not throw RangeError on out-of-bounds access\");\n }\n}\nconst MORE_DATA = new RangeError(\"Insufficient data\");\nconst sharedCachedKeyDecoder = new CachedKeyDecoder();\nexport class Decoder {\n extensionCodec;\n context;\n useBigInt64;\n rawStrings;\n maxStrLength;\n maxBinLength;\n maxArrayLength;\n maxMapLength;\n maxExtLength;\n keyDecoder;\n mapKeyConverter;\n totalPos = 0;\n pos = 0;\n view = EMPTY_VIEW;\n bytes = EMPTY_BYTES;\n headByte = HEAD_BYTE_REQUIRED;\n stack = new StackPool();\n entered = false;\n constructor(options) {\n this.extensionCodec = options?.extensionCodec ?? ExtensionCodec.defaultCodec;\n this.context = options?.context; // needs a type assertion because EncoderOptions has no context property when ContextType is undefined\n this.useBigInt64 = options?.useBigInt64 ?? false;\n this.rawStrings = options?.rawStrings ?? false;\n this.maxStrLength = options?.maxStrLength ?? UINT32_MAX;\n this.maxBinLength = options?.maxBinLength ?? UINT32_MAX;\n this.maxArrayLength = options?.maxArrayLength ?? UINT32_MAX;\n this.maxMapLength = options?.maxMapLength ?? UINT32_MAX;\n this.maxExtLength = options?.maxExtLength ?? UINT32_MAX;\n this.keyDecoder = options?.keyDecoder !== undefined ? options.keyDecoder : sharedCachedKeyDecoder;\n this.mapKeyConverter = options?.mapKeyConverter ?? mapKeyConverter;\n }\n clone() {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n return new Decoder({\n extensionCodec: this.extensionCodec,\n context: this.context,\n useBigInt64: this.useBigInt64,\n rawStrings: this.rawStrings,\n maxStrLength: this.maxStrLength,\n maxBinLength: this.maxBinLength,\n maxArrayLength: this.maxArrayLength,\n maxMapLength: this.maxMapLength,\n maxExtLength: this.maxExtLength,\n keyDecoder: this.keyDecoder,\n });\n }\n reinitializeState() {\n this.totalPos = 0;\n this.headByte = HEAD_BYTE_REQUIRED;\n this.stack.reset();\n // view, bytes, and pos will be re-initialized in setBuffer()\n }\n setBuffer(buffer) {\n const bytes = ensureUint8Array(buffer);\n this.bytes = bytes;\n this.view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n this.pos = 0;\n }\n appendBuffer(buffer) {\n if (this.headByte === HEAD_BYTE_REQUIRED && !this.hasRemaining(1)) {\n this.setBuffer(buffer);\n }\n else {\n const remainingData = this.bytes.subarray(this.pos);\n const newData = ensureUint8Array(buffer);\n // concat remainingData + newData\n const newBuffer = new Uint8Array(remainingData.length + newData.length);\n newBuffer.set(remainingData);\n newBuffer.set(newData, remainingData.length);\n this.setBuffer(newBuffer);\n }\n }\n hasRemaining(size) {\n return this.view.byteLength - this.pos >= size;\n }\n createExtraByteError(posToShow) {\n const { view, pos } = this;\n return new RangeError(`Extra ${view.byteLength - pos} of ${view.byteLength} byte(s) found at buffer[${posToShow}]`);\n }\n /**\n * @throws {@link DecodeError}\n * @throws {@link RangeError}\n */\n decode(buffer) {\n if (this.entered) {\n const instance = this.clone();\n return instance.decode(buffer);\n }\n try {\n this.entered = true;\n this.reinitializeState();\n this.setBuffer(buffer);\n const object = this.doDecodeSync();\n if (this.hasRemaining(1)) {\n throw this.createExtraByteError(this.pos);\n }\n return object;\n }\n finally {\n this.entered = false;\n }\n }\n *decodeMulti(buffer) {\n if (this.entered) {\n const instance = this.clone();\n yield* instance.decodeMulti(buffer);\n return;\n }\n try {\n this.entered = true;\n this.reinitializeState();\n this.setBuffer(buffer);\n while (this.hasRemaining(1)) {\n yield this.doDecodeSync();\n }\n }\n finally {\n this.entered = false;\n }\n }\n async decodeAsync(stream) {\n if (this.entered) {\n const instance = this.clone();\n return instance.decodeAsync(stream);\n }\n try {\n this.entered = true;\n let decoded = false;\n let object;\n for await (const buffer of stream) {\n if (decoded) {\n this.entered = false;\n throw this.createExtraByteError(this.totalPos);\n }\n this.appendBuffer(buffer);\n try {\n object = this.doDecodeSync();\n decoded = true;\n }\n catch (e) {\n if (!(e instanceof RangeError)) {\n throw e; // rethrow\n }\n // fallthrough\n }\n this.totalPos += this.pos;\n }\n if (decoded) {\n if (this.hasRemaining(1)) {\n throw this.createExtraByteError(this.totalPos);\n }\n return object;\n }\n const { headByte, pos, totalPos } = this;\n throw new RangeError(`Insufficient data in parsing ${prettyByte(headByte)} at ${totalPos} (${pos} in the current buffer)`);\n }\n finally {\n this.entered = false;\n }\n }\n decodeArrayStream(stream) {\n return this.decodeMultiAsync(stream, true);\n }\n decodeStream(stream) {\n return this.decodeMultiAsync(stream, false);\n }\n async *decodeMultiAsync(stream, isArray) {\n if (this.entered) {\n const instance = this.clone();\n yield* instance.decodeMultiAsync(stream, isArray);\n return;\n }\n try {\n this.entered = true;\n let isArrayHeaderRequired = isArray;\n let arrayItemsLeft = -1;\n for await (const buffer of stream) {\n if (isArray && arrayItemsLeft === 0) {\n throw this.createExtraByteError(this.totalPos);\n }\n this.appendBuffer(buffer);\n if (isArrayHeaderRequired) {\n arrayItemsLeft = this.readArraySize();\n isArrayHeaderRequired = false;\n this.complete();\n }\n try {\n while (true) {\n yield this.doDecodeSync();\n if (--arrayItemsLeft === 0) {\n break;\n }\n }\n }\n catch (e) {\n if (!(e instanceof RangeError)) {\n throw e; // rethrow\n }\n // fallthrough\n }\n this.totalPos += this.pos;\n }\n }\n finally {\n this.entered = false;\n }\n }\n doDecodeSync() {\n DECODE: while (true) {\n const headByte = this.readHeadByte();\n let object;\n if (headByte >= 0xe0) {\n // negative fixint (111x xxxx) 0xe0 - 0xff\n object = headByte - 0x100;\n }\n else if (headByte < 0xc0) {\n if (headByte < 0x80) {\n // positive fixint (0xxx xxxx) 0x00 - 0x7f\n object = headByte;\n }\n else if (headByte < 0x90) {\n // fixmap (1000 xxxx) 0x80 - 0x8f\n const size = headByte - 0x80;\n if (size !== 0) {\n this.pushMapState(size);\n this.complete();\n continue DECODE;\n }\n else {\n object = {};\n }\n }\n else if (headByte < 0xa0) {\n // fixarray (1001 xxxx) 0x90 - 0x9f\n const size = headByte - 0x90;\n if (size !== 0) {\n this.pushArrayState(size);\n this.complete();\n continue DECODE;\n }\n else {\n object = [];\n }\n }\n else {\n // fixstr (101x xxxx) 0xa0 - 0xbf\n const byteLength = headByte - 0xa0;\n object = this.decodeString(byteLength, 0);\n }\n }\n else if (headByte === 0xc0) {\n // nil\n object = null;\n }\n else if (headByte === 0xc2) {\n // false\n object = false;\n }\n else if (headByte === 0xc3) {\n // true\n object = true;\n }\n else if (headByte === 0xca) {\n // float 32\n object = this.readF32();\n }\n else if (headByte === 0xcb) {\n // float 64\n object = this.readF64();\n }\n else if (headByte === 0xcc) {\n // uint 8\n object = this.readU8();\n }\n else if (headByte === 0xcd) {\n // uint 16\n object = this.readU16();\n }\n else if (headByte === 0xce) {\n // uint 32\n object = this.readU32();\n }\n else if (headByte === 0xcf) {\n // uint 64\n if (this.useBigInt64) {\n object = this.readU64AsBigInt();\n }\n else {\n object = this.readU64();\n }\n }\n else if (headByte === 0xd0) {\n // int 8\n object = this.readI8();\n }\n else if (headByte === 0xd1) {\n // int 16\n object = this.readI16();\n }\n else if (headByte === 0xd2) {\n // int 32\n object = this.readI32();\n }\n else if (headByte === 0xd3) {\n // int 64\n if (this.useBigInt64) {\n object = this.readI64AsBigInt();\n }\n else {\n object = this.readI64();\n }\n }\n else if (headByte === 0xd9) {\n // str 8\n const byteLength = this.lookU8();\n object = this.decodeString(byteLength, 1);\n }\n else if (headByte === 0xda) {\n // str 16\n const byteLength = this.lookU16();\n object = this.decodeString(byteLength, 2);\n }\n else if (headByte === 0xdb) {\n // str 32\n const byteLength = this.lookU32();\n object = this.decodeString(byteLength, 4);\n }\n else if (headByte === 0xdc) {\n // array 16\n const size = this.readU16();\n if (size !== 0) {\n this.pushArrayState(size);\n this.complete();\n continue DECODE;\n }\n else {\n object = [];\n }\n }\n else if (headByte === 0xdd) {\n // array 32\n const size = this.readU32();\n if (size !== 0) {\n this.pushArrayState(size);\n this.complete();\n continue DECODE;\n }\n else {\n object = [];\n }\n }\n else if (headByte === 0xde) {\n // map 16\n const size = this.readU16();\n if (size !== 0) {\n this.pushMapState(size);\n this.complete();\n continue DECODE;\n }\n else {\n object = {};\n }\n }\n else if (headByte === 0xdf) {\n // map 32\n const size = this.readU32();\n if (size !== 0) {\n this.pushMapState(size);\n this.complete();\n continue DECODE;\n }\n else {\n object = {};\n }\n }\n else if (headByte === 0xc4) {\n // bin 8\n const size = this.lookU8();\n object = this.decodeBinary(size, 1);\n }\n else if (headByte === 0xc5) {\n // bin 16\n const size = this.lookU16();\n object = this.decodeBinary(size, 2);\n }\n else if (headByte === 0xc6) {\n // bin 32\n const size = this.lookU32();\n object = this.decodeBinary(size, 4);\n }\n else if (headByte === 0xd4) {\n // fixext 1\n object = this.decodeExtension(1, 0);\n }\n else if (headByte === 0xd5) {\n // fixext 2\n object = this.decodeExtension(2, 0);\n }\n else if (headByte === 0xd6) {\n // fixext 4\n object = this.decodeExtension(4, 0);\n }\n else if (headByte === 0xd7) {\n // fixext 8\n object = this.decodeExtension(8, 0);\n }\n else if (headByte === 0xd8) {\n // fixext 16\n object = this.decodeExtension(16, 0);\n }\n else if (headByte === 0xc7) {\n // ext 8\n const size = this.lookU8();\n object = this.decodeExtension(size, 1);\n }\n else if (headByte === 0xc8) {\n // ext 16\n const size = this.lookU16();\n object = this.decodeExtension(size, 2);\n }\n else if (headByte === 0xc9) {\n // ext 32\n const size = this.lookU32();\n object = this.decodeExtension(size, 4);\n }\n else {\n throw new DecodeError(`Unrecognized type byte: ${prettyByte(headByte)}`);\n }\n this.complete();\n const stack = this.stack;\n while (stack.length > 0) {\n // arrays and maps\n const state = stack.top();\n if (state.type === STATE_ARRAY) {\n state.array[state.position] = object;\n state.position++;\n if (state.position === state.size) {\n object = state.array;\n stack.release(state);\n }\n else {\n continue DECODE;\n }\n }\n else if (state.type === STATE_MAP_KEY) {\n if (object === \"__proto__\") {\n throw new DecodeError(\"The key __proto__ is not allowed\");\n }\n state.key = this.mapKeyConverter(object);\n state.type = STATE_MAP_VALUE;\n continue DECODE;\n }\n else {\n // it must be `state.type === State.MAP_VALUE` here\n state.map[state.key] = object;\n state.readCount++;\n if (state.readCount === state.size) {\n object = state.map;\n stack.release(state);\n }\n else {\n state.key = null;\n state.type = STATE_MAP_KEY;\n continue DECODE;\n }\n }\n }\n return object;\n }\n }\n readHeadByte() {\n if (this.headByte === HEAD_BYTE_REQUIRED) {\n this.headByte = this.readU8();\n // console.log(\"headByte\", prettyByte(this.headByte));\n }\n return this.headByte;\n }\n complete() {\n this.headByte = HEAD_BYTE_REQUIRED;\n }\n readArraySize() {\n const headByte = this.readHeadByte();\n switch (headByte) {\n case 0xdc:\n return this.readU16();\n case 0xdd:\n return this.readU32();\n default: {\n if (headByte < 0xa0) {\n return headByte - 0x90;\n }\n else {\n throw new DecodeError(`Unrecognized array type byte: ${prettyByte(headByte)}`);\n }\n }\n }\n }\n pushMapState(size) {\n if (size > this.maxMapLength) {\n throw new DecodeError(`Max length exceeded: map length (${size}) > maxMapLengthLength (${this.maxMapLength})`);\n }\n this.stack.pushMapState(size);\n }\n pushArrayState(size) {\n if (size > this.maxArrayLength) {\n throw new DecodeError(`Max length exceeded: array length (${size}) > maxArrayLength (${this.maxArrayLength})`);\n }\n this.stack.pushArrayState(size);\n }\n decodeString(byteLength, headerOffset) {\n if (!this.rawStrings || this.stateIsMapKey()) {\n return this.decodeUtf8String(byteLength, headerOffset);\n }\n return this.decodeBinary(byteLength, headerOffset);\n }\n /**\n * @throws {@link RangeError}\n */\n decodeUtf8String(byteLength, headerOffset) {\n if (byteLength > this.maxStrLength) {\n throw new DecodeError(`Max length exceeded: UTF-8 byte length (${byteLength}) > maxStrLength (${this.maxStrLength})`);\n }\n if (this.bytes.byteLength < this.pos + headerOffset + byteLength) {\n throw MORE_DATA;\n }\n const offset = this.pos + headerOffset;\n let object;\n if (this.stateIsMapKey() && this.keyDecoder?.canBeCached(byteLength)) {\n object = this.keyDecoder.decode(this.bytes, offset, byteLength);\n }\n else {\n object = utf8Decode(this.bytes, offset, byteLength);\n }\n this.pos += headerOffset + byteLength;\n return object;\n }\n stateIsMapKey() {\n if (this.stack.length > 0) {\n const state = this.stack.top();\n return state.type === STATE_MAP_KEY;\n }\n return false;\n }\n /**\n * @throws {@link RangeError}\n */\n decodeBinary(byteLength, headOffset) {\n if (byteLength > this.maxBinLength) {\n throw new DecodeError(`Max length exceeded: bin length (${byteLength}) > maxBinLength (${this.maxBinLength})`);\n }\n if (!this.hasRemaining(byteLength + headOffset)) {\n throw MORE_DATA;\n }\n const offset = this.pos + headOffset;\n const object = this.bytes.subarray(offset, offset + byteLength);\n this.pos += headOffset + byteLength;\n return object;\n }\n decodeExtension(size, headOffset) {\n if (size > this.maxExtLength) {\n throw new DecodeError(`Max length exceeded: ext length (${size}) > maxExtLength (${this.maxExtLength})`);\n }\n const extType = this.view.getInt8(this.pos + headOffset);\n const data = this.decodeBinary(size, headOffset + 1 /* extType */);\n return this.extensionCodec.decode(data, extType, this.context);\n }\n lookU8() {\n return this.view.getUint8(this.pos);\n }\n lookU16() {\n return this.view.getUint16(this.pos);\n }\n lookU32() {\n return this.view.getUint32(this.pos);\n }\n readU8() {\n const value = this.view.getUint8(this.pos);\n this.pos++;\n return value;\n }\n readI8() {\n const value = this.view.getInt8(this.pos);\n this.pos++;\n return value;\n }\n readU16() {\n const value = this.view.getUint16(this.pos);\n this.pos += 2;\n return value;\n }\n readI16() {\n const value = this.view.getInt16(this.pos);\n this.pos += 2;\n return value;\n }\n readU32() {\n const value = this.view.getUint32(this.pos);\n this.pos += 4;\n return value;\n }\n readI32() {\n const value = this.view.getInt32(this.pos);\n this.pos += 4;\n return value;\n }\n readU64() {\n const value = getUint64(this.view, this.pos);\n this.pos += 8;\n return value;\n }\n readI64() {\n const value = getInt64(this.view, this.pos);\n this.pos += 8;\n return value;\n }\n readU64AsBigInt() {\n const value = this.view.getBigUint64(this.pos);\n this.pos += 8;\n return value;\n }\n readI64AsBigInt() {\n const value = this.view.getBigInt64(this.pos);\n this.pos += 8;\n return value;\n }\n readF32() {\n const value = this.view.getFloat32(this.pos);\n this.pos += 4;\n return value;\n }\n readF64() {\n const value = this.view.getFloat64(this.pos);\n this.pos += 8;\n return value;\n }\n}\n//# sourceMappingURL=Decoder.mjs.map","import { Decoder } from \"./Decoder.mjs\";\n/**\n * It decodes a single MessagePack object in a buffer.\n *\n * This is a synchronous decoding function.\n * See other variants for asynchronous decoding: {@link decodeAsync}, {@link decodeMultiStream}, or {@link decodeArrayStream}.\n *\n * @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty.\n * @throws {@link DecodeError} if the buffer contains invalid data.\n */\nexport function decode(buffer, options) {\n const decoder = new Decoder(options);\n return decoder.decode(buffer);\n}\n/**\n * It decodes multiple MessagePack objects in a buffer.\n * This is corresponding to {@link decodeMultiStream}.\n *\n * @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty.\n * @throws {@link DecodeError} if the buffer contains invalid data.\n */\nexport function decodeMulti(buffer, options) {\n const decoder = new Decoder(options);\n return decoder.decodeMulti(buffer);\n}\n//# sourceMappingURL=decode.mjs.map","import { encode as mpEncode, decode as mpDecode } from '@msgpack/msgpack'\nimport type { ClientFrame, ServerFrame } from './frames.js'\n\nexport type AnyFrame = ClientFrame | ServerFrame\n\nconst CLIENT_FRAME_TYPES: ReadonlySet<ClientFrame['type']> = new Set([\n 'auth', 'open', 'send', 'sync', 'history', 'read', 'typing', 'react', 'edit', 'delete', 'invoke', 'pubkey', 'ping', 'annotate', 'annotate_clear',\n 'uploadPrekeys', 'fetchPrekey', 'assign', 'tag', 'note', 'agent_status', 'subscribe_inbox', 'unsubscribe_inbox',\n])\n\n/** True if a decoded frame is one a client is allowed to send. The server uses\n * this to reject server-only frame types before dispatch, so a malicious or\n * buggy client can't reach an unexpected handler path. */\nexport function isClientFrame(frame: AnyFrame): frame is ClientFrame {\n return CLIENT_FRAME_TYPES.has(frame.type as ClientFrame['type'])\n}\n\n/** Encode a frame to a binary msgpack payload for the wire. */\nexport function encodeFrame(frame: AnyFrame): Uint8Array {\n return mpEncode(frame)\n}\n\n/** Decode a binary payload into a frame. Returns null on any malformed input or\n * anything lacking a string `type`, so a bad frame can never crash the handler\n * — the boundary validates `type` before trusting the rest. */\nexport function decodeFrame(bytes: Uint8Array): AnyFrame | null {\n let value: unknown\n try {\n value = mpDecode(bytes)\n } catch {\n return null\n }\n if (typeof value !== 'object' || value === null) return null\n if (typeof (value as { type?: unknown }).type !== 'string') return null\n return value as AnyFrame\n}\n"],"names":["resolveRelayUrls","input","apiBaseOverride","_a","trimmed","scheme","secure","authorityAndPath","httpBase","httpBaseFromWsUrl","wsUrl","historyUrl","conversationId","beforeSeq","limit","qs","fetchPage","token","url","res","data","restoreHistory","store","renderer","apiBase","page","loading","loadOlder","oldest","page2","scrollEl","armed","onScroll","KEY","readCookie","name","m","writeCookie","value","newId","persistentUid","existing","id","utf8Count","str","strLength","byteLength","pos","extra","utf8EncodeJs","output","outputOffset","offset","sharedTextEncoder","TEXT_ENCODER_THRESHOLD","utf8EncodeTE","utf8Encode","CHUNK_SIZE","utf8DecodeJs","bytes","inputOffset","end","units","result","byte1","byte2","byte3","byte4","unit","sharedTextDecoder","TEXT_DECODER_THRESHOLD","utf8DecodeTD","stringBytes","utf8Decode","ExtData","type","__publicField","DecodeError","message","proto","UINT32_MAX","setUint64","view","high","low","setInt64","getInt64","getUint64","EXT_TIMESTAMP","TIMESTAMP32_MAX_SEC","TIMESTAMP64_MAX_SEC","encodeTimeSpecToTimestamp","sec","nsec","rv","secHigh","secLow","encodeDateToTimeSpec","date","msec","nsecInSec","encodeTimestampExtension","object","timeSpec","decodeTimestampToTimeSpec","nsec30AndSecHigh2","secLow32","decodeTimestampExtension","timestampExtension","_ExtensionCodec","encode","decode","index","context","i","encodeExt","decodeExt","ExtensionCodec","isArrayBufferLike","buffer","ensureUint8Array","DEFAULT_MAX_DEPTH","DEFAULT_INITIAL_BUFFER_SIZE","Encoder","options","depth","sizeToWrite","requiredSize","newSize","newBuffer","newBytes","newView","ext","size","item","keys","count","key","values","prettyByte","byte","DEFAULT_MAX_KEY_LENGTH","DEFAULT_MAX_LENGTH_PER_KEY","CachedKeyDecoder","maxKeyLength","maxLengthPerKey","records","FIND_CHUNK","record","recordBytes","j","cachedValue","slicedCopyOfBytes","STATE_ARRAY","STATE_MAP_KEY","STATE_MAP_VALUE","mapKeyConverter","StackPool","state","partialState","HEAD_BYTE_REQUIRED","EMPTY_VIEW","EMPTY_BYTES","e","MORE_DATA","sharedCachedKeyDecoder","Decoder","remainingData","newData","posToShow","stream","decoded","headByte","totalPos","isArray","isArrayHeaderRequired","arrayItemsLeft","DECODE","stack","headerOffset","headOffset","extType","CLIENT_FRAME_TYPES","isClientFrame","frame","encodeFrame","mpEncode","decodeFrame","mpDecode"],"mappings":"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","x_google_ignoreList":[2,3,4,5,6,7,8,9,10,11,12,13,14]}
|
package/dist/core.js
CHANGED
|
@@ -2,10 +2,10 @@ var c = Object.defineProperty;
|
|
|
2
2
|
var d = (t, e, s) => e in t ? c(t, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : t[e] = s;
|
|
3
3
|
var n = (t, e, s) => d(t, typeof e != "symbol" ? e + "" : e, s);
|
|
4
4
|
import { a as o, C as u, b as h } from "./outbox.js";
|
|
5
|
-
import { A as C, P as
|
|
6
|
-
import { E2ESession as
|
|
7
|
-
import { p as l, r as m } from "./
|
|
8
|
-
import { h as P, a as X } from "./
|
|
5
|
+
import { A as C, P as A, c as k, d as E, e as U, f as j, g as x, h as R, i as w } from "./outbox.js";
|
|
6
|
+
import { E2ESession as L } from "./e2e.js";
|
|
7
|
+
import { p as l, r as m } from "./codec.js";
|
|
8
|
+
import { d as O, e as q, h as H, i as P, a as X } from "./codec.js";
|
|
9
9
|
import { mountChatList as D } from "./chatlist.js";
|
|
10
10
|
const I = /* @__PURE__ */ new Set([
|
|
11
11
|
"resolved",
|
|
@@ -119,24 +119,24 @@ export {
|
|
|
119
119
|
C as ANONYMOUS_TENANT,
|
|
120
120
|
u as ChatStore,
|
|
121
121
|
h as ConnectionManager,
|
|
122
|
-
|
|
122
|
+
L as E2ESession,
|
|
123
123
|
v as LIMITS,
|
|
124
|
-
|
|
124
|
+
A as PersistentOutbox,
|
|
125
125
|
b as RelayClient,
|
|
126
126
|
f as RelayConversation,
|
|
127
127
|
I as TERMINAL_STATES,
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
128
|
+
k as asActionId,
|
|
129
|
+
E as asConnectionId,
|
|
130
|
+
U as asConversationId,
|
|
131
|
+
j as asMessageId,
|
|
132
132
|
x as asProfileId,
|
|
133
133
|
R as asSubjectId,
|
|
134
134
|
w as asTenantId,
|
|
135
135
|
o as asUserId,
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
136
|
+
O as decodeFrame,
|
|
137
|
+
q as encodeFrame,
|
|
138
|
+
H as httpBaseFromWsUrl,
|
|
139
|
+
P as isClientFrame,
|
|
140
140
|
_ as isTerminalState,
|
|
141
141
|
D as mountChatList,
|
|
142
142
|
l as persistentUid,
|
package/dist/core.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.js","sources":["../src/protocol/entities.ts","../src/protocol/actions.ts","../src/protocol/frames.ts","../src/core.ts"],"sourcesContent":["import type {\n ConversationId, MessageId, ProfileId, SubjectId, TenantId, UserId,\n} from './ids.js'\nimport type { ActionId } from './ids.js'\n\n// ── Message content (discriminated union) ─────────────────────────────────────\n// The runtime stays generic by never hard-coding business content: a message is\n// one of a small, fixed set of shapes. `card`/`form`/`system` are how action\n// results and structured prompts render — they subsume most \"rich messaging\"\n// features without a per-feature content zoo.\n\nexport interface CardField { label: string; value: string }\n\n/** A reference to an action a card/quick-reply can invoke. */\nexport interface InlineActionRef { actionId: ActionId; label: string }\n\nexport type MessageContent =\n | { kind: 'text'; text: string; enc?: boolean; iv?: string }\n | { kind: 'attachment'; url: string; mime: string; name?: string; size?: number }\n | { kind: 'card'; title?: string; body?: string; fields?: CardField[]; actions?: InlineActionRef[] }\n | { kind: 'form'; prompt: string; actionId: ActionId }\n | { kind: 'system'; event: string; data?: Record<string, string | number | boolean> }\n | { kind: 'appointment'; title: string; startIso: string; endIso: string; location?: string; description?: string; googleUrl: string; icalUrl: string; confirmed?: boolean }\n\nexport type SenderRole = 'guest' | 'agent' | 'system' | 'bot'\n\n// ── Message ───────────────────────────────────────────────────────────────────\n// Ordering is by `seq` (server-assigned, monotonic per conversation), never by\n// `ts`. `ts` is wall-clock for display only. This kills the reorder/duplicate/\n// lost-on-reconnect class of bugs that millisecond-timestamp ordering caused.\n\nexport interface Message {\n id: MessageId\n conversationId: ConversationId\n seq: number\n senderId: UserId\n senderRole: SenderRole\n content: MessageContent\n ts: number\n replyToId?: MessageId\n editedAt?: number\n deletedAt?: number\n reactions?: Record<string, UserId[]>\n internal?: boolean // true = internal note, only visible to agents\n}\n\n// ── Conversation (the room; messages partition by conversationId) ─────────────\n// The room is the conversation, NOT the subject. Two guests discussing the same\n// subject get two conversations. `subjectId` is a nullable reference, never part\n// of the room identity — so \"one thread per (guest, subject)\" is enforced as\n// app logic at open-time, and many-threads-per-subject stays possible for free.\n\nexport interface Conversation {\n id: ConversationId\n tenantId: TenantId\n profileId: ProfileId // behavior profile → which actions this room has\n subjectId?: SubjectId // optional: the thing it's about\n guestId: UserId // the end-user\n /** Host-supplied display info for an identified guest (widget `user` option).\n * Display metadata only — identity is still the token/guestId. */\n guestName?: string\n guestEmail?: string\n guestAvatar?: string\n guestMeta?: Record<string, string>\n /** True once the guest's identity has been proven by a signed ES256 JWT\n * against the chatroom's guestPublicKey (secure identity mode). */\n guestVerified?: boolean\n participants: UserId[] // guest + any assigned agents (membership = authz)\n assignedAgentId?: UserId // routing/ownership\n aiActive?: boolean // staff assigned the AI to answer this room\n state: string // conversation state-machine state\n firstResponseAt?: number // first agent reply ts (SLA)\n csat?: number // satisfaction score 1–5 (set on resolution)\n lastSeq: number // highest seq assigned in this conversation\n tags?: string[] // macro/manual tags (e.g. \"refund\", \"vip\")\n /** Live sentiment of the guest's most recent message (best-effort, async). */\n sentiment?: 'positive' | 'neutral' | 'frustrated'\n /** -1 (very frustrated) .. +1 (very positive); paired with `sentiment`. */\n sentimentScore?: number\n /** Set once an SLA-breach escalation macro has fired, so it only fires once. */\n slaEscalatedAt?: number\n /** If set, the conversation is snoozed until this Unix ms timestamp.\n * Hidden from the inbox until the timestamp passes, then resurfaces. */\n snoozedUntil?: number\n /** Page URL where the widget was open when the conversation started. */\n pageUrl?: string\n /** Browser tab title at conversation start — gives agents context. */\n pageTitle?: string\n createdAt: number\n updatedAt: number\n}\n\n// ── Co-browsing / shared annotation ────────────────────────────────────────---\n// A lightweight shared whiteboard layered over a conversation: agent and guest\n// can draw freehand strokes that both sides see live. Strokes are relayed\n// (not stored as messages) and kept per-conversation so late joiners can catch\n// up via the `opened` frame's `annotations` field.\n\nexport interface AnnotationPoint { x: number; y: number }\nexport interface AnnotationStroke {\n id: string\n points: AnnotationPoint[]\n color: string\n width: number\n by: UserId\n}\n\n// ── Subject (the referenced entity — Intercom \"custom object\") ────────────────\n// Carries shared state (available → reserved → sold) and fields (price, vin…)\n// that actions read/write. Many conversations reference one subject. Never a room.\n\nexport interface Subject {\n id: SubjectId\n tenantId: TenantId\n title: string\n state: string\n fields: Record<string, string | number | boolean>\n /** URL of the page where the subject lives (e.g. the listing page URL).\n * Captured automatically by the widget and stored on first open. */\n url?: string\n createdAt: number\n updatedAt: number\n}\n\n// ── Conversation lifecycle ────────────────────────────────────────────────────\n/** States in which a conversation is no longer \"open\": it's done with, so inbox\n * / proactive sweeps skip it and load balancing frees the assigned agent. The\n * single source of truth for \"is this conversation finished?\". */\nexport const TERMINAL_STATES: ReadonlySet<string> = new Set([\n 'resolved', 'closed', 'sold', 'issued', 'checked_out',\n])\nexport function isTerminalState(state: string): boolean {\n return TERMINAL_STATES.has(state)\n}\n\nexport type Channel = 'widget' | 'email' | 'sms' | 'whatsapp' | 'instagram' | 'kakao' | 'messenger' | 'line'\n","import type { ActionId, ProfileId, TenantId } from './ids.js'\n\n// ── Actions: the product primitive ────────────────────────────────────────────\n// An action is data an admin authors in the dashboard; the runtime stays generic\n// and only knows how to execute a small, fixed set of EFFECTS. Adding \"make\n// offer\" or \"schedule meeting\" is a config row, not a code deploy.\n\nexport type ActionAudience = 'guest' | 'agent' | 'both'\nexport type ActionSurface = 'toolbar' | 'inline' | 'quick_reply'\n\nexport interface ActionInputField {\n name: string\n label: string\n type: 'text' | 'number' | 'date' | 'select'\n required?: boolean\n options?: string[] // for type: 'select'\n}\n\n// A terminal effect produces a result and ends the action. Actions are\n// single-shot: structured multi-step lives in the conversation state machine,\n// and conversational multi-step is the `bot` effect — not an action workflow.\nexport type TerminalEffect =\n | { type: 'webhook'; url: string } // signed POST to tenant system\n | { type: 'state_transition'; target: 'conversation' | 'subject'; toState: string }\n | { type: 'bot' } // route to the AI resolver\n | { type: 'builtin'; name: string } // e.g. 'handoff'\n\n// The ONLY composition allowed is \"collect a form, then run one terminal\n// effect\" — exactly one level deep. This covers input-gathering (e.g. an offer\n// amount) without becoming a workflow engine.\nexport type ActionEffect =\n | TerminalEffect\n | { type: 'form'; fields: ActionInputField[]; then: TerminalEffect }\n\nexport type ActionResult =\n | { kind: 'system_message'; template?: string } // post a system line into the chat\n | { kind: 'card' } // render the effect's response as a card\n | { kind: 'state_badge' } // reflect a state change\n | { kind: 'none' }\n\nexport interface ActionDef {\n id: ActionId\n label: string\n icon?: string\n confirm?: boolean\n audience: ActionAudience\n surface: ActionSurface\n availableInStates?: string[] // conversation/subject states; omit = always available\n effect: ActionEffect\n result: ActionResult\n}\n\n// Client-safe projection of an action: enough for the widget to render it and\n// collect inputs, but NONE of the effect internals (webhook URLs, transition\n// targets) — those stay server-side and execute on `invoke`. The client filters\n// by `availableInStates` locally against the current conversation state, so a\n// state change needs no manifest round-trip; the server re-validates on invoke.\nexport interface ManifestAction {\n id: ActionId\n label: string\n icon?: string\n confirm?: boolean\n audience: ActionAudience\n surface: ActionSurface\n availableInStates?: string[]\n input?: ActionInputField[] // present when the action collects input (form effect)\n}\n\n/** Project an internal action to its client-safe manifest form. */\nexport function toManifestAction(a: ActionDef): ManifestAction {\n const input = a.effect.type === 'form' ? a.effect.fields : undefined\n return {\n id: a.id, label: a.label, audience: a.audience, surface: a.surface,\n ...(a.icon ? { icon: a.icon } : {}),\n ...(a.confirm ? { confirm: a.confirm } : {}),\n ...(a.availableInStates ? { availableInStates: a.availableInStates } : {}),\n ...(input ? { input } : {}),\n }\n}\n\n// ── Behavior profile (what \"domain\" becomes) ──────────────────────────────────\n// A reusable, admin-composed bundle of actions + defaults + state machine. Not a\n// built-in taxonomy — the 7 old templates become starter presets of this shape.\n// `version` lets an in-flight invocation validate against a consistent snapshot.\n\n/** Operating hours slot: 0=Sun … 6=Sat, times in \"HH:MM\" 24h local. */\nexport interface OperatingHoursSlot { day: 0|1|2|3|4|5|6; open: string; close: string }\n\nexport interface BehaviorProfile {\n id: ProfileId\n tenantId: TenantId\n name: string\n actions: ActionDef[]\n defaults: {\n greeting?: string\n theme?: { accent: string }\n e2e?: boolean\n persona?: string\n /** Paid-tier flag: when true, hides the \"Powered by Relay\" footer in the widget. */\n whiteLabel?: boolean\n /** White-label: serve/embed the widget from this hostname (e.g.\n * \"chat.acmeco.com\"). Allowed automatically as a CORS origin for the\n * control-plane API so the widget works from the custom domain. */\n customDomain?: string\n }\n states: string[]\n initialState: string\n version: number\n welcomeMessage?: string // first message guests see when opening the widget\n operatingHours?: OperatingHoursSlot[] // empty/absent = always open\n offlineMessage?: string // shown outside operating hours instead of chat\n /** Base64-encoded ECDSA P-256 SPKI public key. When set, guest tokens must be\n * signed JWTs — unsigned opaque tokens are rejected. */\n guestPublicKey?: string\n createdAt: number\n updatedAt: number\n}\n","import type {\n ConnectionId, ConversationId, MessageId, ProfileId, SubjectId, UserId,\n} from './ids.js'\nimport type { Channel, Conversation, Message, MessageContent, Subject, AnnotationStroke } from './entities.js'\nimport type { ManifestAction } from './actions.js'\n\n/** Dashboard-configured pre-chat qualification form, delivered in the manifest. */\nexport interface PreChatConfig {\n enabled: boolean\n showWhen?: 'always' | 'offline'\n fields?: ('name' | 'email' | 'phone')[]\n topics?: string[]\n callbackOption?: boolean\n title?: string\n}\n\n// ── Wire protocol ─────────────────────────────────────────────────────────────\n// One shared contract, imported by server + widget + dashboard. A change here is\n// a compile error in every consumer — which is the whole reason this lives in a\n// shared package instead of being hand-copied three times.\n\nexport type ErrorCode =\n | 'UNAUTHORIZED' | 'FORBIDDEN' | 'NOT_FOUND' | 'BAD_REQUEST'\n | 'RATE_LIMITED' | 'PAYLOAD_TOO_LARGE' | 'CONFLICT' | 'INTERNAL'\n\nexport type ClientFrame =\n | { type: 'auth'; token: string }\n // Open an existing conversation, or find-or-create one. Find-or-create keys on\n // (guest, subject) when subjectId is given; otherwise a fresh conversation.\n | { type: 'open'; conversationId?: ConversationId; subjectId?: SubjectId; profileId?: ProfileId; pageUrl?: string; pageTitle?: string; subjectTitle?: string; subjectMeta?: string; linkFrom?: UserId;\n /** Host-supplied display info for the guest — persisted onto the\n * conversation server-side so agents see who they're talking to.\n * Display metadata only, never used for authorization. */\n userInfo?: { name?: string; email?: string; avatar?: string; meta?: Record<string, string> } }\n | { type: 'send'; conversationId: ConversationId; clientMsgId: string; content: MessageContent; replyToId?: MessageId; via?: Channel[] }\n | { type: 'sync'; conversationId: ConversationId; sinceSeq: number } // catch-up after cursor\n | { type: 'history'; conversationId: ConversationId; beforeSeq: number; limit?: number } // load older\n | { type: 'read'; conversationId: ConversationId; seq: number } // read up to seq\n | { type: 'typing'; conversationId: ConversationId; isTyping: boolean; preview?: string }\n | { type: 'react'; conversationId: ConversationId; messageId: MessageId; emoji: string; remove?: boolean }\n | { type: 'edit'; conversationId: ConversationId; messageId: MessageId; content: MessageContent }\n | { type: 'delete'; conversationId: ConversationId; messageId: MessageId }\n | { type: 'invoke'; conversationId: ConversationId; actionId: string; clientInvokeId: string; inputs?: Record<string, unknown> }\n | { type: 'assign'; conversationId: ConversationId; agentId: UserId | null } // null = unassign\n | { type: 'tag'; conversationId: ConversationId; tag: string; remove?: boolean }\n | { type: 'note'; conversationId: ConversationId; clientMsgId: string; text: string } // internal note\n | { type: 'agent_status'; status: 'online' | 'away' | 'offline' } // agent sets their availability\n // Co-browsing: a freehand stroke (or \"clear\") on the shared annotation canvas\n // for a subject-anchored conversation. Relayed live to the other participant.\n | { type: 'annotate'; conversationId: ConversationId; stroke: Omit<AnnotationStroke, 'by'> }\n | { type: 'annotate_clear'; conversationId: ConversationId }\n | { type: 'pubkey'; conversationId: ConversationId; key: string }\n // X3DH async E2E: a client uploads a batch of one-time prekeys so peers can\n // encrypt to them while they are offline. The server stores them opaquely and\n // vends one on demand — it never derives or uses the keys.\n | { type: 'uploadPrekeys'; identityKey: string; signedPrekey: string; signedPrekeyId: string; signature: string; oneTimePrekeys: string[] }\n | { type: 'fetchPrekey'; targetUserId: UserId }\n // Inbox stream subscription — used by the agent dashboard, which reuses this\n // ConnectionManager. Typed here so the dashboard doesn't need `as never`.\n | { type: 'subscribe_inbox' }\n | { type: 'unsubscribe_inbox' }\n | { type: 'ping' }\n\nexport type ServerFrame =\n | { type: 'authed'; userId: UserId; connectionId: ConnectionId }\n | { type: 'opened'; conversation: Conversation; subject?: Subject; annotations?: AnnotationStroke[] }\n | { type: 'manifest'; conversationId: ConversationId; actions: ManifestAction[]; version: number; name?: string; theme?: { accent: string }; e2e?: boolean; offline?: boolean; offlineMessage?: string; whiteLabel?: boolean; preChat?: PreChatConfig }\n | { type: 'message'; message: Message }\n | { type: 'ack'; clientMsgId: string; messageId: MessageId; seq: number; ts: number }\n | { type: 'delivered'; conversationId: ConversationId; seq: number; to: UserId }\n | { type: 'read'; conversationId: ConversationId; seq: number; by: UserId }\n | { type: 'sync'; conversationId: ConversationId; messages: Message[] }\n | { type: 'history'; conversationId: ConversationId; messages: Message[]; hasMore: boolean }\n | { type: 'typing'; conversationId: ConversationId; userId: UserId; isTyping: boolean; preview?: string }\n | { type: 'reaction'; conversationId: ConversationId; messageId: MessageId; emoji: string; by: UserId; removed: boolean }\n | { type: 'edited'; conversationId: ConversationId; messageId: MessageId; content: MessageContent; editedAt: number }\n | { type: 'deleted'; conversationId: ConversationId; messageId: MessageId; ts: number }\n | { type: 'state'; conversationId: ConversationId; state: string }\n | { type: 'assigned'; conversationId: ConversationId; agentId: UserId | null }\n | { type: 'tagged'; conversationId: ConversationId; tag: string; removed: boolean }\n | { type: 'visitor_count'; count: number } // broadcast to agents: guests currently connected\n | { type: 'agent_status_changed'; agentId: UserId; status: 'online' | 'away' | 'offline' }\n // Live sentiment of a guest's most recent message — relayed to agents only so\n // the inbox can flag frustrated conversations as they happen.\n | { type: 'sentiment'; conversationId: ConversationId; label: 'positive' | 'neutral' | 'frustrated'; score: number }\n // Co-browsing: relay of an annotation stroke / clear to everyone in the room.\n | { type: 'annotation'; conversationId: ConversationId; stroke: AnnotationStroke }\n | { type: 'annotation_clear'; conversationId: ConversationId; by: UserId }\n | { type: 'subjectState'; subjectId: SubjectId; state: string }\n | { type: 'presence'; conversationId: ConversationId; userId: UserId; status: 'online' | 'offline'; lastSeen?: number }\n | { type: 'invoked'; clientInvokeId: string; ok: boolean; error?: string }\n | { type: 'error'; code: ErrorCode; message: string }\n | { type: 'peerkey'; conversationId: ConversationId; userId: UserId; key: string }\n // X3DH bundle vended to a requesting client so they can encrypt to an offline peer.\n // Contains null when the target user has no registered prekeys.\n | { type: 'prekeyBundle'; targetUserId: UserId; bundle: { identityKey: string; signedPrekey: string; signedPrekeyId: string; signature: string; oneTimePrekey?: string } | null }\n | { type: 'pong' }\n\n/** Limits referenced by both ends so validation stays consistent. */\nexport const LIMITS = {\n MAX_TEXT_LEN: 8_000,\n MAX_HISTORY_LIMIT: 100,\n DEFAULT_HISTORY: 50,\n} as const\n","// ── @paramms/chat-widget/core — the headless SDK ─────────────────────────────\n// Everything you need to build your OWN chat UI (an in-app messenger, a\n// marketplace inbox, a full chat app) on the Relay protocol, with zero DOM or\n// React dependencies. This is not a new client: it is the exact transport,\n// store, outbox, and E2E machinery the bundled widget AND the agent dashboard\n// run on — re-exported behind a stable boundary, plus a small convenience\n// client for the common case.\n//\n// import { RelayClient } from '@paramms/chat-widget/core'\n//\n// // ONE url, any scheme — wss/ws/http(s) all work; ws + REST derived from it.\n// const relay = new RelayClient({ url: 'https://api.relay.paramms.com', token, profileId: 'p_x' })\n// const convo = relay.open({ subjectId: 'listing_42' }) // support thread\n// const dm = relay.open({ kind: 'direct', peerId: 'user_bob' }) // user↔user (signed identity required)\n// convo.onChange(() => render(convo.store.messages()))\n// convo.send('hello!')\n//\n// For React, see '@paramms/chat-widget/hooks'.\nexport { ConnectionManager, type SocketLike } from './connection.js'\nexport { ChatStore } from './store.js'\nexport { PersistentOutbox } from './outbox.js'\nexport { E2ESession } from './e2e.js'\nexport { restoreHistory, resolveRelayUrls, httpBaseFromWsUrl } from './history.js'\nexport { mountChatList, type ChatListEntry, type ChatListHandle, type ChatListOptions } from './chatlist.js'\nexport { persistentUid } from './uid.js'\nexport * from './protocol/index.js'\n\nimport { ConnectionManager } from './connection.js'\nimport { ChatStore } from './store.js'\nimport type { ClientFrame, ServerFrame, ConversationId, UserId } from './protocol/index.js'\nimport { asUserId } from './protocol/index.js'\nimport { persistentUid } from './uid.js'\nimport { resolveRelayUrls } from './history.js'\n\nexport interface RelayClientOptions {\n /** Relay URL — ONE url, any scheme. `https://api.relay.paramms.com` is the\n * recommended form; the WebSocket URL (`wss://…/ws`) and REST base are\n * derived from it automatically. `wss://`/`ws://`/`http://` also accepted. */\n url: string\n /** HTTP(S) base for REST calls — only when the REST API lives on a\n * DIFFERENT origin than the socket. Normally omit.\n * @deprecated pass a single `url`; kept for back-compat. */\n apiUrl?: string\n /** Identity: a signed JWT (secure), a stable userId (host-vouched), or omit\n * for an anonymous per-browser guest (browser environments only). */\n token?: string\n /** Chatroom id (from the dashboard). Required to open conversations. */\n profileId: string\n}\n\nexport interface OpenOptions {\n /** Support thread scoped to a subject (listing/order/…): one thread per\n * (user, subject). Omit for the profile's single support thread. */\n subjectId?: string\n subjectTitle?: string\n /** User↔user conversation (requires the chatroom to have signed identity\n * and `token` to be a valid signed JWT). */\n kind?: 'direct'\n peerId?: string\n /** Display info persisted for agents (support threads only). */\n user?: { name?: string; email?: string; avatar?: string; meta?: Record<string, string> }\n}\n\n/** One conversation = one connection + one store. Deliberately thin: the\n * store is the source of truth, `onChange` is the render signal, everything\n * else is the same primitives the first-party UIs use. */\nexport class RelayConversation {\n readonly store: ChatStore\n private readonly conn: ConnectionManager\n private readonly listeners = new Set<() => void>()\n private msgSeq = 0\n private _status = 'connecting'\n private _statusMessage: string | undefined\n\n constructor(opts: RelayClientOptions & OpenOptions & { me: UserId }) {\n this.store = new ChatStore(opts.me)\n const open: Extract<ClientFrame, { type: 'open' }> = {\n type: 'open',\n profileId: opts.profileId as never,\n ...(opts.subjectId ? { subjectId: opts.subjectId as never } : {}),\n ...(opts.subjectTitle ? { subjectTitle: opts.subjectTitle } : {}),\n ...(opts.kind === 'direct' ? { kind: 'direct' as const, peerId: asUserId(opts.peerId ?? '') } : {}),\n ...(opts.user ? { userInfo: opts.user } : {}),\n }\n // Accept any scheme (https/http/wss/ws) — a plain `https://api.…` URL is\n // resolved to the concrete `wss://…/ws` socket endpoint, exactly like the\n // bundled widget's mount(). Before this, RelayClient required a raw\n // WebSocket URL while the React components took `https://` — one URL now\n // works across the entire SDK.\n const { wsUrl } = resolveRelayUrls(opts.url, opts.apiUrl)\n this.conn = new ConnectionManager({\n url: wsUrl,\n token: opts.token ?? opts.me,\n open,\n getCursor: () => this.store.highestSeq(),\n onFrame: (f: ServerFrame) => {\n // The server tells us our CANONICAL id on auth (a signed JWT's sub,\n // not the raw token) — capture it so `mine` checks work under every\n // identity tier.\n if (f.type === 'authed') this._me = f.userId as UserId\n this.store.apply(f); this.emit()\n },\n onStatusChange: (s, msg) => { this._status = s; this._statusMessage = msg; this.emit() },\n })\n this.conn.connect()\n }\n\n /** Subscribe to any change (message, typing, status). Returns unsubscribe. */\n onChange(fn: () => void): () => void {\n this.listeners.add(fn)\n return () => this.listeners.delete(fn)\n }\n private emit(): void { for (const fn of this.listeners) fn() }\n\n private _me: UserId | undefined\n /** Our canonical user id as resolved by the server (JWT sub / userId / anon id). */\n get me(): UserId | undefined { return this._me }\n get conversationId(): ConversationId | undefined { return this.store.conversationId }\n get status(): string { return this._status }\n get statusMessage(): string | undefined { return this._statusMessage }\n\n send(text: string): void {\n const clientMsgId = `c_${Date.now().toString(36)}_${++this.msgSeq}`\n const cid = this.store.conversationId\n if (!cid) return\n this.store.addOptimistic(clientMsgId, { kind: 'text', text })\n this.conn.send({ type: 'send', conversationId: cid, clientMsgId, content: { kind: 'text', text } })\n this.emit()\n }\n\n typing(isTyping: boolean, preview?: string): void {\n const cid = this.store.conversationId\n if (!cid) return\n this.conn.send({ type: 'typing', conversationId: cid, isTyping, ...(preview ? { preview } : {}) })\n }\n\n markRead(): void {\n const cid = this.store.conversationId\n if (!cid) return\n this.conn.send({ type: 'read', conversationId: cid, seq: this.store.highestSeq() })\n }\n\n close(): void { this.conn.close(); this.listeners.clear() }\n}\n\nexport class RelayClient {\n constructor(private readonly opts: RelayClientOptions) {}\n\n /** The identity this client will act as: the token's subject (resolved\n * server-side), the raw userId, or a persistent anonymous browser id. */\n me(): UserId {\n return asUserId(this.opts.token ?? persistentUid())\n }\n\n open(open: OpenOptions = {}): RelayConversation {\n return new RelayConversation({ ...this.opts, ...open, me: this.me() })\n }\n}\n"],"names":["TERMINAL_STATES","isTerminalState","state","toManifestAction","a","input","LIMITS","RelayConversation","opts","__publicField","ChatStore","open","asUserId","wsUrl","resolveRelayUrls","ConnectionManager","f","s","msg","fn","text","clientMsgId","cid","isTyping","preview","RelayClient","persistentUid"],"mappings":";;;;;;;;;AAgIO,MAAMA,wBAA2C,IAAI;AAAA,EAC1D;AAAA,EAAY;AAAA,EAAU;AAAA,EAAQ;AAAA,EAAU;AAC1C,CAAC;AACM,SAASC,EAAgBC,GAAwB;AACtD,SAAOF,EAAgB,IAAIE,CAAK;AAClC;AChEO,SAASC,EAAiBC,GAA8B;AAC7D,QAAMC,IAAQD,EAAE,OAAO,SAAS,SAASA,EAAE,OAAO,SAAS;AAC3D,SAAO;AAAA,IACL,IAAIA,EAAE;AAAA,IAAI,OAAOA,EAAE;AAAA,IAAO,UAAUA,EAAE;AAAA,IAAU,SAASA,EAAE;AAAA,IAC3D,GAAIA,EAAE,OAAO,EAAE,MAAMA,EAAE,KAAA,IAAS,CAAA;AAAA,IAChC,GAAIA,EAAE,UAAU,EAAE,SAASA,EAAE,QAAA,IAAY,CAAA;AAAA,IACzC,GAAIA,EAAE,oBAAoB,EAAE,mBAAmBA,EAAE,kBAAA,IAAsB,CAAA;AAAA,IACvE,GAAIC,IAAQ,EAAE,OAAAA,MAAU,CAAA;AAAA,EAAC;AAE7B;ACqBO,MAAMC,IAAS;AAAA,EACpB,cAAoB;AAAA,EACpB,mBAAoB;AAAA,EACpB,iBAAoB;AACtB;ACrCO,MAAMC,EAAkB;AAAA,EAQ7B,YAAYC,GAAyD;AAP5D,IAAAC,EAAA;AACQ,IAAAA,EAAA;AACA,IAAAA,EAAA,uCAAgB,IAAA;AACzB,IAAAA,EAAA,gBAAS;AACT,IAAAA,EAAA,iBAAU;AACV,IAAAA,EAAA;AA0CA,IAAAA,EAAA;AAvCN,SAAK,QAAQ,IAAIC,EAAUF,EAAK,EAAE;AAClC,UAAMG,IAA+C;AAAA,MACnD,MAAM;AAAA,MACN,WAAWH,EAAK;AAAA,MAChB,GAAIA,EAAK,YAAY,EAAE,WAAWA,EAAK,UAAA,IAAuB,CAAA;AAAA,MAC9D,GAAIA,EAAK,eAAe,EAAE,cAAcA,EAAK,aAAA,IAAiB,CAAA;AAAA,MAC9D,GAAIA,EAAK,SAAS,WAAW,EAAE,MAAM,UAAmB,QAAQI,EAASJ,EAAK,UAAU,EAAE,EAAA,IAAM,CAAA;AAAA,MAChG,GAAIA,EAAK,OAAO,EAAE,UAAUA,EAAK,KAAA,IAAS,CAAA;AAAA,IAAC,GAOvC,EAAE,OAAAK,EAAA,IAAUC,EAAiBN,EAAK,KAAKA,EAAK,MAAM;AACxD,SAAK,OAAO,IAAIO,EAAkB;AAAA,MAChC,KAAKF;AAAA,MACL,OAAOL,EAAK,SAASA,EAAK;AAAA,MAC1B,MAAAG;AAAA,MACA,WAAW,MAAM,KAAK,MAAM,WAAA;AAAA,MAC5B,SAAS,CAACK,MAAmB;AAI3B,QAAIA,EAAE,SAAS,aAAU,KAAK,MAAMA,EAAE,SACtC,KAAK,MAAM,MAAMA,CAAC,GAAG,KAAK,KAAA;AAAA,MAC5B;AAAA,MACA,gBAAgB,CAACC,GAAGC,MAAQ;AAAE,aAAK,UAAUD,GAAG,KAAK,iBAAiBC,GAAK,KAAK,KAAA;AAAA,MAAO;AAAA,IAAA,CACxF,GACD,KAAK,KAAK,QAAA;AAAA,EACZ;AAAA;AAAA,EAGA,SAASC,GAA4B;AACnC,gBAAK,UAAU,IAAIA,CAAE,GACd,MAAM,KAAK,UAAU,OAAOA,CAAE;AAAA,EACvC;AAAA,EACQ,OAAa;AAAE,eAAWA,KAAM,KAAK,UAAW,CAAAA,EAAA;AAAA,EAAK;AAAA;AAAA,EAI7D,IAAI,KAAyB;AAAE,WAAO,KAAK;AAAA,EAAI;AAAA,EAC/C,IAAI,iBAA6C;AAAE,WAAO,KAAK,MAAM;AAAA,EAAe;AAAA,EACpF,IAAI,SAAiB;AAAE,WAAO,KAAK;AAAA,EAAQ;AAAA,EAC3C,IAAI,gBAAoC;AAAE,WAAO,KAAK;AAAA,EAAe;AAAA,EAErE,KAAKC,GAAoB;AACvB,UAAMC,IAAc,KAAK,KAAK,IAAA,EAAM,SAAS,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,IAC3DC,IAAM,KAAK,MAAM;AACvB,IAAKA,MACL,KAAK,MAAM,cAAcD,GAAa,EAAE,MAAM,QAAQ,MAAAD,GAAM,GAC5D,KAAK,KAAK,KAAK,EAAE,MAAM,QAAQ,gBAAgBE,GAAK,aAAAD,GAAa,SAAS,EAAE,MAAM,QAAQ,MAAAD,EAAA,GAAQ,GAClG,KAAK,KAAA;AAAA,EACP;AAAA,EAEA,OAAOG,GAAmBC,GAAwB;AAChD,UAAMF,IAAM,KAAK,MAAM;AACvB,IAAKA,KACL,KAAK,KAAK,KAAK,EAAE,MAAM,UAAU,gBAAgBA,GAAK,UAAAC,GAAU,GAAIC,IAAU,EAAE,SAAAA,EAAA,IAAY,CAAA,GAAK;AAAA,EACnG;AAAA,EAEA,WAAiB;AACf,UAAMF,IAAM,KAAK,MAAM;AACvB,IAAKA,KACL,KAAK,KAAK,KAAK,EAAE,MAAM,QAAQ,gBAAgBA,GAAK,KAAK,KAAK,MAAM,WAAA,EAAW,CAAG;AAAA,EACpF;AAAA,EAEA,QAAc;AAAE,SAAK,KAAK,MAAA,GAAS,KAAK,UAAU,MAAA;AAAA,EAAQ;AAC5D;AAEO,MAAMG,EAAY;AAAA,EACvB,YAA6BjB,GAA0B;AAA1B,SAAA,OAAAA;AAAA,EAA2B;AAAA;AAAA;AAAA,EAIxD,KAAa;AACX,WAAOI,EAAS,KAAK,KAAK,SAASc,GAAe;AAAA,EACpD;AAAA,EAEA,KAAKf,IAAoB,IAAuB;AAC9C,WAAO,IAAIJ,EAAkB,EAAE,GAAG,KAAK,MAAM,GAAGI,GAAM,IAAI,KAAK,GAAA,GAAM;AAAA,EACvE;AACF;"}
|
|
1
|
+
{"version":3,"file":"core.js","sources":["../src/protocol/entities.ts","../src/protocol/actions.ts","../src/protocol/frames.ts","../src/core.ts"],"sourcesContent":["import type {\n ConversationId, MessageId, ProfileId, SubjectId, TenantId, UserId,\n} from './ids.js'\nimport type { ActionId } from './ids.js'\n\n// ── Message content (discriminated union) ─────────────────────────────────────\n// The runtime stays generic by never hard-coding business content: a message is\n// one of a small, fixed set of shapes. `card`/`form`/`system` are how action\n// results and structured prompts render — they subsume most \"rich messaging\"\n// features without a per-feature content zoo.\n\nexport interface CardField { label: string; value: string }\n\n/** A reference to an action a card/quick-reply can invoke. */\nexport interface InlineActionRef { actionId: ActionId; label: string }\n\nexport type MessageContent =\n | { kind: 'text'; text: string; enc?: boolean; iv?: string }\n | { kind: 'attachment'; url: string; mime: string; name?: string; size?: number }\n | { kind: 'card'; title?: string; body?: string; fields?: CardField[]; actions?: InlineActionRef[] }\n | { kind: 'form'; prompt: string; actionId: ActionId }\n | { kind: 'system'; event: string; data?: Record<string, string | number | boolean> }\n | { kind: 'appointment'; title: string; startIso: string; endIso: string; location?: string; description?: string; googleUrl: string; icalUrl: string; confirmed?: boolean }\n\nexport type SenderRole = 'guest' | 'agent' | 'system' | 'bot'\n\n// ── Message ───────────────────────────────────────────────────────────────────\n// Ordering is by `seq` (server-assigned, monotonic per conversation), never by\n// `ts`. `ts` is wall-clock for display only. This kills the reorder/duplicate/\n// lost-on-reconnect class of bugs that millisecond-timestamp ordering caused.\n\nexport interface Message {\n id: MessageId\n conversationId: ConversationId\n seq: number\n senderId: UserId\n senderRole: SenderRole\n content: MessageContent\n ts: number\n replyToId?: MessageId\n editedAt?: number\n deletedAt?: number\n reactions?: Record<string, UserId[]>\n internal?: boolean // true = internal note, only visible to agents\n}\n\n// ── Conversation (the room; messages partition by conversationId) ─────────────\n// The room is the conversation, NOT the subject. Two guests discussing the same\n// subject get two conversations. `subjectId` is a nullable reference, never part\n// of the room identity — so \"one thread per (guest, subject)\" is enforced as\n// app logic at open-time, and many-threads-per-subject stays possible for free.\n\nexport interface Conversation {\n id: ConversationId\n tenantId: TenantId\n profileId: ProfileId // behavior profile → which actions this room has\n subjectId?: SubjectId // optional: the thing it's about\n guestId: UserId // the end-user\n /** Host-supplied display info for an identified guest (widget `user` option).\n * Display metadata only — identity is still the token/guestId. */\n guestName?: string\n guestEmail?: string\n guestAvatar?: string\n guestMeta?: Record<string, string>\n /** True once the guest's identity has been proven by a signed ES256 JWT\n * against the chatroom's guestPublicKey (secure identity mode). */\n guestVerified?: boolean\n participants: UserId[] // guest + any assigned agents (membership = authz)\n assignedAgentId?: UserId // routing/ownership\n aiActive?: boolean // staff assigned the AI to answer this room\n state: string // conversation state-machine state\n firstResponseAt?: number // first agent reply ts (SLA)\n csat?: number // satisfaction score 1–5 (set on resolution)\n lastSeq: number // highest seq assigned in this conversation\n tags?: string[] // macro/manual tags (e.g. \"refund\", \"vip\")\n /** Live sentiment of the guest's most recent message (best-effort, async). */\n sentiment?: 'positive' | 'neutral' | 'frustrated'\n /** -1 (very frustrated) .. +1 (very positive); paired with `sentiment`. */\n sentimentScore?: number\n /** Set once an SLA-breach escalation macro has fired, so it only fires once. */\n slaEscalatedAt?: number\n /** If set, the conversation is snoozed until this Unix ms timestamp.\n * Hidden from the inbox until the timestamp passes, then resurfaces. */\n snoozedUntil?: number\n /** Page URL where the widget was open when the conversation started. */\n pageUrl?: string\n /** Browser tab title at conversation start — gives agents context. */\n pageTitle?: string\n createdAt: number\n updatedAt: number\n}\n\n// ── Co-browsing / shared annotation ────────────────────────────────────────---\n// A lightweight shared whiteboard layered over a conversation: agent and guest\n// can draw freehand strokes that both sides see live. Strokes are relayed\n// (not stored as messages) and kept per-conversation so late joiners can catch\n// up via the `opened` frame's `annotations` field.\n\nexport interface AnnotationPoint { x: number; y: number }\nexport interface AnnotationStroke {\n id: string\n points: AnnotationPoint[]\n color: string\n width: number\n by: UserId\n}\n\n// ── Subject (the referenced entity — Intercom \"custom object\") ────────────────\n// Carries shared state (available → reserved → sold) and fields (price, vin…)\n// that actions read/write. Many conversations reference one subject. Never a room.\n\nexport interface Subject {\n id: SubjectId\n tenantId: TenantId\n title: string\n state: string\n fields: Record<string, string | number | boolean>\n /** URL of the page where the subject lives (e.g. the listing page URL).\n * Captured automatically by the widget and stored on first open. */\n url?: string\n createdAt: number\n updatedAt: number\n}\n\n// ── Conversation lifecycle ────────────────────────────────────────────────────\n/** States in which a conversation is no longer \"open\": it's done with, so inbox\n * / proactive sweeps skip it and load balancing frees the assigned agent. The\n * single source of truth for \"is this conversation finished?\". */\nexport const TERMINAL_STATES: ReadonlySet<string> = new Set([\n 'resolved', 'closed', 'sold', 'issued', 'checked_out',\n])\nexport function isTerminalState(state: string): boolean {\n return TERMINAL_STATES.has(state)\n}\n\nexport type Channel = 'widget' | 'email' | 'sms' | 'whatsapp' | 'instagram' | 'kakao' | 'messenger' | 'line'\n","import type { ActionId, ProfileId, TenantId } from './ids.js'\n\n// ── Actions: the product primitive ────────────────────────────────────────────\n// An action is data an admin authors in the dashboard; the runtime stays generic\n// and only knows how to execute a small, fixed set of EFFECTS. Adding \"make\n// offer\" or \"schedule meeting\" is a config row, not a code deploy.\n\nexport type ActionAudience = 'guest' | 'agent' | 'both'\nexport type ActionSurface = 'toolbar' | 'inline' | 'quick_reply'\n\nexport interface ActionInputField {\n name: string\n label: string\n type: 'text' | 'number' | 'date' | 'select'\n required?: boolean\n options?: string[] // for type: 'select'\n}\n\n// A terminal effect produces a result and ends the action. Actions are\n// single-shot: structured multi-step lives in the conversation state machine,\n// and conversational multi-step is the `bot` effect — not an action workflow.\nexport type TerminalEffect =\n | { type: 'webhook'; url: string } // signed POST to tenant system\n | { type: 'state_transition'; target: 'conversation' | 'subject'; toState: string }\n | { type: 'bot' } // route to the AI resolver\n | { type: 'builtin'; name: string } // e.g. 'handoff'\n\n// The ONLY composition allowed is \"collect a form, then run one terminal\n// effect\" — exactly one level deep. This covers input-gathering (e.g. an offer\n// amount) without becoming a workflow engine.\nexport type ActionEffect =\n | TerminalEffect\n | { type: 'form'; fields: ActionInputField[]; then: TerminalEffect }\n\nexport type ActionResult =\n | { kind: 'system_message'; template?: string } // post a system line into the chat\n | { kind: 'card' } // render the effect's response as a card\n | { kind: 'state_badge' } // reflect a state change\n | { kind: 'none' }\n\nexport interface ActionDef {\n id: ActionId\n label: string\n icon?: string\n confirm?: boolean\n audience: ActionAudience\n surface: ActionSurface\n availableInStates?: string[] // conversation/subject states; omit = always available\n effect: ActionEffect\n result: ActionResult\n}\n\n// Client-safe projection of an action: enough for the widget to render it and\n// collect inputs, but NONE of the effect internals (webhook URLs, transition\n// targets) — those stay server-side and execute on `invoke`. The client filters\n// by `availableInStates` locally against the current conversation state, so a\n// state change needs no manifest round-trip; the server re-validates on invoke.\nexport interface ManifestAction {\n id: ActionId\n label: string\n icon?: string\n confirm?: boolean\n audience: ActionAudience\n surface: ActionSurface\n availableInStates?: string[]\n input?: ActionInputField[] // present when the action collects input (form effect)\n}\n\n/** Project an internal action to its client-safe manifest form. */\nexport function toManifestAction(a: ActionDef): ManifestAction {\n const input = a.effect.type === 'form' ? a.effect.fields : undefined\n return {\n id: a.id, label: a.label, audience: a.audience, surface: a.surface,\n ...(a.icon ? { icon: a.icon } : {}),\n ...(a.confirm ? { confirm: a.confirm } : {}),\n ...(a.availableInStates ? { availableInStates: a.availableInStates } : {}),\n ...(input ? { input } : {}),\n }\n}\n\n// ── Behavior profile (what \"domain\" becomes) ──────────────────────────────────\n// A reusable, admin-composed bundle of actions + defaults + state machine. Not a\n// built-in taxonomy — the 7 old templates become starter presets of this shape.\n// `version` lets an in-flight invocation validate against a consistent snapshot.\n\n/** Operating hours slot: 0=Sun … 6=Sat, times in \"HH:MM\" 24h local. */\nexport interface OperatingHoursSlot { day: 0|1|2|3|4|5|6; open: string; close: string }\n\nexport interface BehaviorProfile {\n id: ProfileId\n tenantId: TenantId\n name: string\n actions: ActionDef[]\n defaults: {\n greeting?: string\n theme?: { accent: string }\n e2e?: boolean\n persona?: string\n /** Paid-tier flag: when true, hides the \"Powered by Relay\" footer in the widget. */\n whiteLabel?: boolean\n /** White-label: serve/embed the widget from this hostname (e.g.\n * \"chat.acmeco.com\"). Allowed automatically as a CORS origin for the\n * control-plane API so the widget works from the custom domain. */\n customDomain?: string\n }\n states: string[]\n initialState: string\n version: number\n welcomeMessage?: string // first message guests see when opening the widget\n operatingHours?: OperatingHoursSlot[] // empty/absent = always open\n offlineMessage?: string // shown outside operating hours instead of chat\n /** Base64-encoded ECDSA P-256 SPKI public key. When set, guest tokens must be\n * signed JWTs — unsigned opaque tokens are rejected. */\n guestPublicKey?: string\n createdAt: number\n updatedAt: number\n}\n","import type {\n ConnectionId, ConversationId, MessageId, ProfileId, SubjectId, UserId,\n} from './ids.js'\nimport type { Channel, Conversation, Message, MessageContent, Subject, AnnotationStroke } from './entities.js'\nimport type { ManifestAction } from './actions.js'\n\n/** Dashboard-configured pre-chat qualification form, delivered in the manifest. */\nexport interface PreChatConfig {\n enabled: boolean\n showWhen?: 'always' | 'offline'\n fields?: ('name' | 'email' | 'phone')[]\n topics?: string[]\n callbackOption?: boolean\n title?: string\n}\n\n// ── Wire protocol ─────────────────────────────────────────────────────────────\n// One shared contract, imported by server + widget + dashboard. A change here is\n// a compile error in every consumer — which is the whole reason this lives in a\n// shared package instead of being hand-copied three times.\n\nexport type ErrorCode =\n | 'UNAUTHORIZED' | 'FORBIDDEN' | 'NOT_FOUND' | 'BAD_REQUEST'\n | 'RATE_LIMITED' | 'PAYLOAD_TOO_LARGE' | 'CONFLICT' | 'INTERNAL'\n\nexport type ClientFrame =\n | { type: 'auth'; token: string }\n // Open an existing conversation, or find-or-create one. Find-or-create keys on\n // (guest, subject) when subjectId is given; otherwise a fresh conversation.\n | { type: 'open'; conversationId?: ConversationId; subjectId?: SubjectId; profileId?: ProfileId; pageUrl?: string; pageTitle?: string; subjectTitle?: string; subjectMeta?: string; linkFrom?: UserId;\n /** Host-supplied display info for the guest — persisted onto the\n * conversation server-side so agents see who they're talking to.\n * Display metadata only, never used for authorization. */\n userInfo?: { name?: string; email?: string; avatar?: string; meta?: Record<string, string> } }\n | { type: 'send'; conversationId: ConversationId; clientMsgId: string; content: MessageContent; replyToId?: MessageId; via?: Channel[] }\n | { type: 'sync'; conversationId: ConversationId; sinceSeq: number } // catch-up after cursor\n | { type: 'history'; conversationId: ConversationId; beforeSeq: number; limit?: number } // load older\n | { type: 'read'; conversationId: ConversationId; seq: number } // read up to seq\n | { type: 'typing'; conversationId: ConversationId; isTyping: boolean; preview?: string }\n | { type: 'react'; conversationId: ConversationId; messageId: MessageId; emoji: string; remove?: boolean }\n | { type: 'edit'; conversationId: ConversationId; messageId: MessageId; content: MessageContent }\n | { type: 'delete'; conversationId: ConversationId; messageId: MessageId }\n | { type: 'invoke'; conversationId: ConversationId; actionId: string; clientInvokeId: string; inputs?: Record<string, unknown> }\n | { type: 'assign'; conversationId: ConversationId; agentId: UserId | null } // null = unassign\n | { type: 'tag'; conversationId: ConversationId; tag: string; remove?: boolean }\n | { type: 'note'; conversationId: ConversationId; clientMsgId: string; text: string } // internal note\n | { type: 'agent_status'; status: 'online' | 'away' | 'offline' } // agent sets their availability\n // Co-browsing: a freehand stroke (or \"clear\") on the shared annotation canvas\n // for a subject-anchored conversation. Relayed live to the other participant.\n | { type: 'annotate'; conversationId: ConversationId; stroke: Omit<AnnotationStroke, 'by'> }\n | { type: 'annotate_clear'; conversationId: ConversationId }\n | { type: 'pubkey'; conversationId: ConversationId; key: string }\n // X3DH async E2E: a client uploads a batch of one-time prekeys so peers can\n // encrypt to them while they are offline. The server stores them opaquely and\n // vends one on demand — it never derives or uses the keys.\n | { type: 'uploadPrekeys'; identityKey: string; signedPrekey: string; signedPrekeyId: string; signature: string; oneTimePrekeys: string[] }\n | { type: 'fetchPrekey'; targetUserId: UserId }\n // Inbox stream subscription — used by the agent dashboard, which reuses this\n // ConnectionManager. Typed here so the dashboard doesn't need `as never`.\n | { type: 'subscribe_inbox' }\n | { type: 'unsubscribe_inbox' }\n | { type: 'ping' }\n\nexport type ServerFrame =\n | { type: 'authed'; userId: UserId; connectionId: ConnectionId }\n | { type: 'opened'; conversation: Conversation; subject?: Subject; annotations?: AnnotationStroke[] }\n | { type: 'manifest'; conversationId: ConversationId; actions: ManifestAction[]; version: number; name?: string; theme?: { accent: string }; e2e?: boolean; offline?: boolean; offlineMessage?: string; whiteLabel?: boolean; preChat?: PreChatConfig }\n | { type: 'message'; message: Message }\n | { type: 'ack'; clientMsgId: string; messageId: MessageId; seq: number; ts: number }\n | { type: 'delivered'; conversationId: ConversationId; seq: number; to: UserId }\n | { type: 'read'; conversationId: ConversationId; seq: number; by: UserId }\n | { type: 'sync'; conversationId: ConversationId; messages: Message[] }\n | { type: 'history'; conversationId: ConversationId; messages: Message[]; hasMore: boolean }\n | { type: 'typing'; conversationId: ConversationId; userId: UserId; isTyping: boolean; preview?: string }\n | { type: 'reaction'; conversationId: ConversationId; messageId: MessageId; emoji: string; by: UserId; removed: boolean }\n | { type: 'edited'; conversationId: ConversationId; messageId: MessageId; content: MessageContent; editedAt: number }\n | { type: 'deleted'; conversationId: ConversationId; messageId: MessageId; ts: number }\n | { type: 'state'; conversationId: ConversationId; state: string }\n | { type: 'assigned'; conversationId: ConversationId; agentId: UserId | null }\n | { type: 'tagged'; conversationId: ConversationId; tag: string; removed: boolean }\n | { type: 'visitor_count'; count: number } // broadcast to agents: guests currently connected\n | { type: 'agent_status_changed'; agentId: UserId; status: 'online' | 'away' | 'offline' }\n // Live sentiment of a guest's most recent message — relayed to agents only so\n // the inbox can flag frustrated conversations as they happen.\n | { type: 'sentiment'; conversationId: ConversationId; label: 'positive' | 'neutral' | 'frustrated'; score: number }\n // Co-browsing: relay of an annotation stroke / clear to everyone in the room.\n | { type: 'annotation'; conversationId: ConversationId; stroke: AnnotationStroke }\n | { type: 'annotation_clear'; conversationId: ConversationId; by: UserId }\n | { type: 'subjectState'; subjectId: SubjectId; state: string }\n | { type: 'presence'; conversationId: ConversationId; userId: UserId; status: 'online' | 'offline'; lastSeen?: number }\n | { type: 'invoked'; clientInvokeId: string; ok: boolean; error?: string }\n | { type: 'error'; code: ErrorCode; message: string }\n | { type: 'peerkey'; conversationId: ConversationId; userId: UserId; key: string }\n // X3DH bundle vended to a requesting client so they can encrypt to an offline peer.\n // Contains null when the target user has no registered prekeys.\n | { type: 'prekeyBundle'; targetUserId: UserId; bundle: { identityKey: string; signedPrekey: string; signedPrekeyId: string; signature: string; oneTimePrekey?: string } | null }\n | { type: 'pong' }\n // Live inbox update for the guest's OWN conversation list (widget list socket\n // subscribes via `subscribe_inbox`). `patch` mirrors the agent inbox patch; the\n // list re-fetches on receipt, so only `kind`/`conversationId` are load-bearing.\n | { type: 'inbox_event'; kind: 'new' | 'update'; conversationId: ConversationId; patch?: Record<string, unknown> }\n\n/** Limits referenced by both ends so validation stays consistent. */\nexport const LIMITS = {\n MAX_TEXT_LEN: 8_000,\n MAX_HISTORY_LIMIT: 100,\n DEFAULT_HISTORY: 50,\n} as const\n","// ── @paramms/chat-widget/core — the headless SDK ─────────────────────────────\n// Everything you need to build your OWN chat UI (an in-app messenger, a\n// marketplace inbox, a full chat app) on the Relay protocol, with zero DOM or\n// React dependencies. This is not a new client: it is the exact transport,\n// store, outbox, and E2E machinery the bundled widget AND the agent dashboard\n// run on — re-exported behind a stable boundary, plus a small convenience\n// client for the common case.\n//\n// import { RelayClient } from '@paramms/chat-widget/core'\n//\n// // ONE url, any scheme — wss/ws/http(s) all work; ws + REST derived from it.\n// const relay = new RelayClient({ url: 'https://api.relay.paramms.com', token, profileId: 'p_x' })\n// const convo = relay.open({ subjectId: 'listing_42' }) // support thread\n// const dm = relay.open({ kind: 'direct', peerId: 'user_bob' }) // user↔user (signed identity required)\n// convo.onChange(() => render(convo.store.messages()))\n// convo.send('hello!')\n//\n// For React, see '@paramms/chat-widget/hooks'.\nexport { ConnectionManager, type SocketLike } from './connection.js'\nexport { ChatStore } from './store.js'\nexport { PersistentOutbox } from './outbox.js'\nexport { E2ESession } from './e2e.js'\nexport { restoreHistory, resolveRelayUrls, httpBaseFromWsUrl } from './history.js'\nexport { mountChatList, type ChatListEntry, type ChatListHandle, type ChatListOptions } from './chatlist.js'\nexport { persistentUid } from './uid.js'\nexport * from './protocol/index.js'\n\nimport { ConnectionManager } from './connection.js'\nimport { ChatStore } from './store.js'\nimport type { ClientFrame, ServerFrame, ConversationId, UserId } from './protocol/index.js'\nimport { asUserId } from './protocol/index.js'\nimport { persistentUid } from './uid.js'\nimport { resolveRelayUrls } from './history.js'\n\nexport interface RelayClientOptions {\n /** Relay URL — ONE url, any scheme. `https://api.relay.paramms.com` is the\n * recommended form; the WebSocket URL (`wss://…/ws`) and REST base are\n * derived from it automatically. `wss://`/`ws://`/`http://` also accepted. */\n url: string\n /** HTTP(S) base for REST calls — only when the REST API lives on a\n * DIFFERENT origin than the socket. Normally omit.\n * @deprecated pass a single `url`; kept for back-compat. */\n apiUrl?: string\n /** Identity: a signed JWT (secure), a stable userId (host-vouched), or omit\n * for an anonymous per-browser guest (browser environments only). */\n token?: string\n /** Chatroom id (from the dashboard). Required to open conversations. */\n profileId: string\n}\n\nexport interface OpenOptions {\n /** Support thread scoped to a subject (listing/order/…): one thread per\n * (user, subject). Omit for the profile's single support thread. */\n subjectId?: string\n subjectTitle?: string\n /** User↔user conversation (requires the chatroom to have signed identity\n * and `token` to be a valid signed JWT). */\n kind?: 'direct'\n peerId?: string\n /** Display info persisted for agents (support threads only). */\n user?: { name?: string; email?: string; avatar?: string; meta?: Record<string, string> }\n}\n\n/** One conversation = one connection + one store. Deliberately thin: the\n * store is the source of truth, `onChange` is the render signal, everything\n * else is the same primitives the first-party UIs use. */\nexport class RelayConversation {\n readonly store: ChatStore\n private readonly conn: ConnectionManager\n private readonly listeners = new Set<() => void>()\n private msgSeq = 0\n private _status = 'connecting'\n private _statusMessage: string | undefined\n\n constructor(opts: RelayClientOptions & OpenOptions & { me: UserId }) {\n this.store = new ChatStore(opts.me)\n const open: Extract<ClientFrame, { type: 'open' }> = {\n type: 'open',\n profileId: opts.profileId as never,\n ...(opts.subjectId ? { subjectId: opts.subjectId as never } : {}),\n ...(opts.subjectTitle ? { subjectTitle: opts.subjectTitle } : {}),\n ...(opts.kind === 'direct' ? { kind: 'direct' as const, peerId: asUserId(opts.peerId ?? '') } : {}),\n ...(opts.user ? { userInfo: opts.user } : {}),\n }\n // Accept any scheme (https/http/wss/ws) — a plain `https://api.…` URL is\n // resolved to the concrete `wss://…/ws` socket endpoint, exactly like the\n // bundled widget's mount(). Before this, RelayClient required a raw\n // WebSocket URL while the React components took `https://` — one URL now\n // works across the entire SDK.\n const { wsUrl } = resolveRelayUrls(opts.url, opts.apiUrl)\n this.conn = new ConnectionManager({\n url: wsUrl,\n token: opts.token ?? opts.me,\n open,\n getCursor: () => this.store.highestSeq(),\n onFrame: (f: ServerFrame) => {\n // The server tells us our CANONICAL id on auth (a signed JWT's sub,\n // not the raw token) — capture it so `mine` checks work under every\n // identity tier.\n if (f.type === 'authed') this._me = f.userId as UserId\n this.store.apply(f); this.emit()\n },\n onStatusChange: (s, msg) => { this._status = s; this._statusMessage = msg; this.emit() },\n })\n this.conn.connect()\n }\n\n /** Subscribe to any change (message, typing, status). Returns unsubscribe. */\n onChange(fn: () => void): () => void {\n this.listeners.add(fn)\n return () => this.listeners.delete(fn)\n }\n private emit(): void { for (const fn of this.listeners) fn() }\n\n private _me: UserId | undefined\n /** Our canonical user id as resolved by the server (JWT sub / userId / anon id). */\n get me(): UserId | undefined { return this._me }\n get conversationId(): ConversationId | undefined { return this.store.conversationId }\n get status(): string { return this._status }\n get statusMessage(): string | undefined { return this._statusMessage }\n\n send(text: string): void {\n const clientMsgId = `c_${Date.now().toString(36)}_${++this.msgSeq}`\n const cid = this.store.conversationId\n if (!cid) return\n this.store.addOptimistic(clientMsgId, { kind: 'text', text })\n this.conn.send({ type: 'send', conversationId: cid, clientMsgId, content: { kind: 'text', text } })\n this.emit()\n }\n\n typing(isTyping: boolean, preview?: string): void {\n const cid = this.store.conversationId\n if (!cid) return\n this.conn.send({ type: 'typing', conversationId: cid, isTyping, ...(preview ? { preview } : {}) })\n }\n\n markRead(): void {\n const cid = this.store.conversationId\n if (!cid) return\n this.conn.send({ type: 'read', conversationId: cid, seq: this.store.highestSeq() })\n }\n\n close(): void { this.conn.close(); this.listeners.clear() }\n}\n\nexport class RelayClient {\n constructor(private readonly opts: RelayClientOptions) {}\n\n /** The identity this client will act as: the token's subject (resolved\n * server-side), the raw userId, or a persistent anonymous browser id. */\n me(): UserId {\n return asUserId(this.opts.token ?? persistentUid())\n }\n\n open(open: OpenOptions = {}): RelayConversation {\n return new RelayConversation({ ...this.opts, ...open, me: this.me() })\n }\n}\n"],"names":["TERMINAL_STATES","isTerminalState","state","toManifestAction","a","input","LIMITS","RelayConversation","opts","__publicField","ChatStore","open","asUserId","wsUrl","resolveRelayUrls","ConnectionManager","f","s","msg","fn","text","clientMsgId","cid","isTyping","preview","RelayClient","persistentUid"],"mappings":";;;;;;;;;AAgIO,MAAMA,wBAA2C,IAAI;AAAA,EAC1D;AAAA,EAAY;AAAA,EAAU;AAAA,EAAQ;AAAA,EAAU;AAC1C,CAAC;AACM,SAASC,EAAgBC,GAAwB;AACtD,SAAOF,EAAgB,IAAIE,CAAK;AAClC;AChEO,SAASC,EAAiBC,GAA8B;AAC7D,QAAMC,IAAQD,EAAE,OAAO,SAAS,SAASA,EAAE,OAAO,SAAS;AAC3D,SAAO;AAAA,IACL,IAAIA,EAAE;AAAA,IAAI,OAAOA,EAAE;AAAA,IAAO,UAAUA,EAAE;AAAA,IAAU,SAASA,EAAE;AAAA,IAC3D,GAAIA,EAAE,OAAO,EAAE,MAAMA,EAAE,KAAA,IAAS,CAAA;AAAA,IAChC,GAAIA,EAAE,UAAU,EAAE,SAASA,EAAE,QAAA,IAAY,CAAA;AAAA,IACzC,GAAIA,EAAE,oBAAoB,EAAE,mBAAmBA,EAAE,kBAAA,IAAsB,CAAA;AAAA,IACvE,GAAIC,IAAQ,EAAE,OAAAA,MAAU,CAAA;AAAA,EAAC;AAE7B;ACyBO,MAAMC,IAAS;AAAA,EACpB,cAAoB;AAAA,EACpB,mBAAoB;AAAA,EACpB,iBAAoB;AACtB;ACzCO,MAAMC,EAAkB;AAAA,EAQ7B,YAAYC,GAAyD;AAP5D,IAAAC,EAAA;AACQ,IAAAA,EAAA;AACA,IAAAA,EAAA,uCAAgB,IAAA;AACzB,IAAAA,EAAA,gBAAS;AACT,IAAAA,EAAA,iBAAU;AACV,IAAAA,EAAA;AA0CA,IAAAA,EAAA;AAvCN,SAAK,QAAQ,IAAIC,EAAUF,EAAK,EAAE;AAClC,UAAMG,IAA+C;AAAA,MACnD,MAAM;AAAA,MACN,WAAWH,EAAK;AAAA,MAChB,GAAIA,EAAK,YAAY,EAAE,WAAWA,EAAK,UAAA,IAAuB,CAAA;AAAA,MAC9D,GAAIA,EAAK,eAAe,EAAE,cAAcA,EAAK,aAAA,IAAiB,CAAA;AAAA,MAC9D,GAAIA,EAAK,SAAS,WAAW,EAAE,MAAM,UAAmB,QAAQI,EAASJ,EAAK,UAAU,EAAE,EAAA,IAAM,CAAA;AAAA,MAChG,GAAIA,EAAK,OAAO,EAAE,UAAUA,EAAK,KAAA,IAAS,CAAA;AAAA,IAAC,GAOvC,EAAE,OAAAK,EAAA,IAAUC,EAAiBN,EAAK,KAAKA,EAAK,MAAM;AACxD,SAAK,OAAO,IAAIO,EAAkB;AAAA,MAChC,KAAKF;AAAA,MACL,OAAOL,EAAK,SAASA,EAAK;AAAA,MAC1B,MAAAG;AAAA,MACA,WAAW,MAAM,KAAK,MAAM,WAAA;AAAA,MAC5B,SAAS,CAACK,MAAmB;AAI3B,QAAIA,EAAE,SAAS,aAAU,KAAK,MAAMA,EAAE,SACtC,KAAK,MAAM,MAAMA,CAAC,GAAG,KAAK,KAAA;AAAA,MAC5B;AAAA,MACA,gBAAgB,CAACC,GAAGC,MAAQ;AAAE,aAAK,UAAUD,GAAG,KAAK,iBAAiBC,GAAK,KAAK,KAAA;AAAA,MAAO;AAAA,IAAA,CACxF,GACD,KAAK,KAAK,QAAA;AAAA,EACZ;AAAA;AAAA,EAGA,SAASC,GAA4B;AACnC,gBAAK,UAAU,IAAIA,CAAE,GACd,MAAM,KAAK,UAAU,OAAOA,CAAE;AAAA,EACvC;AAAA,EACQ,OAAa;AAAE,eAAWA,KAAM,KAAK,UAAW,CAAAA,EAAA;AAAA,EAAK;AAAA;AAAA,EAI7D,IAAI,KAAyB;AAAE,WAAO,KAAK;AAAA,EAAI;AAAA,EAC/C,IAAI,iBAA6C;AAAE,WAAO,KAAK,MAAM;AAAA,EAAe;AAAA,EACpF,IAAI,SAAiB;AAAE,WAAO,KAAK;AAAA,EAAQ;AAAA,EAC3C,IAAI,gBAAoC;AAAE,WAAO,KAAK;AAAA,EAAe;AAAA,EAErE,KAAKC,GAAoB;AACvB,UAAMC,IAAc,KAAK,KAAK,IAAA,EAAM,SAAS,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,IAC3DC,IAAM,KAAK,MAAM;AACvB,IAAKA,MACL,KAAK,MAAM,cAAcD,GAAa,EAAE,MAAM,QAAQ,MAAAD,GAAM,GAC5D,KAAK,KAAK,KAAK,EAAE,MAAM,QAAQ,gBAAgBE,GAAK,aAAAD,GAAa,SAAS,EAAE,MAAM,QAAQ,MAAAD,EAAA,GAAQ,GAClG,KAAK,KAAA;AAAA,EACP;AAAA,EAEA,OAAOG,GAAmBC,GAAwB;AAChD,UAAMF,IAAM,KAAK,MAAM;AACvB,IAAKA,KACL,KAAK,KAAK,KAAK,EAAE,MAAM,UAAU,gBAAgBA,GAAK,UAAAC,GAAU,GAAIC,IAAU,EAAE,SAAAA,EAAA,IAAY,CAAA,GAAK;AAAA,EACnG;AAAA,EAEA,WAAiB;AACf,UAAMF,IAAM,KAAK,MAAM;AACvB,IAAKA,KACL,KAAK,KAAK,KAAK,EAAE,MAAM,QAAQ,gBAAgBA,GAAK,KAAK,KAAK,MAAM,WAAA,EAAW,CAAG;AAAA,EACpF;AAAA,EAEA,QAAc;AAAE,SAAK,KAAK,MAAA,GAAS,KAAK,UAAU,MAAA;AAAA,EAAQ;AAC5D;AAEO,MAAMG,EAAY;AAAA,EACvB,YAA6BjB,GAA0B;AAA1B,SAAA,OAAAA;AAAA,EAA2B;AAAA;AAAA;AAAA,EAIxD,KAAa;AACX,WAAOI,EAAS,KAAK,KAAK,SAASc,GAAe;AAAA,EACpD;AAAA,EAEA,KAAKf,IAAoB,IAAuB;AAC9C,WAAO,IAAIJ,EAAkB,EAAE,GAAG,KAAK,MAAM,GAAGI,GAAM,IAAI,KAAK,GAAA,GAAM;AAAA,EACvE;AACF;"}
|