@wix/legends-platform-sdk 1.25.0 → 1.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/cjs/conversation/types.js.map +1 -1
- package/dist/cjs/hooks/useConversation/livekit/useConversation.js +34 -16
- package/dist/cjs/hooks/useConversation/livekit/useConversation.js.map +1 -1
- package/dist/cjs/hooks/useConversation/livekit/utils/dataChannel.js +4 -0
- package/dist/cjs/hooks/useConversation/livekit/utils/dataChannel.js.map +1 -1
- package/dist/cjs/hooks/useConversationEvents/types.js.map +1 -1
- package/dist/cjs/hooks/useTextChat/streamChatMessage.js +18 -1
- package/dist/cjs/hooks/useTextChat/streamChatMessage.js.map +1 -1
- package/dist/cjs/hooks/useTextChat/useTextChatStream.js +5 -2
- package/dist/cjs/hooks/useTextChat/useTextChatStream.js.map +1 -1
- package/dist/esm/conversation/types.js.map +1 -1
- package/dist/esm/hooks/useConversation/livekit/useConversation.js +35 -17
- package/dist/esm/hooks/useConversation/livekit/useConversation.js.map +1 -1
- package/dist/esm/hooks/useConversation/livekit/utils/dataChannel.js +3 -0
- package/dist/esm/hooks/useConversation/livekit/utils/dataChannel.js.map +1 -1
- package/dist/esm/hooks/useConversationEvents/types.js.map +1 -1
- package/dist/esm/hooks/useTextChat/streamChatMessage.js +17 -1
- package/dist/esm/hooks/useTextChat/streamChatMessage.js.map +1 -1
- package/dist/esm/hooks/useTextChat/useTextChatStream.js +5 -2
- package/dist/esm/hooks/useTextChat/useTextChatStream.js.map +1 -1
- package/dist/types/conversation/types.d.ts +1 -1
- package/dist/types/conversation/types.d.ts.map +1 -1
- package/dist/types/hooks/useConversation/livekit/useConversation.d.ts.map +1 -1
- package/dist/types/hooks/useConversation/livekit/utils/dataChannel.d.ts +1 -0
- package/dist/types/hooks/useConversation/livekit/utils/dataChannel.d.ts.map +1 -1
- package/dist/types/hooks/useConversationEvents/types.d.ts +4 -0
- package/dist/types/hooks/useConversationEvents/types.d.ts.map +1 -1
- package/dist/types/hooks/useTextChat/streamChatMessage.d.ts +2 -0
- package/dist/types/hooks/useTextChat/streamChatMessage.d.ts.map +1 -1
- package/dist/types/hooks/useTextChat/useTextChatStream.d.ts +1 -0
- package/dist/types/hooks/useTextChat/useTextChatStream.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","require","_reactQuery","_sdkConsumer","_streamChatMessage","messageKey","m","role","content","trim","useTextChatStream","options","limit","headers","onError","revealMsPerChar","chatId","namespace","personaChatService","useSdkConsumer","data","sdkMessages","status","fetchNextPage","refetch","useInfiniteQuery","queryKey","queryFn","pageParam","messages","nextCursor","undefined","queryChatMessages","cursor","getNextPageParam","lastPage","initialPageParam","select","pages","flatMap","page","streamingMessages","setStreamingMessages","useState","completedMessages","setCompletedMessages","abortRef","useRef","rafRef","lastConfirmedRef","sendSeqRef","stopRaf","useCallback","current","cancelAnimationFrame","useEffect","_abortRef$current","abort","useMemo","converted","reverse","confirmedMessages","length","completedKeys","Set","map","confirmedShown","filter","has","chronological","send","message","chatConfig","attachments","metadata","_abortRef$current2","controller","AbortController","seq","userMsgId","Date","now","assistantMsgId","optimisticUserMsg","id","streamingAssistantMsg","streamStatus","streamingText","accumulated","revealedLen","streamDone","carry","lastFrameTime","receivedContent","errored","settle","finalAssistantMsg","prev","frame","elapsedMs","step","Math","floor","min","slice","requestAnimationFrame","startRaf","streamChatMessage","onChunk","token","onDone","err","signal","ok","producedContent","aborted","pending","fetchNext"],"sources":["../../../../src/hooks/useTextChat/useTextChatStream.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useInfiniteQuery } from '@tanstack/react-query';\nimport type { ChatMessage, ChatMessageAttachment } from '../../types';\nimport { useSdkConsumer } from '../../sdk-consumer';\nimport { streamChatMessage } from './streamChatMessage';\n\nexport type {\n StreamCallbacks,\n StreamChatMessageParams,\n} from './streamChatMessage';\n\n/**\n * A platform `ChatMessage` augmented with streaming metadata. The host renderer\n * uses `streamStatus`/`streamingText` to drive its typewriter; confirmed\n * (non-streamed) messages carry neither.\n */\nexport type StreamingChatMessage = ChatMessage & {\n streamingText?: string;\n streamStatus?: 'streaming' | 'settled';\n};\n\nexport interface UseTextChatStreamOptions {\n limit?: number;\n // Extra headers forwarded on every stream request — e.g. an `x-xsrf-token`\n // for the CSRF-protected persona-chat gateway.\n headers?: Record<string, string>;\n // Stream failures surfaced to the host (e.g. report to Sentry + toast).\n onError?: (err: Error) => void;\n // Milliseconds per character for the requestAnimationFrame reveal drip.\n // Default 16 (~62 chars/s).\n revealMsPerChar?: number;\n}\n\nexport interface SendStreamMessageParams {\n message: string;\n chatConfig?: object;\n attachments?: ChatMessageAttachment[];\n metadata?: object;\n}\n\n/**\n * Per-send outcome resolved by `send`. Reported at the transport level,\n * independent of the rAF reveal state — so a consumer can implement a\n * race-free, reveal-independent safe fallback.\n */\nexport type StreamSendResult = {\n ok: boolean; // stream completed successfully (reached onDone)\n producedContent: boolean; // at least one content chunk was received\n aborted: boolean; // the send was superseded/cancelled — not a real failure\n};\n\nconst messageKey = (m: StreamingChatMessage) =>\n `${m.role}::${(m.content ?? '').trim()}`;\n\n/**\n * Streaming counterpart to `useTextChat`. Sends a message over the SSE transport\n * and drips the accumulated reply into `streamingText` at a steady, time-paced\n * rate via requestAnimationFrame.\n *\n * Uses the same React Query key as `useTextChat` so mounting both hooks\n * does not double-fetch the message history.\n *\n * NOTE: uses `credentials: 'include'` + XSRF cookie auth — intended for\n * Wix-internal consumers where the persona-chat gateway is same-origin.\n */\nexport function useTextChatStream(options: UseTextChatStreamOptions = {}) {\n const { limit = 50, headers, onError, revealMsPerChar = 16 } = options;\n\n const { chatId, namespace, personaChatService } = useSdkConsumer();\n\n // Same query key as useTextChat — dedupes the history fetch when both are mounted.\n const {\n data: sdkMessages = [],\n status,\n fetchNextPage,\n refetch,\n } = useInfiniteQuery({\n queryKey: ['chat-messages', chatId, namespace],\n queryFn: async ({ pageParam }: { pageParam?: string }) => {\n if (!personaChatService) {\n return { messages: [], nextCursor: undefined };\n }\n return personaChatService.queryChatMessages({\n chatId,\n namespace,\n limit,\n cursor: pageParam,\n });\n },\n getNextPageParam: (lastPage) => lastPage.nextCursor,\n initialPageParam: undefined as string | undefined,\n select: (data) =>\n data.pages.flatMap((page) => page.messages as ChatMessage[]),\n });\n\n const [streamingMessages, setStreamingMessages] = useState<\n StreamingChatMessage[]\n >([]);\n const [completedMessages, setCompletedMessages] = useState<\n StreamingChatMessage[]\n >([]);\n const abortRef = useRef<AbortController | null>(null);\n const rafRef = useRef<number | null>(null);\n const lastConfirmedRef = useRef<StreamingChatMessage[]>([]);\n const sendSeqRef = useRef(0);\n\n const stopRaf = useCallback(() => {\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current);\n rafRef.current = null;\n }\n }, []);\n\n useEffect(() => {\n return () => {\n abortRef.current?.abort();\n stopRaf();\n };\n }, [stopRaf]);\n\n const messages = useMemo<StreamingChatMessage[]>(() => {\n const converted = [...sdkMessages].reverse() as StreamingChatMessage[];\n const confirmedMessages =\n converted.length > 0 ? converted : lastConfirmedRef.current;\n\n const completedKeys = new Set(completedMessages.map(messageKey));\n const confirmedShown = confirmedMessages.filter(\n (m) => !completedKeys.has(messageKey(m)),\n );\n const chronological = [\n ...confirmedShown,\n ...completedMessages,\n ...streamingMessages,\n ];\n return chronological.reverse();\n }, [sdkMessages, streamingMessages, completedMessages]);\n\n useEffect(() => {\n const converted = [...sdkMessages].reverse() as StreamingChatMessage[];\n if (converted.length > 0) {\n lastConfirmedRef.current = converted;\n }\n }, [sdkMessages]);\n\n const send = useCallback(\n async ({\n message,\n chatConfig,\n attachments,\n metadata,\n }: SendStreamMessageParams): Promise<StreamSendResult> => {\n abortRef.current?.abort();\n const controller = new AbortController();\n abortRef.current = controller;\n\n const seq = (sendSeqRef.current += 1);\n const userMsgId = `stream-user-${Date.now()}-${seq}`;\n const assistantMsgId = `stream-assistant-${Date.now()}-${seq}`;\n\n const optimisticUserMsg: StreamingChatMessage = {\n id: userMsgId,\n role: 'USER' as ChatMessage['role'],\n content: message,\n attachments: attachments as StreamingChatMessage['attachments'],\n };\n\n const streamingAssistantMsg: StreamingChatMessage = {\n id: assistantMsgId,\n role: 'ASSISTANT' as ChatMessage['role'],\n content: '',\n streamStatus: 'streaming',\n streamingText: '',\n };\n\n setStreamingMessages([optimisticUserMsg, streamingAssistantMsg]);\n\n let accumulated = '';\n let revealedLen = 0;\n let streamDone = false;\n let carry = 0;\n let lastFrameTime = 0;\n let receivedContent = false;\n let errored = false;\n\n const settle = () => {\n stopRaf();\n const finalAssistantMsg: StreamingChatMessage = {\n ...streamingAssistantMsg,\n content: accumulated,\n streamStatus: 'settled',\n streamingText: accumulated,\n };\n setCompletedMessages((prev) => [\n ...prev,\n optimisticUserMsg,\n finalAssistantMsg,\n ]);\n setStreamingMessages([]);\n void refetch();\n };\n\n const frame = (now: number) => {\n if (lastFrameTime === 0) {\n lastFrameTime = now;\n }\n const elapsedMs = now - lastFrameTime;\n lastFrameTime = now;\n\n if (revealedLen < accumulated.length) {\n carry += elapsedMs / revealMsPerChar;\n const step = Math.floor(carry);\n if (step > 0) {\n carry -= step;\n revealedLen = Math.min(accumulated.length, revealedLen + step);\n setStreamingMessages([\n optimisticUserMsg,\n {\n ...streamingAssistantMsg,\n streamStatus: 'streaming',\n streamingText: accumulated.slice(0, revealedLen),\n },\n ]);\n }\n rafRef.current = requestAnimationFrame(frame);\n } else if (streamDone) {\n settle();\n } else {\n stopRaf();\n }\n };\n\n const startRaf = () => {\n if (rafRef.current === null) {\n lastFrameTime = 0;\n rafRef.current = requestAnimationFrame(frame);\n }\n };\n\n await streamChatMessage(\n {\n chatId,\n message,\n namespace,\n chatConfig,\n attachments,\n metadata,\n headers,\n },\n {\n onChunk: (token) => {\n receivedContent = true;\n accumulated += token;\n startRaf();\n },\n onDone: () => {\n streamDone = true;\n startRaf();\n },\n onError: (err) => {\n errored = true;\n stopRaf();\n onError?.(err);\n setStreamingMessages([]);\n },\n },\n controller.signal,\n );\n\n return {\n ok: streamDone && !errored,\n producedContent: receivedContent,\n aborted: !streamDone && !errored,\n };\n },\n [chatId, namespace, headers, onError, refetch, revealMsPerChar, stopRaf],\n );\n\n return {\n status,\n pending: [] as never[],\n messages,\n fetchNext,\n refetch,\n send,\n };\n\n function fetchNext() {\n void fetchNextPage();\n }\n}\n"],"mappings":";;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,WAAA,GAAAD,OAAA;AAEA,IAAAE,YAAA,GAAAF,OAAA;AACA,IAAAG,kBAAA,GAAAH,OAAA;AAOA;AACA;AACA;AACA;AACA;;AAyBA;AACA;AACA;AACA;AACA;;AAOA,MAAMI,UAAU,GAAIC,CAAuB,IACzC,GAAGA,CAAC,CAACC,IAAI,KAAK,CAACD,CAAC,CAACE,OAAO,IAAI,EAAE,EAAEC,IAAI,CAAC,CAAC,EAAE;;AAE1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASC,iBAAiBA,CAACC,OAAiC,GAAG,CAAC,CAAC,EAAE;EACxE,MAAM;IAAEC,KAAK,GAAG,EAAE;IAAEC,OAAO;IAAEC,OAAO;IAAEC,eAAe,GAAG;EAAG,CAAC,GAAGJ,OAAO;EAEtE,MAAM;IAAEK,MAAM;IAAEC,SAAS;IAAEC;EAAmB,CAAC,GAAG,IAAAC,2BAAc,EAAC,CAAC;;EAElE;EACA,MAAM;IACJC,IAAI,EAAEC,WAAW,GAAG,EAAE;IACtBC,MAAM;IACNC,aAAa;IACbC;EACF,CAAC,GAAG,IAAAC,4BAAgB,EAAC;IACnBC,QAAQ,EAAE,CAAC,eAAe,EAAEV,MAAM,EAAEC,SAAS,CAAC;IAC9CU,OAAO,EAAE,MAAAA,CAAO;MAAEC;IAAkC,CAAC,KAAK;MACxD,IAAI,CAACV,kBAAkB,EAAE;QACvB,OAAO;UAAEW,QAAQ,EAAE,EAAE;UAAEC,UAAU,EAAEC;QAAU,CAAC;MAChD;MACA,OAAOb,kBAAkB,CAACc,iBAAiB,CAAC;QAC1ChB,MAAM;QACNC,SAAS;QACTL,KAAK;QACLqB,MAAM,EAAEL;MACV,CAAC,CAAC;IACJ,CAAC;IACDM,gBAAgB,EAAGC,QAAQ,IAAKA,QAAQ,CAACL,UAAU;IACnDM,gBAAgB,EAAEL,SAA+B;IACjDM,MAAM,EAAGjB,IAAI,IACXA,IAAI,CAACkB,KAAK,CAACC,OAAO,CAAEC,IAAI,IAAKA,IAAI,CAACX,QAAyB;EAC/D,CAAC,CAAC;EAEF,MAAM,CAACY,iBAAiB,EAAEC,oBAAoB,CAAC,GAAG,IAAAC,eAAQ,EAExD,EAAE,CAAC;EACL,MAAM,CAACC,iBAAiB,EAAEC,oBAAoB,CAAC,GAAG,IAAAF,eAAQ,EAExD,EAAE,CAAC;EACL,MAAMG,QAAQ,GAAG,IAAAC,aAAM,EAAyB,IAAI,CAAC;EACrD,MAAMC,MAAM,GAAG,IAAAD,aAAM,EAAgB,IAAI,CAAC;EAC1C,MAAME,gBAAgB,GAAG,IAAAF,aAAM,EAAyB,EAAE,CAAC;EAC3D,MAAMG,UAAU,GAAG,IAAAH,aAAM,EAAC,CAAC,CAAC;EAE5B,MAAMI,OAAO,GAAG,IAAAC,kBAAW,EAAC,MAAM;IAChC,IAAIJ,MAAM,CAACK,OAAO,KAAK,IAAI,EAAE;MAC3BC,oBAAoB,CAACN,MAAM,CAACK,OAAO,CAAC;MACpCL,MAAM,CAACK,OAAO,GAAG,IAAI;IACvB;EACF,CAAC,EAAE,EAAE,CAAC;EAEN,IAAAE,gBAAS,EAAC,MAAM;IACd,OAAO,MAAM;MAAA,IAAAC,iBAAA;MACX,CAAAA,iBAAA,GAAAV,QAAQ,CAACO,OAAO,aAAhBG,iBAAA,CAAkBC,KAAK,CAAC,CAAC;MACzBN,OAAO,CAAC,CAAC;IACX,CAAC;EACH,CAAC,EAAE,CAACA,OAAO,CAAC,CAAC;EAEb,MAAMtB,QAAQ,GAAG,IAAA6B,cAAO,EAAyB,MAAM;IACrD,MAAMC,SAAS,GAAG,CAAC,GAAGtC,WAAW,CAAC,CAACuC,OAAO,CAAC,CAA2B;IACtE,MAAMC,iBAAiB,GACrBF,SAAS,CAACG,MAAM,GAAG,CAAC,GAAGH,SAAS,GAAGV,gBAAgB,CAACI,OAAO;IAE7D,MAAMU,aAAa,GAAG,IAAIC,GAAG,CAACpB,iBAAiB,CAACqB,GAAG,CAAC5D,UAAU,CAAC,CAAC;IAChE,MAAM6D,cAAc,GAAGL,iBAAiB,CAACM,MAAM,CAC5C7D,CAAC,IAAK,CAACyD,aAAa,CAACK,GAAG,CAAC/D,UAAU,CAACC,CAAC,CAAC,CACzC,CAAC;IACD,MAAM+D,aAAa,GAAG,CACpB,GAAGH,cAAc,EACjB,GAAGtB,iBAAiB,EACpB,GAAGH,iBAAiB,CACrB;IACD,OAAO4B,aAAa,CAACT,OAAO,CAAC,CAAC;EAChC,CAAC,EAAE,CAACvC,WAAW,EAAEoB,iBAAiB,EAAEG,iBAAiB,CAAC,CAAC;EAEvD,IAAAW,gBAAS,EAAC,MAAM;IACd,MAAMI,SAAS,GAAG,CAAC,GAAGtC,WAAW,CAAC,CAACuC,OAAO,CAAC,CAA2B;IACtE,IAAID,SAAS,CAACG,MAAM,GAAG,CAAC,EAAE;MACxBb,gBAAgB,CAACI,OAAO,GAAGM,SAAS;IACtC;EACF,CAAC,EAAE,CAACtC,WAAW,CAAC,CAAC;EAEjB,MAAMiD,IAAI,GAAG,IAAAlB,kBAAW,EACtB,OAAO;IACLmB,OAAO;IACPC,UAAU;IACVC,WAAW;IACXC;EACuB,CAAC,KAAgC;IAAA,IAAAC,kBAAA;IACxD,CAAAA,kBAAA,GAAA7B,QAAQ,CAACO,OAAO,aAAhBsB,kBAAA,CAAkBlB,KAAK,CAAC,CAAC;IACzB,MAAMmB,UAAU,GAAG,IAAIC,eAAe,CAAC,CAAC;IACxC/B,QAAQ,CAACO,OAAO,GAAGuB,UAAU;IAE7B,MAAME,GAAG,GAAI5B,UAAU,CAACG,OAAO,IAAI,CAAE;IACrC,MAAM0B,SAAS,GAAG,eAAeC,IAAI,CAACC,GAAG,CAAC,CAAC,IAAIH,GAAG,EAAE;IACpD,MAAMI,cAAc,GAAG,oBAAoBF,IAAI,CAACC,GAAG,CAAC,CAAC,IAAIH,GAAG,EAAE;IAE9D,MAAMK,iBAAuC,GAAG;MAC9CC,EAAE,EAAEL,SAAS;MACbxE,IAAI,EAAE,MAA6B;MACnCC,OAAO,EAAE+D,OAAO;MAChBE,WAAW,EAAEA;IACf,CAAC;IAED,MAAMY,qBAA2C,GAAG;MAClDD,EAAE,EAAEF,cAAc;MAClB3E,IAAI,EAAE,WAAkC;MACxCC,OAAO,EAAE,EAAE;MACX8E,YAAY,EAAE,WAAW;MACzBC,aAAa,EAAE;IACjB,CAAC;IAED7C,oBAAoB,CAAC,CAACyC,iBAAiB,EAAEE,qBAAqB,CAAC,CAAC;IAEhE,IAAIG,WAAW,GAAG,EAAE;IACpB,IAAIC,WAAW,GAAG,CAAC;IACnB,IAAIC,UAAU,GAAG,KAAK;IACtB,IAAIC,KAAK,GAAG,CAAC;IACb,IAAIC,aAAa,GAAG,CAAC;IACrB,IAAIC,eAAe,GAAG,KAAK;IAC3B,IAAIC,OAAO,GAAG,KAAK;IAEnB,MAAMC,MAAM,GAAGA,CAAA,KAAM;MACnB5C,OAAO,CAAC,CAAC;MACT,MAAM6C,iBAAuC,GAAG;QAC9C,GAAGX,qBAAqB;QACxB7E,OAAO,EAAEgF,WAAW;QACpBF,YAAY,EAAE,SAAS;QACvBC,aAAa,EAAEC;MACjB,CAAC;MACD3C,oBAAoB,CAAEoD,IAAI,IAAK,CAC7B,GAAGA,IAAI,EACPd,iBAAiB,EACjBa,iBAAiB,CAClB,CAAC;MACFtD,oBAAoB,CAAC,EAAE,CAAC;MACxB,KAAKlB,OAAO,CAAC,CAAC;IAChB,CAAC;IAED,MAAM0E,KAAK,GAAIjB,GAAW,IAAK;MAC7B,IAAIW,aAAa,KAAK,CAAC,EAAE;QACvBA,aAAa,GAAGX,GAAG;MACrB;MACA,MAAMkB,SAAS,GAAGlB,GAAG,GAAGW,aAAa;MACrCA,aAAa,GAAGX,GAAG;MAEnB,IAAIQ,WAAW,GAAGD,WAAW,CAAC1B,MAAM,EAAE;QACpC6B,KAAK,IAAIQ,SAAS,GAAGpF,eAAe;QACpC,MAAMqF,IAAI,GAAGC,IAAI,CAACC,KAAK,CAACX,KAAK,CAAC;QAC9B,IAAIS,IAAI,GAAG,CAAC,EAAE;UACZT,KAAK,IAAIS,IAAI;UACbX,WAAW,GAAGY,IAAI,CAACE,GAAG,CAACf,WAAW,CAAC1B,MAAM,EAAE2B,WAAW,GAAGW,IAAI,CAAC;UAC9D1D,oBAAoB,CAAC,CACnByC,iBAAiB,EACjB;YACE,GAAGE,qBAAqB;YACxBC,YAAY,EAAE,WAAW;YACzBC,aAAa,EAAEC,WAAW,CAACgB,KAAK,CAAC,CAAC,EAAEf,WAAW;UACjD,CAAC,CACF,CAAC;QACJ;QACAzC,MAAM,CAACK,OAAO,GAAGoD,qBAAqB,CAACP,KAAK,CAAC;MAC/C,CAAC,MAAM,IAAIR,UAAU,EAAE;QACrBK,MAAM,CAAC,CAAC;MACV,CAAC,MAAM;QACL5C,OAAO,CAAC,CAAC;MACX;IACF,CAAC;IAED,MAAMuD,QAAQ,GAAGA,CAAA,KAAM;MACrB,IAAI1D,MAAM,CAACK,OAAO,KAAK,IAAI,EAAE;QAC3BuC,aAAa,GAAG,CAAC;QACjB5C,MAAM,CAACK,OAAO,GAAGoD,qBAAqB,CAACP,KAAK,CAAC;MAC/C;IACF,CAAC;IAED,MAAM,IAAAS,oCAAiB,EACrB;MACE3F,MAAM;MACNuD,OAAO;MACPtD,SAAS;MACTuD,UAAU;MACVC,WAAW;MACXC,QAAQ;MACR7D;IACF,CAAC,EACD;MACE+F,OAAO,EAAGC,KAAK,IAAK;QAClBhB,eAAe,GAAG,IAAI;QACtBL,WAAW,IAAIqB,KAAK;QACpBH,QAAQ,CAAC,CAAC;MACZ,CAAC;MACDI,MAAM,EAAEA,CAAA,KAAM;QACZpB,UAAU,GAAG,IAAI;QACjBgB,QAAQ,CAAC,CAAC;MACZ,CAAC;MACD5F,OAAO,EAAGiG,GAAG,IAAK;QAChBjB,OAAO,GAAG,IAAI;QACd3C,OAAO,CAAC,CAAC;QACTrC,OAAO,YAAPA,OAAO,CAAGiG,GAAG,CAAC;QACdrE,oBAAoB,CAAC,EAAE,CAAC;MAC1B;IACF,CAAC,EACDkC,UAAU,CAACoC,MACb,CAAC;IAED,OAAO;MACLC,EAAE,EAAEvB,UAAU,IAAI,CAACI,OAAO;MAC1BoB,eAAe,EAAErB,eAAe;MAChCsB,OAAO,EAAE,CAACzB,UAAU,IAAI,CAACI;IAC3B,CAAC;EACH,CAAC,EACD,CAAC9E,MAAM,EAAEC,SAAS,EAAEJ,OAAO,EAAEC,OAAO,EAAEU,OAAO,EAAET,eAAe,EAAEoC,OAAO,CACzE,CAAC;EAED,OAAO;IACL7B,MAAM;IACN8F,OAAO,EAAE,EAAa;IACtBvF,QAAQ;IACRwF,SAAS;IACT7F,OAAO;IACP8C;EACF,CAAC;EAED,SAAS+C,SAASA,CAAA,EAAG;IACnB,KAAK9F,aAAa,CAAC,CAAC;EACtB;AACF","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["_react","require","_reactQuery","_sdkConsumer","_streamChatMessage","messageKey","m","role","content","trim","useTextChatStream","options","limit","headers","onError","revealMsPerChar","chatId","namespace","personaChatService","useSdkConsumer","data","sdkMessages","status","fetchNextPage","refetch","useInfiniteQuery","queryKey","queryFn","pageParam","messages","nextCursor","undefined","queryChatMessages","cursor","getNextPageParam","lastPage","initialPageParam","select","pages","flatMap","page","streamingMessages","setStreamingMessages","useState","completedMessages","setCompletedMessages","abortRef","useRef","rafRef","lastConfirmedRef","sendSeqRef","stopRaf","useCallback","current","cancelAnimationFrame","useEffect","_abortRef$current","abort","useMemo","converted","reverse","confirmedMessages","length","completedKeys","Set","map","confirmedShown","filter","has","chronological","send","message","chatConfig","attachments","metadata","_abortRef$current2","controller","AbortController","seq","userMsgId","Date","now","assistantMsgId","optimisticUserMsg","id","streamingAssistantMsg","streamStatus","streamingText","accumulated","revealedLen","streamDone","carry","lastFrameTime","receivedContent","errored","canSendChatMessage","settle","finalAssistantMsg","prev","frame","elapsedMs","step","Math","floor","min","slice","requestAnimationFrame","startRaf","streamChatMessage","onChunk","token","onDone","err","onCanSendChatMessage","canSend","signal","ok","producedContent","aborted","pending","fetchNext"],"sources":["../../../../src/hooks/useTextChat/useTextChatStream.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useInfiniteQuery } from '@tanstack/react-query';\nimport type { ChatMessage, ChatMessageAttachment } from '../../types';\nimport { useSdkConsumer } from '../../sdk-consumer';\nimport { streamChatMessage } from './streamChatMessage';\n\nexport type {\n StreamCallbacks,\n StreamChatMessageParams,\n} from './streamChatMessage';\n\n/**\n * A platform `ChatMessage` augmented with streaming metadata. The host renderer\n * uses `streamStatus`/`streamingText` to drive its typewriter; confirmed\n * (non-streamed) messages carry neither.\n */\nexport type StreamingChatMessage = ChatMessage & {\n streamingText?: string;\n streamStatus?: 'streaming' | 'settled';\n};\n\nexport interface UseTextChatStreamOptions {\n limit?: number;\n // Extra headers forwarded on every stream request — e.g. an `x-xsrf-token`\n // for the CSRF-protected persona-chat gateway.\n headers?: Record<string, string>;\n // Stream failures surfaced to the host (e.g. report to Sentry + toast).\n onError?: (err: Error) => void;\n // Milliseconds per character for the requestAnimationFrame reveal drip.\n // Default 16 (~62 chars/s).\n revealMsPerChar?: number;\n}\n\nexport interface SendStreamMessageParams {\n message: string;\n chatConfig?: object;\n attachments?: ChatMessageAttachment[];\n metadata?: object;\n}\n\n/**\n * Per-send outcome resolved by `send`. Reported at the transport level,\n * independent of the rAF reveal state — so a consumer can implement a\n * race-free, reveal-independent safe fallback.\n */\nexport type StreamSendResult = {\n ok: boolean; // stream completed successfully (reached onDone)\n producedContent: boolean; // at least one content chunk was received\n aborted: boolean; // the send was superseded/cancelled — not a real failure\n canSendChatMessage?: boolean; // set only when a frame reported it\n};\n\nconst messageKey = (m: StreamingChatMessage) =>\n `${m.role}::${(m.content ?? '').trim()}`;\n\n/**\n * Streaming counterpart to `useTextChat`. Sends a message over the SSE transport\n * and drips the accumulated reply into `streamingText` at a steady, time-paced\n * rate via requestAnimationFrame.\n *\n * Uses the same React Query key as `useTextChat` so mounting both hooks\n * does not double-fetch the message history.\n *\n * NOTE: uses `credentials: 'include'` + XSRF cookie auth — intended for\n * Wix-internal consumers where the persona-chat gateway is same-origin.\n */\nexport function useTextChatStream(options: UseTextChatStreamOptions = {}) {\n const { limit = 50, headers, onError, revealMsPerChar = 16 } = options;\n\n const { chatId, namespace, personaChatService } = useSdkConsumer();\n\n // Same query key as useTextChat — dedupes the history fetch when both are mounted.\n const {\n data: sdkMessages = [],\n status,\n fetchNextPage,\n refetch,\n } = useInfiniteQuery({\n queryKey: ['chat-messages', chatId, namespace],\n queryFn: async ({ pageParam }: { pageParam?: string }) => {\n if (!personaChatService) {\n return { messages: [], nextCursor: undefined };\n }\n return personaChatService.queryChatMessages({\n chatId,\n namespace,\n limit,\n cursor: pageParam,\n });\n },\n getNextPageParam: (lastPage) => lastPage.nextCursor,\n initialPageParam: undefined as string | undefined,\n select: (data) =>\n data.pages.flatMap((page) => page.messages as ChatMessage[]),\n });\n\n const [streamingMessages, setStreamingMessages] = useState<\n StreamingChatMessage[]\n >([]);\n const [completedMessages, setCompletedMessages] = useState<\n StreamingChatMessage[]\n >([]);\n const abortRef = useRef<AbortController | null>(null);\n const rafRef = useRef<number | null>(null);\n const lastConfirmedRef = useRef<StreamingChatMessage[]>([]);\n const sendSeqRef = useRef(0);\n\n const stopRaf = useCallback(() => {\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current);\n rafRef.current = null;\n }\n }, []);\n\n useEffect(() => {\n return () => {\n abortRef.current?.abort();\n stopRaf();\n };\n }, [stopRaf]);\n\n const messages = useMemo<StreamingChatMessage[]>(() => {\n const converted = [...sdkMessages].reverse() as StreamingChatMessage[];\n const confirmedMessages =\n converted.length > 0 ? converted : lastConfirmedRef.current;\n\n const completedKeys = new Set(completedMessages.map(messageKey));\n const confirmedShown = confirmedMessages.filter(\n (m) => !completedKeys.has(messageKey(m)),\n );\n const chronological = [\n ...confirmedShown,\n ...completedMessages,\n ...streamingMessages,\n ];\n return chronological.reverse();\n }, [sdkMessages, streamingMessages, completedMessages]);\n\n useEffect(() => {\n const converted = [...sdkMessages].reverse() as StreamingChatMessage[];\n if (converted.length > 0) {\n lastConfirmedRef.current = converted;\n }\n }, [sdkMessages]);\n\n const send = useCallback(\n async ({\n message,\n chatConfig,\n attachments,\n metadata,\n }: SendStreamMessageParams): Promise<StreamSendResult> => {\n abortRef.current?.abort();\n const controller = new AbortController();\n abortRef.current = controller;\n\n const seq = (sendSeqRef.current += 1);\n const userMsgId = `stream-user-${Date.now()}-${seq}`;\n const assistantMsgId = `stream-assistant-${Date.now()}-${seq}`;\n\n const optimisticUserMsg: StreamingChatMessage = {\n id: userMsgId,\n role: 'USER' as ChatMessage['role'],\n content: message,\n attachments: attachments as StreamingChatMessage['attachments'],\n };\n\n const streamingAssistantMsg: StreamingChatMessage = {\n id: assistantMsgId,\n role: 'ASSISTANT' as ChatMessage['role'],\n content: '',\n streamStatus: 'streaming',\n streamingText: '',\n };\n\n setStreamingMessages([optimisticUserMsg, streamingAssistantMsg]);\n\n let accumulated = '';\n let revealedLen = 0;\n let streamDone = false;\n let carry = 0;\n let lastFrameTime = 0;\n let receivedContent = false;\n let errored = false;\n let canSendChatMessage: boolean | undefined;\n\n const settle = () => {\n stopRaf();\n const finalAssistantMsg: StreamingChatMessage = {\n ...streamingAssistantMsg,\n content: accumulated,\n streamStatus: 'settled',\n streamingText: accumulated,\n };\n setCompletedMessages((prev) => [\n ...prev,\n optimisticUserMsg,\n finalAssistantMsg,\n ]);\n setStreamingMessages([]);\n void refetch();\n };\n\n const frame = (now: number) => {\n if (lastFrameTime === 0) {\n lastFrameTime = now;\n }\n const elapsedMs = now - lastFrameTime;\n lastFrameTime = now;\n\n if (revealedLen < accumulated.length) {\n carry += elapsedMs / revealMsPerChar;\n const step = Math.floor(carry);\n if (step > 0) {\n carry -= step;\n revealedLen = Math.min(accumulated.length, revealedLen + step);\n setStreamingMessages([\n optimisticUserMsg,\n {\n ...streamingAssistantMsg,\n streamStatus: 'streaming',\n streamingText: accumulated.slice(0, revealedLen),\n },\n ]);\n }\n rafRef.current = requestAnimationFrame(frame);\n } else if (streamDone) {\n settle();\n } else {\n stopRaf();\n }\n };\n\n const startRaf = () => {\n if (rafRef.current === null) {\n lastFrameTime = 0;\n rafRef.current = requestAnimationFrame(frame);\n }\n };\n\n await streamChatMessage(\n {\n chatId,\n message,\n namespace,\n chatConfig,\n attachments,\n metadata,\n headers,\n },\n {\n onChunk: (token) => {\n receivedContent = true;\n accumulated += token;\n startRaf();\n },\n onDone: () => {\n streamDone = true;\n startRaf();\n },\n onError: (err) => {\n errored = true;\n stopRaf();\n onError?.(err);\n setStreamingMessages([]);\n },\n onCanSendChatMessage: (canSend) => (canSendChatMessage = canSend),\n },\n controller.signal,\n );\n\n return {\n ok: streamDone && !errored,\n producedContent: receivedContent,\n aborted: !streamDone && !errored,\n canSendChatMessage,\n };\n },\n [chatId, namespace, headers, onError, refetch, revealMsPerChar, stopRaf],\n );\n\n return {\n status,\n pending: [] as never[],\n messages,\n fetchNext,\n refetch,\n send,\n };\n\n function fetchNext() {\n void fetchNextPage();\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["../../../src/conversation/types.ts"],"sourcesContent":["export type ConversationType = 'video' | 'audio';\n\nexport type ConversationParticipantRole = 'user' | 'agent';\n\nexport type ConversationVendor =\n | 'LIVEKIT'\n | 'DAILY'\n | 'HUME'\n | 'ELEVEN_LABS'\n | 'UNKNOWN_VENDOR';\n\nexport type AgentConnectionState =\n | 'joined' // agent is connected to the conversation\n | 'joining' // agent is connecting to the conversation\n | 'left' // agent left the conversation\n | 'idle'; // agent is not connected to the conversation\n\nexport type UserConnectionState =\n | 'joined' // user is connected to the conversation\n | 'joining' // user is connecting to the conversation\n | 'idle' // user is not connected to the conversation\n | 'leaving' // user is leaving the conversation\n | 'join-error'; // failed to join the conversation\n\nexport type ActivityState = 'idle' | 'speaking' | 'listening';\n\nexport type ConversationStatus =\n // Initial state\n | 'pending' // conversation is not created yet\n // States\n | 'created' // conversation was created\n | 'destroying' // destroying the conversation\n | 'destroyed' // conversation was destroyed\n | 'exceeded' // conversation limit is exceeded\n | 'inactivity-timeout' // conversation ended due to inactivity\n // Errors\n | 'voice-not-found' // failed to find a voice\n | 'initialization-error' // failed to create conversation\n | 'error'; // unknown error\n\nexport type Conversation = {\n id: string;\n url: string;\n limit?: number;\n type: ConversationType;\n};\n\nexport type ConversationTranscription = {\n message: string;\n source: ConversationParticipantRole;\n id: string;\n};\n\nexport type ConversationDevice = {\n enabled: boolean;\n deviceId: string;\n};\n\nexport type ConversationAudio = {\n // Range between `0.0` and `1.0`.\n volume: number;\n muted: boolean;\n};\n"],"mappings":"","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["../../../src/conversation/types.ts"],"sourcesContent":["export type ConversationType = 'video' | 'audio';\n\nexport type ConversationParticipantRole = 'user' | 'agent';\n\nexport type ConversationVendor =\n | 'LIVEKIT'\n | 'DAILY'\n | 'HUME'\n | 'ELEVEN_LABS'\n | 'UNKNOWN_VENDOR';\n\nexport type AgentConnectionState =\n | 'joined' // agent is connected to the conversation\n | 'joining' // agent is connecting to the conversation\n | 'left' // agent left the conversation\n | 'idle'; // agent is not connected to the conversation\n\nexport type UserConnectionState =\n | 'joined' // user is connected to the conversation\n | 'joining' // user is connecting to the conversation\n | 'idle' // user is not connected to the conversation\n | 'leaving' // user is leaving the conversation\n | 'join-error'; // failed to join the conversation\n\nexport type ActivityState = 'idle' | 'speaking' | 'listening';\n\nexport type ConversationStatus =\n // Initial state\n | 'pending' // conversation is not created yet\n // States\n | 'created' // conversation was created\n | 'destroying' // destroying the conversation\n | 'destroyed' // conversation was destroyed\n | 'exceeded' // conversation limit is exceeded\n | 'inactivity-timeout' // conversation ended due to inactivity\n | 'credit-exhausted' // the server ended the conversation because the Legend owner ran out of credit\n // Errors\n | 'voice-not-found' // failed to find a voice\n | 'initialization-error' // failed to create conversation\n | 'error'; // unknown error\n\nexport type Conversation = {\n id: string;\n url: string;\n limit?: number;\n type: ConversationType;\n};\n\nexport type ConversationTranscription = {\n message: string;\n source: ConversationParticipantRole;\n id: string;\n};\n\nexport type ConversationDevice = {\n enabled: boolean;\n deviceId: string;\n};\n\nexport type ConversationAudio = {\n // Range between `0.0` and `1.0`.\n volume: number;\n muted: boolean;\n};\n"],"mappings":"","ignoreList":[]}
|
|
@@ -13,7 +13,7 @@ import { useParticipantTrack, Source, getTrackStats, parseTrackStats } from '../
|
|
|
13
13
|
import { useEmitConversationEvent } from '../../useConversationEvents/useEmitConversationEvent';
|
|
14
14
|
import { useToolCallingRuntime } from '../../useTools/runtime/useToolCallingRuntime';
|
|
15
15
|
import { extractToolErrorMessage } from '../../useTools/utils/serialize';
|
|
16
|
-
import { checkIsTurnDetectionData, checkIsInactivityWarningData, checkIsInactivityTimeoutData, buildToolDefinitions, decodeDataPayload, findJoinedAgentParticipant, mergeTranscriptions, parseFunctionCallPayload, publishConversationDataMessage, safeStringify, shouldHandleParticipantConnected } from './utils';
|
|
16
|
+
import { checkIsTurnDetectionData, checkIsInactivityWarningData, checkIsInactivityTimeoutData, checkIsCreditExhaustedMessage, buildToolDefinitions, decodeDataPayload, findJoinedAgentParticipant, mergeTranscriptions, parseFunctionCallPayload, publishConversationDataMessage, safeStringify, shouldHandleParticipantConnected } from './utils';
|
|
17
17
|
import { ACOUSTIC_AGENT_HANGOVER_MS, ACOUSTIC_USER_HANGOVER_MS, ACOUSTIC_USER_THRESHOLD_RMS, EXECUTE_TOOL_RPC_METHOD, GET_TOOLS_RPC_METHOD } from './constants';
|
|
18
18
|
export function useConversation(_ref) {
|
|
19
19
|
var _conversation$data2;
|
|
@@ -81,6 +81,7 @@ export function useConversation(_ref) {
|
|
|
81
81
|
const setUserActivityState = useSetAtom(state.userActivityState);
|
|
82
82
|
const emitEvent = useEmitConversationEvent();
|
|
83
83
|
const inactivityTimeoutRef = useRef(false);
|
|
84
|
+
const creditExhaustedRef = useRef(false);
|
|
84
85
|
const acousticPhaseRef = useRef('idle');
|
|
85
86
|
const acousticT0Ref = useRef(null);
|
|
86
87
|
const latestTurnMetadataRef = useRef({});
|
|
@@ -346,11 +347,19 @@ export function useConversation(_ref) {
|
|
|
346
347
|
guard: checkIsInactivityTimeoutData,
|
|
347
348
|
handle: handleInactivityTimeoutEvent
|
|
348
349
|
}];
|
|
349
|
-
function handleDataReceivedEvent(payload) {
|
|
350
|
+
function handleDataReceivedEvent(payload, _participant, _kind, topic) {
|
|
350
351
|
const decoded = decodeDataPayload(payload);
|
|
351
352
|
if (decoded === null) {
|
|
352
353
|
return;
|
|
353
354
|
}
|
|
355
|
+
if (checkIsCreditExhaustedMessage(decoded, topic)) {
|
|
356
|
+
var _conversationRef$curr6;
|
|
357
|
+
creditExhaustedRef.current = true;
|
|
358
|
+
emitEvent('creditExhausted', {
|
|
359
|
+
conversationId: (_conversationRef$curr6 = conversationRef.current) == null ? void 0 : _conversationRef$curr6.id
|
|
360
|
+
});
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
354
363
|
for (const _ref2 of dataChannelHandlers) {
|
|
355
364
|
const guard = _ref2.guard;
|
|
356
365
|
const handle = _ref2.handle;
|
|
@@ -363,12 +372,12 @@ export function useConversation(_ref) {
|
|
|
363
372
|
}
|
|
364
373
|
}
|
|
365
374
|
function handleConnectedEvent() {
|
|
366
|
-
var _conversationRef$
|
|
375
|
+
var _conversationRef$curr7;
|
|
367
376
|
isConnectedRef.current = true;
|
|
368
377
|
setUserConnectionState('joined');
|
|
369
378
|
setAgentConnectionState('joining');
|
|
370
379
|
emitEvent('callStarted', {
|
|
371
|
-
conversationId: (_conversationRef$
|
|
380
|
+
conversationId: (_conversationRef$curr7 = conversationRef.current) == null ? void 0 : _conversationRef$curr7.id
|
|
372
381
|
});
|
|
373
382
|
}
|
|
374
383
|
async function handleEncryptionErrorEvent(error) {
|
|
@@ -391,6 +400,11 @@ export function useConversation(_ref) {
|
|
|
391
400
|
setConversationStatus('inactivity-timeout');
|
|
392
401
|
return;
|
|
393
402
|
}
|
|
403
|
+
if (creditExhaustedRef.current) {
|
|
404
|
+
creditExhaustedRef.current = false;
|
|
405
|
+
setConversationStatus('credit-exhausted');
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
394
408
|
switch (reason) {
|
|
395
409
|
case DisconnectReason.CLIENT_INITIATED:
|
|
396
410
|
break;
|
|
@@ -409,18 +423,18 @@ export function useConversation(_ref) {
|
|
|
409
423
|
}
|
|
410
424
|
}
|
|
411
425
|
function handleAgentJoin(participant) {
|
|
412
|
-
var _conversationRef$
|
|
426
|
+
var _conversationRef$curr8;
|
|
413
427
|
setAgentConnectionState('joined');
|
|
414
428
|
emitEvent('agentJoined', {
|
|
415
|
-
conversationId: (_conversationRef$
|
|
429
|
+
conversationId: (_conversationRef$curr8 = conversationRef.current) == null ? void 0 : _conversationRef$curr8.id,
|
|
416
430
|
participant
|
|
417
431
|
});
|
|
418
432
|
}
|
|
419
433
|
function handleParticipantDisconnectedEvent(participant) {
|
|
420
|
-
var _conversationRef$
|
|
434
|
+
var _conversationRef$curr9;
|
|
421
435
|
setAgentConnectionState('left');
|
|
422
436
|
emitEvent('agentLeft', {
|
|
423
|
-
conversationId: (_conversationRef$
|
|
437
|
+
conversationId: (_conversationRef$curr9 = conversationRef.current) == null ? void 0 : _conversationRef$curr9.id,
|
|
424
438
|
participant
|
|
425
439
|
});
|
|
426
440
|
}
|
|
@@ -429,13 +443,13 @@ export function useConversation(_ref) {
|
|
|
429
443
|
return;
|
|
430
444
|
}
|
|
431
445
|
try {
|
|
432
|
-
var _conversationRef$
|
|
446
|
+
var _conversationRef$curr0;
|
|
433
447
|
setUserConnectionState('leaving');
|
|
434
448
|
await (room == null ? void 0 : room.disconnect(true));
|
|
435
449
|
setConversationStatus('destroyed');
|
|
436
450
|
setJoinedAt(undefined);
|
|
437
451
|
emitEvent('callEnded', {
|
|
438
|
-
conversationId: (_conversationRef$
|
|
452
|
+
conversationId: (_conversationRef$curr0 = conversationRef.current) == null ? void 0 : _conversationRef$curr0.id
|
|
439
453
|
});
|
|
440
454
|
} catch (error) {
|
|
441
455
|
console.error('Failed to leave', error);
|
|
@@ -443,18 +457,22 @@ export function useConversation(_ref) {
|
|
|
443
457
|
}
|
|
444
458
|
}
|
|
445
459
|
async function handleExpire() {
|
|
446
|
-
var _conversationRef$
|
|
460
|
+
var _conversationRef$curr1, _conversationRef$curr10;
|
|
461
|
+
// The duration timer keeps running after the call ends.
|
|
462
|
+
if (conversationStatus === 'credit-exhausted') {
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
447
465
|
emitEvent('timeExceeded', {
|
|
448
|
-
conversationId: (_conversationRef$
|
|
449
|
-
limit: (_conversationRef$
|
|
466
|
+
conversationId: (_conversationRef$curr1 = conversationRef.current) == null ? void 0 : _conversationRef$curr1.id,
|
|
467
|
+
limit: (_conversationRef$curr10 = conversationRef.current) == null ? void 0 : _conversationRef$curr10.limit
|
|
450
468
|
});
|
|
451
469
|
await leave();
|
|
452
470
|
setConversationStatus('exceeded');
|
|
453
471
|
}
|
|
454
472
|
async function interrupt() {
|
|
455
|
-
var _conversationRef$
|
|
473
|
+
var _conversationRef$curr11;
|
|
456
474
|
emitEvent('interrupt', {
|
|
457
|
-
conversationId: (_conversationRef$
|
|
475
|
+
conversationId: (_conversationRef$curr11 = conversationRef.current) == null ? void 0 : _conversationRef$curr11.id
|
|
458
476
|
});
|
|
459
477
|
await publishConversationDataMessage(room, {}, 'interrupt');
|
|
460
478
|
}
|
|
@@ -464,7 +482,7 @@ export function useConversation(_ref) {
|
|
|
464
482
|
}, 'inactivity_dismiss');
|
|
465
483
|
}
|
|
466
484
|
async function send(message, attachments) {
|
|
467
|
-
var _conversationRef$
|
|
485
|
+
var _conversationRef$curr12;
|
|
468
486
|
if (attachments === void 0) {
|
|
469
487
|
attachments = [];
|
|
470
488
|
}
|
|
@@ -475,7 +493,7 @@ export function useConversation(_ref) {
|
|
|
475
493
|
}
|
|
476
494
|
}));
|
|
477
495
|
emitEvent('userSendMessage', {
|
|
478
|
-
conversationId: (_conversationRef$
|
|
496
|
+
conversationId: (_conversationRef$curr12 = conversationRef.current) == null ? void 0 : _conversationRef$curr12.id,
|
|
479
497
|
message
|
|
480
498
|
});
|
|
481
499
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useEffect","useRef","DisconnectReason","setLogLevel","ParticipantKind","LogLevel","invariant","useTimer","useLatest","useUpdateEffect","useEnsureRoom","useMediaDeviceSelect","useAtom","useAtomValue","useSetAtom","state","useSdkConsumer","useCreateConversation","useSpeechActivityDetector","useParticipantTrack","Source","getTrackStats","parseTrackStats","useEmitConversationEvent","useToolCallingRuntime","extractToolErrorMessage","checkIsTurnDetectionData","checkIsInactivityWarningData","checkIsInactivityTimeoutData","buildToolDefinitions","decodeDataPayload","findJoinedAgentParticipant","mergeTranscriptions","parseFunctionCallPayload","publishConversationDataMessage","safeStringify","shouldHandleParticipantConnected","ACOUSTIC_AGENT_HANGOVER_MS","ACOUSTIC_USER_HANGOVER_MS","ACOUSTIC_USER_THRESHOLD_RMS","EXECUTE_TOOL_RPC_METHOD","GET_TOOLS_RPC_METHOD","useConversation","_ref","_conversation$data2","_ref$autoJoin","autoJoin","type","config","_ref$startWithMicroph","startWithMicrophone","_ref$startWithCamera","startWithCamera","firstConversation","lastConversationTopic","silent","conversation","room","speaker","_useAtom","microphone","setMicrophone","_useAtom2","camera","setCamera","_useSdkConsumer","_useSdkConsumer$tools","tools","toolsRegistry","toolRuntime","toolsRegistryRef","conversationRef","data","toolRuntimeRef","_useAtom3","conversationStatus","setConversationStatus","_useAtom4","userConnectionState","setUserConnectionState","_useAtom5","joinedAt","setJoinedAt","_useMediaDeviceSelect","kind","setMicrophoneDeviceId","setActiveMediaDevice","_useMediaDeviceSelect2","setSpeakerDeviceId","_useMediaDeviceSelect3","requestPermissions","enabled","setCameraDeviceId","setTranscriptions","transcriptions","_useAtom6","agentConnectionState","setAgentConnectionState","setAgentActivityState","agentActivityState","setUserActivityState","userActivityState","emitEvent","inactivityTimeoutRef","acousticPhaseRef","acousticT0Ref","latestTurnMetadataRef","isConnectedRef","userCumulativeTrackStatsRef","undefined","agentCumulativeTrackStatsRef","userMicPublication","source","Microphone","agentMicPublication","timer","autoStart","onExpire","handleExpire","expiryTimestamp","Date","registerRoomEvents","unregisterRoomEvents","deviceId","localParticipant","setMicrophoneEnabled","setCameraEnabled","resolution","width","height","join","_conversation$data","limit","restart","getTime","_conversation$data3","url","URL","accessToken","searchParams","get","connect","remoteParticipant","handleAgentJoin","enableMediaDevices","error","console","handleTranscriptionReceivedEvent","segments","participant","map","s","id","message","text","AGENT","old","handleTurnDetectionEvent","_conversationRef$curr","conversationId","current","participantKind","eventState","turnDetectionStrategy","sequence","speechId","handleAcousticUserOnset","handleAcousticUserOffset","timestampMs","handleAcousticAgentOnset","_conversationRef$curr2","latencyMs","emitConversationTurnLatency","clientAcousticLatencyMs","_conversationRef$curr3","_await$Promise$all","Promise","all","userReport","agentReport","userStats","agentStats","cumulativeTrackStats","rttMs","roundTripTimeMs","jitterBufferDelayMs","userPacketsLost","packetsLost","agentPacketsLost","handleAcousticAgentOffset","onSpeechStart","onSpeechEnd","thresholdRms","hangoverMs","handleInactivityWarningEvent","_conversationRef$curr4","gracePeriodSec","grace_period_sec","handleInactivityTimeoutEvent","_data","_conversationRef$curr5","handleGetToolsRpc","JSON","stringify","handleExecuteToolRpc","call","payload","functionCallId","result","_await$toolRuntimeRef","executeToolCalls","dataChannelHandlers","guard","handle","handleDataReceivedEvent","decoded","_ref2","resolve","catch","handleConnectedEvent","_conversationRef$curr6","handleEncryptionErrorEvent","handleDisconnectedEvent","reason","CLIENT_INITIATED","ROOM_CLOSED","handleParticipantConnectedEvent","_conversationRef$curr7","handleParticipantDisconnectedEvent","_conversationRef$curr8","leave","_conversationRef$curr9","disconnect","_conversationRef$curr0","_conversationRef$curr1","interrupt","_conversationRef$curr10","dismissInactivity","send","attachments","_conversationRef$curr11","sendText","topic","attributes","on","unregisterRpcMethod","registerRpcMethod","off","status"],"sources":["../../../../../src/hooks/useConversation/livekit/useConversation.ts"],"sourcesContent":["import { useEffect, useRef } from 'react';\nimport {\n DisconnectReason,\n Participant,\n setLogLevel,\n ParticipantKind,\n RemoteParticipant,\n TranscriptionSegment,\n LogLevel,\n type RpcInvocationData,\n} from 'livekit-client';\nimport invariant from 'invariant';\nimport { useTimer } from 'react-timer-hook';\nimport { useLatest, useUpdateEffect } from 'react-use';\nimport { useEnsureRoom, useMediaDeviceSelect } from '@livekit/components-react';\nimport { useAtom, useAtomValue, useSetAtom } from 'jotai';\nimport {\n Conversation,\n state,\n type ConversationTranscription,\n} from '../../../conversation';\nimport type {\n UseConversationResult,\n UseConversationOptions,\n Attachment,\n} from '../types';\nimport type { FunctionCallResult } from '../../../types/service';\nimport { useSdkConsumer } from '../../../sdk-consumer';\nimport type {\n InactivityWarningData,\n InactivityTimeoutData,\n TurnDetectionData,\n} from './types';\nimport { useCreateConversation } from '../../useCreateConversation';\nimport { useSpeechActivityDetector } from '../../useSpeechActivityDetector';\nimport {\n useParticipantTrack,\n Source,\n getTrackStats,\n parseTrackStats,\n type CumulativeTrackStats,\n} from '../../useParticipantTrack';\n\nimport { useEmitConversationEvent } from '../../useConversationEvents/useEmitConversationEvent';\nimport { useToolCallingRuntime } from '../../useTools/runtime/useToolCallingRuntime';\nimport { extractToolErrorMessage } from '../../useTools/utils/serialize';\nimport {\n checkIsTurnDetectionData,\n checkIsInactivityWarningData,\n checkIsInactivityTimeoutData,\n buildToolDefinitions,\n decodeDataPayload,\n findJoinedAgentParticipant,\n mergeTranscriptions,\n parseFunctionCallPayload,\n publishConversationDataMessage,\n safeStringify,\n shouldHandleParticipantConnected,\n} from './utils';\nimport {\n ACOUSTIC_AGENT_HANGOVER_MS,\n ACOUSTIC_USER_HANGOVER_MS,\n ACOUSTIC_USER_THRESHOLD_RMS,\n EXECUTE_TOOL_RPC_METHOD,\n GET_TOOLS_RPC_METHOD,\n} from './constants';\n\nexport function useConversation({\n autoJoin = true,\n type,\n config,\n startWithMicrophone = false,\n startWithCamera = false,\n firstConversation,\n lastConversationTopic,\n}: UseConversationOptions): UseConversationResult {\n setLogLevel(LogLevel.silent);\n\n const conversation = useCreateConversation({\n type,\n config,\n firstConversation,\n lastConversationTopic,\n });\n const room = useEnsureRoom();\n const speaker = useAtomValue(state.speaker);\n const [microphone, setMicrophone] = useAtom(state.microphone);\n const [camera, setCamera] = useAtom(state.camera);\n const { tools: toolsRegistry = {} } = useSdkConsumer();\n const toolRuntime = useToolCallingRuntime();\n const toolsRegistryRef = useLatest(toolsRegistry);\n\n // for use in register/unregister room events\n const conversationRef = useLatest<Conversation | undefined>(\n conversation.data,\n );\n const toolRuntimeRef = useLatest(toolRuntime);\n\n const [conversationStatus, setConversationStatus] = useAtom(\n state.conversationStatus,\n );\n\n const [userConnectionState, setUserConnectionState] = useAtom(\n state.userConnectionState,\n );\n\n const [joinedAt, setJoinedAt] = useAtom(state.joinedAt);\n\n const { setActiveMediaDevice: setMicrophoneDeviceId } = useMediaDeviceSelect({\n kind: 'audioinput',\n });\n const { setActiveMediaDevice: setSpeakerDeviceId } = useMediaDeviceSelect({\n kind: 'audiooutput',\n });\n const { setActiveMediaDevice: setCameraDeviceId } = useMediaDeviceSelect({\n kind: 'videoinput',\n requestPermissions: camera.enabled,\n });\n\n const setTranscriptions = useSetAtom(state.transcriptions);\n const [agentConnectionState, setAgentConnectionState] = useAtom(\n state.agentConnectionState,\n );\n const setAgentActivityState = useSetAtom(state.agentActivityState);\n const setUserActivityState = useSetAtom(state.userActivityState);\n const emitEvent = useEmitConversationEvent();\n\n const inactivityTimeoutRef = useRef(false);\n const acousticPhaseRef = useRef<'idle' | 'waitingForAgent' | 'busy'>('idle');\n const acousticT0Ref = useRef<number | null>(null);\n const latestTurnMetadataRef = useRef<{\n turnDetectionStrategy?: string;\n sequence?: number;\n speechId?: string;\n }>({});\n const isConnectedRef = useRef(false);\n const userCumulativeTrackStatsRef = useRef<CumulativeTrackStats | undefined>(\n undefined,\n );\n const agentCumulativeTrackStatsRef = useRef<CumulativeTrackStats | undefined>(\n undefined,\n );\n\n const userMicPublication = useParticipantTrack({\n type: 'user',\n source: Source.Microphone,\n });\n const agentMicPublication = useParticipantTrack({\n type: 'agent',\n source: Source.Microphone,\n });\n\n const timer = useTimer({\n autoStart: false,\n onExpire: handleExpire,\n expiryTimestamp: new Date(),\n });\n\n useEffect(() => {\n if (!room) {\n return;\n }\n registerRoomEvents();\n\n return () => {\n unregisterRoomEvents();\n };\n }, [room]);\n\n useUpdateEffect(() => {\n setMicrophoneDeviceId(microphone.deviceId);\n }, [microphone.deviceId]);\n\n useUpdateEffect(() => {\n setSpeakerDeviceId(speaker.deviceId);\n }, [speaker.deviceId]);\n\n useUpdateEffect(() => {\n setCameraDeviceId(camera.deviceId);\n }, [camera.deviceId]);\n\n useUpdateEffect(() => {\n if (agentConnectionState !== 'joined') {\n return;\n }\n room.localParticipant.setMicrophoneEnabled(microphone.enabled);\n }, [microphone.enabled, agentConnectionState]);\n\n useUpdateEffect(() => {\n if (agentConnectionState !== 'joined') {\n return;\n }\n room.localParticipant.setCameraEnabled(camera.enabled, {\n resolution: { width: 1920, height: 1080 },\n });\n }, [camera.enabled, agentConnectionState]);\n\n useEffect(() => {\n if (!autoJoin) {\n return;\n }\n\n if (conversationStatus === 'created') {\n void join();\n }\n }, [conversationStatus, autoJoin]);\n\n useEffect(() => {\n if (!joinedAt || conversation.data?.limit === undefined) {\n return;\n }\n\n timer.restart(new Date(joinedAt.getTime() + conversation.data!.limit!));\n }, [joinedAt, conversation.data?.limit]);\n\n async function join() {\n invariant(userConnectionState === 'idle', 'Already joined');\n invariant(conversation.data, 'Conversation is not ready');\n const url = new URL(conversation?.data?.url || '');\n const accessToken = url.searchParams.get('token');\n try {\n setUserConnectionState('joining');\n await room?.connect(conversation.data.url, accessToken!, {});\n\n // sometimes the agent is already joined before the user joins the conversation\n const remoteParticipant = findJoinedAgentParticipant(room, type);\n if (remoteParticipant && agentConnectionState !== 'joined') {\n handleAgentJoin(remoteParticipant);\n }\n\n enableMediaDevices();\n } catch (error) {\n console.error('Failed to join', error);\n setUserConnectionState('join-error');\n }\n }\n\n function enableMediaDevices() {\n if (startWithMicrophone) {\n setMicrophone({ ...microphone, enabled: true });\n }\n if (startWithCamera && type === 'video') {\n setCamera({ ...camera, enabled: true });\n }\n }\n\n function handleTranscriptionReceivedEvent(\n segments: TranscriptionSegment[],\n participant?: Participant,\n ) {\n const transcriptions: ConversationTranscription[] = segments.map((s) => ({\n id: s.id,\n message: s.text,\n source: participant?.kind === ParticipantKind.AGENT ? 'agent' : 'user',\n }));\n\n setTranscriptions((old) => mergeTranscriptions(transcriptions, old));\n }\n\n function handleTurnDetectionEvent(data: TurnDetectionData) {\n const conversationId = conversationRef.current?.id;\n const { participantKind, state: eventState } = data;\n switch (participantKind) {\n case 'STANDARD':\n if (eventState === 'listening') {\n latestTurnMetadataRef.current = {\n turnDetectionStrategy: data.turnDetectionStrategy,\n sequence: data.sequence,\n speechId: data.speechId,\n };\n }\n emitEvent(\n eventState === 'speaking' ? 'userSpeakStart' : 'userSpeakStop',\n { conversationId: conversationId! },\n );\n setUserActivityState(eventState);\n break;\n case 'AGENT':\n if (data.speechId) {\n latestTurnMetadataRef.current = {\n ...latestTurnMetadataRef.current,\n speechId: data.speechId,\n };\n }\n emitEvent(\n eventState === 'speaking' ? 'agentSpeakStart' : 'agentSpeakStop',\n { conversationId: conversationId! },\n );\n setAgentActivityState(eventState);\n break;\n }\n }\n\n function handleAcousticUserOnset() {\n if (!isConnectedRef.current) {\n return;\n }\n if (acousticPhaseRef.current === 'waitingForAgent') {\n acousticPhaseRef.current = 'idle';\n acousticT0Ref.current = null;\n }\n }\n\n function handleAcousticUserOffset(timestampMs: number) {\n if (!isConnectedRef.current || acousticPhaseRef.current !== 'idle') {\n return;\n }\n acousticT0Ref.current = timestampMs - ACOUSTIC_USER_HANGOVER_MS;\n acousticPhaseRef.current = 'waitingForAgent';\n }\n\n function handleAcousticAgentOnset(timestampMs: number) {\n if (\n !isConnectedRef.current ||\n acousticPhaseRef.current !== 'waitingForAgent' ||\n acousticT0Ref.current == null\n ) {\n return;\n }\n\n const latencyMs = timestampMs - acousticT0Ref.current;\n acousticT0Ref.current = null;\n acousticPhaseRef.current = 'busy';\n\n if (latencyMs < 0 || latencyMs > 15000) {\n return;\n }\n\n emitEvent('responseLatency', {\n conversationId: conversationRef.current?.id!,\n latencyMs,\n turnDetectionStrategy:\n latestTurnMetadataRef.current.turnDetectionStrategy!,\n sequence: latestTurnMetadataRef.current.sequence,\n speechId: latestTurnMetadataRef.current.speechId,\n });\n\n void emitConversationTurnLatency(latencyMs);\n }\n\n async function emitConversationTurnLatency(clientAcousticLatencyMs: number) {\n const [userReport, agentReport] = await Promise.all([\n getTrackStats(userMicPublication),\n getTrackStats(agentMicPublication),\n ]);\n const userStats = parseTrackStats(\n userReport,\n userCumulativeTrackStatsRef.current,\n );\n const agentStats = parseTrackStats(\n agentReport,\n agentCumulativeTrackStatsRef.current,\n );\n userCumulativeTrackStatsRef.current = userStats.cumulativeTrackStats;\n agentCumulativeTrackStatsRef.current = agentStats.cumulativeTrackStats;\n\n emitEvent('conversationTurnLatency', {\n conversationId: conversationRef.current?.id!,\n speechId: latestTurnMetadataRef.current.speechId,\n sequence: latestTurnMetadataRef.current.sequence,\n clientAcousticLatencyMs,\n rttMs: userStats.roundTripTimeMs,\n jitterBufferDelayMs: agentStats.jitterBufferDelayMs,\n userPacketsLost: userStats.packetsLost,\n agentPacketsLost: agentStats.packetsLost,\n });\n }\n\n function handleAcousticAgentOffset() {\n acousticPhaseRef.current = 'idle';\n }\n\n useSpeechActivityDetector({\n source: 'user',\n onSpeechStart: handleAcousticUserOnset,\n onSpeechEnd: handleAcousticUserOffset,\n thresholdRms: ACOUSTIC_USER_THRESHOLD_RMS,\n hangoverMs: ACOUSTIC_USER_HANGOVER_MS,\n });\n useSpeechActivityDetector({\n source: 'agent',\n onSpeechStart: handleAcousticAgentOnset,\n onSpeechEnd: handleAcousticAgentOffset,\n hangoverMs: ACOUSTIC_AGENT_HANGOVER_MS,\n });\n\n function handleInactivityWarningEvent(data: InactivityWarningData) {\n emitEvent('inactivityWarning', {\n conversationId: conversationRef.current?.id!,\n gracePeriodSec: data.grace_period_sec,\n });\n }\n\n function handleInactivityTimeoutEvent(_data: InactivityTimeoutData) {\n inactivityTimeoutRef.current = true;\n emitEvent('inactivityTimeout', {\n conversationId: conversationRef.current?.id!,\n });\n }\n\n async function handleGetToolsRpc() {\n return JSON.stringify(buildToolDefinitions(toolsRegistryRef.current));\n }\n\n async function handleExecuteToolRpc(data: RpcInvocationData) {\n const call = parseFunctionCallPayload(data.payload);\n if (!call) {\n return JSON.stringify({\n functionCallId: '',\n result: '',\n error: 'Malformed function call payload.',\n } satisfies FunctionCallResult);\n }\n try {\n const [result] = await toolRuntimeRef.current.executeToolCalls([call]);\n return JSON.stringify(result);\n } catch (error) {\n return JSON.stringify({\n functionCallId: call.functionCallId,\n result: '',\n error: extractToolErrorMessage(error),\n } satisfies FunctionCallResult);\n }\n }\n\n const dataChannelHandlers: {\n guard: (data: unknown) => boolean;\n handle: (data: unknown) => void | Promise<void>;\n }[] = [\n {\n guard: checkIsTurnDetectionData,\n handle: handleTurnDetectionEvent as (data: unknown) => void,\n },\n {\n guard: checkIsInactivityWarningData,\n handle: handleInactivityWarningEvent as (data: unknown) => void,\n },\n {\n guard: checkIsInactivityTimeoutData,\n handle: handleInactivityTimeoutEvent as (data: unknown) => void,\n },\n ];\n\n function handleDataReceivedEvent(payload: Uint8Array) {\n const decoded = decodeDataPayload(payload);\n if (decoded === null) {\n return;\n }\n for (const { guard, handle } of dataChannelHandlers) {\n if (guard(decoded)) {\n void Promise.resolve(handle(decoded)).catch((error) => {\n console.error('Failed to handle data channel payload', error);\n });\n return;\n }\n }\n }\n\n function handleConnectedEvent() {\n isConnectedRef.current = true;\n setUserConnectionState('joined');\n setAgentConnectionState('joining');\n emitEvent('callStarted', {\n conversationId: conversationRef.current?.id!,\n });\n }\n\n async function handleEncryptionErrorEvent(error: Error) {\n console.error('Encryption error', error);\n setConversationStatus('error');\n }\n\n function handleDisconnectedEvent(reason?: DisconnectReason) {\n isConnectedRef.current = false;\n acousticPhaseRef.current = 'idle';\n acousticT0Ref.current = null;\n latestTurnMetadataRef.current = {};\n userCumulativeTrackStatsRef.current = undefined;\n agentCumulativeTrackStatsRef.current = undefined;\n setAgentActivityState('idle');\n setAgentConnectionState('idle');\n setUserActivityState('idle');\n setUserConnectionState('idle');\n\n if (inactivityTimeoutRef.current) {\n inactivityTimeoutRef.current = false;\n setConversationStatus('inactivity-timeout');\n return;\n }\n\n switch (reason) {\n case DisconnectReason.CLIENT_INITIATED:\n break;\n case DisconnectReason.ROOM_CLOSED:\n setConversationStatus('destroyed');\n break;\n default:\n console.error('Conversation disconnected with reason', reason);\n setConversationStatus('error');\n break;\n }\n }\n\n function handleParticipantConnectedEvent(participant: RemoteParticipant) {\n if (shouldHandleParticipantConnected(participant, type)) {\n handleAgentJoin(participant);\n }\n }\n\n function handleAgentJoin(participant: RemoteParticipant) {\n setAgentConnectionState('joined');\n emitEvent('agentJoined', {\n conversationId: conversationRef.current?.id!,\n participant,\n });\n }\n\n function handleParticipantDisconnectedEvent(participant: RemoteParticipant) {\n setAgentConnectionState('left');\n emitEvent('agentLeft', {\n conversationId: conversationRef.current?.id!,\n participant,\n });\n }\n\n async function leave() {\n if (userConnectionState !== 'joined' && userConnectionState !== 'joining') {\n return;\n }\n\n try {\n setUserConnectionState('leaving');\n await room?.disconnect(true);\n setConversationStatus('destroyed');\n setJoinedAt(undefined);\n emitEvent('callEnded', {\n conversationId: conversationRef.current?.id!,\n });\n } catch (error) {\n console.error('Failed to leave', error);\n setConversationStatus('error');\n }\n }\n\n async function handleExpire() {\n emitEvent('timeExceeded', {\n conversationId: conversationRef.current?.id!,\n limit: conversationRef.current?.limit!,\n });\n await leave();\n setConversationStatus('exceeded');\n }\n\n async function interrupt() {\n emitEvent('interrupt', {\n conversationId: conversationRef.current?.id!,\n });\n\n await publishConversationDataMessage(room, {}, 'interrupt');\n }\n\n async function dismissInactivity() {\n await publishConversationDataMessage(\n room,\n { type: 'inactivity_dismiss' },\n 'inactivity_dismiss',\n );\n }\n\n async function send(message: string, attachments: Attachment[] = []) {\n await room?.localParticipant.sendText(message, {\n topic: 'lk.chat',\n attributes: {\n attachments: safeStringify(attachments),\n },\n });\n emitEvent('userSendMessage', {\n conversationId: conversationRef.current?.id!,\n message,\n });\n }\n\n function registerRoomEvents() {\n room\n .on('connected', handleConnectedEvent)\n .on('encryptionError', handleEncryptionErrorEvent)\n .on('disconnected', handleDisconnectedEvent)\n .on('transcriptionReceived', handleTranscriptionReceivedEvent)\n .on('participantConnected', handleParticipantConnectedEvent)\n .on('participantDisconnected', handleParticipantDisconnectedEvent)\n .on('dataReceived', handleDataReceivedEvent);\n room.unregisterRpcMethod(GET_TOOLS_RPC_METHOD);\n room.unregisterRpcMethod(EXECUTE_TOOL_RPC_METHOD);\n room.registerRpcMethod(GET_TOOLS_RPC_METHOD, handleGetToolsRpc);\n room.registerRpcMethod(EXECUTE_TOOL_RPC_METHOD, handleExecuteToolRpc);\n }\n\n function unregisterRoomEvents() {\n room.unregisterRpcMethod(GET_TOOLS_RPC_METHOD);\n room.unregisterRpcMethod(EXECUTE_TOOL_RPC_METHOD);\n room.off('connected', handleConnectedEvent);\n room.off('encryptionError', handleEncryptionErrorEvent);\n room.off('disconnected', handleDisconnectedEvent);\n room.off('transcriptionReceived', handleTranscriptionReceivedEvent);\n room.off('participantConnected', handleParticipantConnectedEvent);\n room.off('participantDisconnected', handleParticipantDisconnectedEvent);\n room.off('dataReceived', handleDataReceivedEvent);\n }\n\n return {\n status: conversationStatus,\n conversation: conversation.data,\n join,\n send,\n interrupt,\n dismissInactivity,\n leave,\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["useEffect","useRef","DisconnectReason","setLogLevel","ParticipantKind","LogLevel","invariant","useTimer","useLatest","useUpdateEffect","useEnsureRoom","useMediaDeviceSelect","useAtom","useAtomValue","useSetAtom","state","useSdkConsumer","useCreateConversation","useSpeechActivityDetector","useParticipantTrack","Source","getTrackStats","parseTrackStats","useEmitConversationEvent","useToolCallingRuntime","extractToolErrorMessage","checkIsTurnDetectionData","checkIsInactivityWarningData","checkIsInactivityTimeoutData","checkIsCreditExhaustedMessage","buildToolDefinitions","decodeDataPayload","findJoinedAgentParticipant","mergeTranscriptions","parseFunctionCallPayload","publishConversationDataMessage","safeStringify","shouldHandleParticipantConnected","ACOUSTIC_AGENT_HANGOVER_MS","ACOUSTIC_USER_HANGOVER_MS","ACOUSTIC_USER_THRESHOLD_RMS","EXECUTE_TOOL_RPC_METHOD","GET_TOOLS_RPC_METHOD","useConversation","_ref","_conversation$data2","_ref$autoJoin","autoJoin","type","config","_ref$startWithMicroph","startWithMicrophone","_ref$startWithCamera","startWithCamera","firstConversation","lastConversationTopic","silent","conversation","room","speaker","_useAtom","microphone","setMicrophone","_useAtom2","camera","setCamera","_useSdkConsumer","_useSdkConsumer$tools","tools","toolsRegistry","toolRuntime","toolsRegistryRef","conversationRef","data","toolRuntimeRef","_useAtom3","conversationStatus","setConversationStatus","_useAtom4","userConnectionState","setUserConnectionState","_useAtom5","joinedAt","setJoinedAt","_useMediaDeviceSelect","kind","setMicrophoneDeviceId","setActiveMediaDevice","_useMediaDeviceSelect2","setSpeakerDeviceId","_useMediaDeviceSelect3","requestPermissions","enabled","setCameraDeviceId","setTranscriptions","transcriptions","_useAtom6","agentConnectionState","setAgentConnectionState","setAgentActivityState","agentActivityState","setUserActivityState","userActivityState","emitEvent","inactivityTimeoutRef","creditExhaustedRef","acousticPhaseRef","acousticT0Ref","latestTurnMetadataRef","isConnectedRef","userCumulativeTrackStatsRef","undefined","agentCumulativeTrackStatsRef","userMicPublication","source","Microphone","agentMicPublication","timer","autoStart","onExpire","handleExpire","expiryTimestamp","Date","registerRoomEvents","unregisterRoomEvents","deviceId","localParticipant","setMicrophoneEnabled","setCameraEnabled","resolution","width","height","join","_conversation$data","limit","restart","getTime","_conversation$data3","url","URL","accessToken","searchParams","get","connect","remoteParticipant","handleAgentJoin","enableMediaDevices","error","console","handleTranscriptionReceivedEvent","segments","participant","map","s","id","message","text","AGENT","old","handleTurnDetectionEvent","_conversationRef$curr","conversationId","current","participantKind","eventState","turnDetectionStrategy","sequence","speechId","handleAcousticUserOnset","handleAcousticUserOffset","timestampMs","handleAcousticAgentOnset","_conversationRef$curr2","latencyMs","emitConversationTurnLatency","clientAcousticLatencyMs","_conversationRef$curr3","_await$Promise$all","Promise","all","userReport","agentReport","userStats","agentStats","cumulativeTrackStats","rttMs","roundTripTimeMs","jitterBufferDelayMs","userPacketsLost","packetsLost","agentPacketsLost","handleAcousticAgentOffset","onSpeechStart","onSpeechEnd","thresholdRms","hangoverMs","handleInactivityWarningEvent","_conversationRef$curr4","gracePeriodSec","grace_period_sec","handleInactivityTimeoutEvent","_data","_conversationRef$curr5","handleGetToolsRpc","JSON","stringify","handleExecuteToolRpc","call","payload","functionCallId","result","_await$toolRuntimeRef","executeToolCalls","dataChannelHandlers","guard","handle","handleDataReceivedEvent","_participant","_kind","topic","decoded","_conversationRef$curr6","_ref2","resolve","catch","handleConnectedEvent","_conversationRef$curr7","handleEncryptionErrorEvent","handleDisconnectedEvent","reason","CLIENT_INITIATED","ROOM_CLOSED","handleParticipantConnectedEvent","_conversationRef$curr8","handleParticipantDisconnectedEvent","_conversationRef$curr9","leave","_conversationRef$curr0","disconnect","_conversationRef$curr1","_conversationRef$curr10","interrupt","_conversationRef$curr11","dismissInactivity","send","attachments","_conversationRef$curr12","sendText","attributes","on","unregisterRpcMethod","registerRpcMethod","off","status"],"sources":["../../../../../src/hooks/useConversation/livekit/useConversation.ts"],"sourcesContent":["import { useEffect, useRef } from 'react';\nimport {\n DisconnectReason,\n Participant,\n setLogLevel,\n ParticipantKind,\n RemoteParticipant,\n TranscriptionSegment,\n LogLevel,\n type RpcInvocationData,\n} from 'livekit-client';\nimport invariant from 'invariant';\nimport { useTimer } from 'react-timer-hook';\nimport { useLatest, useUpdateEffect } from 'react-use';\nimport { useEnsureRoom, useMediaDeviceSelect } from '@livekit/components-react';\nimport { useAtom, useAtomValue, useSetAtom } from 'jotai';\nimport {\n Conversation,\n state,\n type ConversationTranscription,\n} from '../../../conversation';\nimport type {\n UseConversationResult,\n UseConversationOptions,\n Attachment,\n} from '../types';\nimport type { FunctionCallResult } from '../../../types/service';\nimport { useSdkConsumer } from '../../../sdk-consumer';\nimport type {\n InactivityWarningData,\n InactivityTimeoutData,\n TurnDetectionData,\n} from './types';\nimport { useCreateConversation } from '../../useCreateConversation';\nimport { useSpeechActivityDetector } from '../../useSpeechActivityDetector';\nimport {\n useParticipantTrack,\n Source,\n getTrackStats,\n parseTrackStats,\n type CumulativeTrackStats,\n} from '../../useParticipantTrack';\n\nimport { useEmitConversationEvent } from '../../useConversationEvents/useEmitConversationEvent';\nimport { useToolCallingRuntime } from '../../useTools/runtime/useToolCallingRuntime';\nimport { extractToolErrorMessage } from '../../useTools/utils/serialize';\nimport {\n checkIsTurnDetectionData,\n checkIsInactivityWarningData,\n checkIsInactivityTimeoutData,\n checkIsCreditExhaustedMessage,\n buildToolDefinitions,\n decodeDataPayload,\n findJoinedAgentParticipant,\n mergeTranscriptions,\n parseFunctionCallPayload,\n publishConversationDataMessage,\n safeStringify,\n shouldHandleParticipantConnected,\n} from './utils';\nimport {\n ACOUSTIC_AGENT_HANGOVER_MS,\n ACOUSTIC_USER_HANGOVER_MS,\n ACOUSTIC_USER_THRESHOLD_RMS,\n EXECUTE_TOOL_RPC_METHOD,\n GET_TOOLS_RPC_METHOD,\n} from './constants';\n\nexport function useConversation({\n autoJoin = true,\n type,\n config,\n startWithMicrophone = false,\n startWithCamera = false,\n firstConversation,\n lastConversationTopic,\n}: UseConversationOptions): UseConversationResult {\n setLogLevel(LogLevel.silent);\n\n const conversation = useCreateConversation({\n type,\n config,\n firstConversation,\n lastConversationTopic,\n });\n const room = useEnsureRoom();\n const speaker = useAtomValue(state.speaker);\n const [microphone, setMicrophone] = useAtom(state.microphone);\n const [camera, setCamera] = useAtom(state.camera);\n const { tools: toolsRegistry = {} } = useSdkConsumer();\n const toolRuntime = useToolCallingRuntime();\n const toolsRegistryRef = useLatest(toolsRegistry);\n\n // for use in register/unregister room events\n const conversationRef = useLatest<Conversation | undefined>(\n conversation.data,\n );\n const toolRuntimeRef = useLatest(toolRuntime);\n\n const [conversationStatus, setConversationStatus] = useAtom(\n state.conversationStatus,\n );\n\n const [userConnectionState, setUserConnectionState] = useAtom(\n state.userConnectionState,\n );\n\n const [joinedAt, setJoinedAt] = useAtom(state.joinedAt);\n\n const { setActiveMediaDevice: setMicrophoneDeviceId } = useMediaDeviceSelect({\n kind: 'audioinput',\n });\n const { setActiveMediaDevice: setSpeakerDeviceId } = useMediaDeviceSelect({\n kind: 'audiooutput',\n });\n const { setActiveMediaDevice: setCameraDeviceId } = useMediaDeviceSelect({\n kind: 'videoinput',\n requestPermissions: camera.enabled,\n });\n\n const setTranscriptions = useSetAtom(state.transcriptions);\n const [agentConnectionState, setAgentConnectionState] = useAtom(\n state.agentConnectionState,\n );\n const setAgentActivityState = useSetAtom(state.agentActivityState);\n const setUserActivityState = useSetAtom(state.userActivityState);\n const emitEvent = useEmitConversationEvent();\n\n const inactivityTimeoutRef = useRef(false);\n const creditExhaustedRef = useRef(false);\n const acousticPhaseRef = useRef<'idle' | 'waitingForAgent' | 'busy'>('idle');\n const acousticT0Ref = useRef<number | null>(null);\n const latestTurnMetadataRef = useRef<{\n turnDetectionStrategy?: string;\n sequence?: number;\n speechId?: string;\n }>({});\n const isConnectedRef = useRef(false);\n const userCumulativeTrackStatsRef = useRef<CumulativeTrackStats | undefined>(\n undefined,\n );\n const agentCumulativeTrackStatsRef = useRef<CumulativeTrackStats | undefined>(\n undefined,\n );\n\n const userMicPublication = useParticipantTrack({\n type: 'user',\n source: Source.Microphone,\n });\n const agentMicPublication = useParticipantTrack({\n type: 'agent',\n source: Source.Microphone,\n });\n\n const timer = useTimer({\n autoStart: false,\n onExpire: handleExpire,\n expiryTimestamp: new Date(),\n });\n\n useEffect(() => {\n if (!room) {\n return;\n }\n registerRoomEvents();\n\n return () => {\n unregisterRoomEvents();\n };\n }, [room]);\n\n useUpdateEffect(() => {\n setMicrophoneDeviceId(microphone.deviceId);\n }, [microphone.deviceId]);\n\n useUpdateEffect(() => {\n setSpeakerDeviceId(speaker.deviceId);\n }, [speaker.deviceId]);\n\n useUpdateEffect(() => {\n setCameraDeviceId(camera.deviceId);\n }, [camera.deviceId]);\n\n useUpdateEffect(() => {\n if (agentConnectionState !== 'joined') {\n return;\n }\n room.localParticipant.setMicrophoneEnabled(microphone.enabled);\n }, [microphone.enabled, agentConnectionState]);\n\n useUpdateEffect(() => {\n if (agentConnectionState !== 'joined') {\n return;\n }\n room.localParticipant.setCameraEnabled(camera.enabled, {\n resolution: { width: 1920, height: 1080 },\n });\n }, [camera.enabled, agentConnectionState]);\n\n useEffect(() => {\n if (!autoJoin) {\n return;\n }\n\n if (conversationStatus === 'created') {\n void join();\n }\n }, [conversationStatus, autoJoin]);\n\n useEffect(() => {\n if (!joinedAt || conversation.data?.limit === undefined) {\n return;\n }\n\n timer.restart(new Date(joinedAt.getTime() + conversation.data!.limit!));\n }, [joinedAt, conversation.data?.limit]);\n\n async function join() {\n invariant(userConnectionState === 'idle', 'Already joined');\n invariant(conversation.data, 'Conversation is not ready');\n const url = new URL(conversation?.data?.url || '');\n const accessToken = url.searchParams.get('token');\n try {\n setUserConnectionState('joining');\n await room?.connect(conversation.data.url, accessToken!, {});\n\n // sometimes the agent is already joined before the user joins the conversation\n const remoteParticipant = findJoinedAgentParticipant(room, type);\n if (remoteParticipant && agentConnectionState !== 'joined') {\n handleAgentJoin(remoteParticipant);\n }\n\n enableMediaDevices();\n } catch (error) {\n console.error('Failed to join', error);\n setUserConnectionState('join-error');\n }\n }\n\n function enableMediaDevices() {\n if (startWithMicrophone) {\n setMicrophone({ ...microphone, enabled: true });\n }\n if (startWithCamera && type === 'video') {\n setCamera({ ...camera, enabled: true });\n }\n }\n\n function handleTranscriptionReceivedEvent(\n segments: TranscriptionSegment[],\n participant?: Participant,\n ) {\n const transcriptions: ConversationTranscription[] = segments.map((s) => ({\n id: s.id,\n message: s.text,\n source: participant?.kind === ParticipantKind.AGENT ? 'agent' : 'user',\n }));\n\n setTranscriptions((old) => mergeTranscriptions(transcriptions, old));\n }\n\n function handleTurnDetectionEvent(data: TurnDetectionData) {\n const conversationId = conversationRef.current?.id;\n const { participantKind, state: eventState } = data;\n switch (participantKind) {\n case 'STANDARD':\n if (eventState === 'listening') {\n latestTurnMetadataRef.current = {\n turnDetectionStrategy: data.turnDetectionStrategy,\n sequence: data.sequence,\n speechId: data.speechId,\n };\n }\n emitEvent(\n eventState === 'speaking' ? 'userSpeakStart' : 'userSpeakStop',\n { conversationId: conversationId! },\n );\n setUserActivityState(eventState);\n break;\n case 'AGENT':\n if (data.speechId) {\n latestTurnMetadataRef.current = {\n ...latestTurnMetadataRef.current,\n speechId: data.speechId,\n };\n }\n emitEvent(\n eventState === 'speaking' ? 'agentSpeakStart' : 'agentSpeakStop',\n { conversationId: conversationId! },\n );\n setAgentActivityState(eventState);\n break;\n }\n }\n\n function handleAcousticUserOnset() {\n if (!isConnectedRef.current) {\n return;\n }\n if (acousticPhaseRef.current === 'waitingForAgent') {\n acousticPhaseRef.current = 'idle';\n acousticT0Ref.current = null;\n }\n }\n\n function handleAcousticUserOffset(timestampMs: number) {\n if (!isConnectedRef.current || acousticPhaseRef.current !== 'idle') {\n return;\n }\n acousticT0Ref.current = timestampMs - ACOUSTIC_USER_HANGOVER_MS;\n acousticPhaseRef.current = 'waitingForAgent';\n }\n\n function handleAcousticAgentOnset(timestampMs: number) {\n if (\n !isConnectedRef.current ||\n acousticPhaseRef.current !== 'waitingForAgent' ||\n acousticT0Ref.current == null\n ) {\n return;\n }\n\n const latencyMs = timestampMs - acousticT0Ref.current;\n acousticT0Ref.current = null;\n acousticPhaseRef.current = 'busy';\n\n if (latencyMs < 0 || latencyMs > 15000) {\n return;\n }\n\n emitEvent('responseLatency', {\n conversationId: conversationRef.current?.id!,\n latencyMs,\n turnDetectionStrategy:\n latestTurnMetadataRef.current.turnDetectionStrategy!,\n sequence: latestTurnMetadataRef.current.sequence,\n speechId: latestTurnMetadataRef.current.speechId,\n });\n\n void emitConversationTurnLatency(latencyMs);\n }\n\n async function emitConversationTurnLatency(clientAcousticLatencyMs: number) {\n const [userReport, agentReport] = await Promise.all([\n getTrackStats(userMicPublication),\n getTrackStats(agentMicPublication),\n ]);\n const userStats = parseTrackStats(\n userReport,\n userCumulativeTrackStatsRef.current,\n );\n const agentStats = parseTrackStats(\n agentReport,\n agentCumulativeTrackStatsRef.current,\n );\n userCumulativeTrackStatsRef.current = userStats.cumulativeTrackStats;\n agentCumulativeTrackStatsRef.current = agentStats.cumulativeTrackStats;\n\n emitEvent('conversationTurnLatency', {\n conversationId: conversationRef.current?.id!,\n speechId: latestTurnMetadataRef.current.speechId,\n sequence: latestTurnMetadataRef.current.sequence,\n clientAcousticLatencyMs,\n rttMs: userStats.roundTripTimeMs,\n jitterBufferDelayMs: agentStats.jitterBufferDelayMs,\n userPacketsLost: userStats.packetsLost,\n agentPacketsLost: agentStats.packetsLost,\n });\n }\n\n function handleAcousticAgentOffset() {\n acousticPhaseRef.current = 'idle';\n }\n\n useSpeechActivityDetector({\n source: 'user',\n onSpeechStart: handleAcousticUserOnset,\n onSpeechEnd: handleAcousticUserOffset,\n thresholdRms: ACOUSTIC_USER_THRESHOLD_RMS,\n hangoverMs: ACOUSTIC_USER_HANGOVER_MS,\n });\n useSpeechActivityDetector({\n source: 'agent',\n onSpeechStart: handleAcousticAgentOnset,\n onSpeechEnd: handleAcousticAgentOffset,\n hangoverMs: ACOUSTIC_AGENT_HANGOVER_MS,\n });\n\n function handleInactivityWarningEvent(data: InactivityWarningData) {\n emitEvent('inactivityWarning', {\n conversationId: conversationRef.current?.id!,\n gracePeriodSec: data.grace_period_sec,\n });\n }\n\n function handleInactivityTimeoutEvent(_data: InactivityTimeoutData) {\n inactivityTimeoutRef.current = true;\n emitEvent('inactivityTimeout', {\n conversationId: conversationRef.current?.id!,\n });\n }\n\n async function handleGetToolsRpc() {\n return JSON.stringify(buildToolDefinitions(toolsRegistryRef.current));\n }\n\n async function handleExecuteToolRpc(data: RpcInvocationData) {\n const call = parseFunctionCallPayload(data.payload);\n if (!call) {\n return JSON.stringify({\n functionCallId: '',\n result: '',\n error: 'Malformed function call payload.',\n } satisfies FunctionCallResult);\n }\n try {\n const [result] = await toolRuntimeRef.current.executeToolCalls([call]);\n return JSON.stringify(result);\n } catch (error) {\n return JSON.stringify({\n functionCallId: call.functionCallId,\n result: '',\n error: extractToolErrorMessage(error),\n } satisfies FunctionCallResult);\n }\n }\n\n const dataChannelHandlers: {\n guard: (data: unknown) => boolean;\n handle: (data: unknown) => void | Promise<void>;\n }[] = [\n {\n guard: checkIsTurnDetectionData,\n handle: handleTurnDetectionEvent as (data: unknown) => void,\n },\n {\n guard: checkIsInactivityWarningData,\n handle: handleInactivityWarningEvent as (data: unknown) => void,\n },\n {\n guard: checkIsInactivityTimeoutData,\n handle: handleInactivityTimeoutEvent as (data: unknown) => void,\n },\n ];\n\n function handleDataReceivedEvent(\n payload: Uint8Array,\n _participant?: RemoteParticipant,\n _kind?: unknown,\n topic?: string,\n ) {\n const decoded = decodeDataPayload(payload);\n if (decoded === null) {\n return;\n }\n if (checkIsCreditExhaustedMessage(decoded, topic)) {\n creditExhaustedRef.current = true;\n emitEvent('creditExhausted', {\n conversationId: conversationRef.current?.id!,\n });\n return;\n }\n for (const { guard, handle } of dataChannelHandlers) {\n if (guard(decoded)) {\n void Promise.resolve(handle(decoded)).catch((error) => {\n console.error('Failed to handle data channel payload', error);\n });\n return;\n }\n }\n }\n\n function handleConnectedEvent() {\n isConnectedRef.current = true;\n setUserConnectionState('joined');\n setAgentConnectionState('joining');\n emitEvent('callStarted', {\n conversationId: conversationRef.current?.id!,\n });\n }\n\n async function handleEncryptionErrorEvent(error: Error) {\n console.error('Encryption error', error);\n setConversationStatus('error');\n }\n\n function handleDisconnectedEvent(reason?: DisconnectReason) {\n isConnectedRef.current = false;\n acousticPhaseRef.current = 'idle';\n acousticT0Ref.current = null;\n latestTurnMetadataRef.current = {};\n userCumulativeTrackStatsRef.current = undefined;\n agentCumulativeTrackStatsRef.current = undefined;\n setAgentActivityState('idle');\n setAgentConnectionState('idle');\n setUserActivityState('idle');\n setUserConnectionState('idle');\n\n if (inactivityTimeoutRef.current) {\n inactivityTimeoutRef.current = false;\n setConversationStatus('inactivity-timeout');\n return;\n }\n\n if (creditExhaustedRef.current) {\n creditExhaustedRef.current = false;\n setConversationStatus('credit-exhausted');\n return;\n }\n\n switch (reason) {\n case DisconnectReason.CLIENT_INITIATED:\n break;\n case DisconnectReason.ROOM_CLOSED:\n setConversationStatus('destroyed');\n break;\n default:\n console.error('Conversation disconnected with reason', reason);\n setConversationStatus('error');\n break;\n }\n }\n\n function handleParticipantConnectedEvent(participant: RemoteParticipant) {\n if (shouldHandleParticipantConnected(participant, type)) {\n handleAgentJoin(participant);\n }\n }\n\n function handleAgentJoin(participant: RemoteParticipant) {\n setAgentConnectionState('joined');\n emitEvent('agentJoined', {\n conversationId: conversationRef.current?.id!,\n participant,\n });\n }\n\n function handleParticipantDisconnectedEvent(participant: RemoteParticipant) {\n setAgentConnectionState('left');\n emitEvent('agentLeft', {\n conversationId: conversationRef.current?.id!,\n participant,\n });\n }\n\n async function leave() {\n if (userConnectionState !== 'joined' && userConnectionState !== 'joining') {\n return;\n }\n\n try {\n setUserConnectionState('leaving');\n await room?.disconnect(true);\n setConversationStatus('destroyed');\n setJoinedAt(undefined);\n emitEvent('callEnded', {\n conversationId: conversationRef.current?.id!,\n });\n } catch (error) {\n console.error('Failed to leave', error);\n setConversationStatus('error');\n }\n }\n\n async function handleExpire() {\n // The duration timer keeps running after the call ends.\n if (conversationStatus === 'credit-exhausted') {\n return;\n }\n emitEvent('timeExceeded', {\n conversationId: conversationRef.current?.id!,\n limit: conversationRef.current?.limit!,\n });\n await leave();\n setConversationStatus('exceeded');\n }\n\n async function interrupt() {\n emitEvent('interrupt', {\n conversationId: conversationRef.current?.id!,\n });\n\n await publishConversationDataMessage(room, {}, 'interrupt');\n }\n\n async function dismissInactivity() {\n await publishConversationDataMessage(\n room,\n { type: 'inactivity_dismiss' },\n 'inactivity_dismiss',\n );\n }\n\n async function send(message: string, attachments: Attachment[] = []) {\n await room?.localParticipant.sendText(message, {\n topic: 'lk.chat',\n attributes: {\n attachments: safeStringify(attachments),\n },\n });\n emitEvent('userSendMessage', {\n conversationId: conversationRef.current?.id!,\n message,\n });\n }\n\n function registerRoomEvents() {\n room\n .on('connected', handleConnectedEvent)\n .on('encryptionError', handleEncryptionErrorEvent)\n .on('disconnected', handleDisconnectedEvent)\n .on('transcriptionReceived', handleTranscriptionReceivedEvent)\n .on('participantConnected', handleParticipantConnectedEvent)\n .on('participantDisconnected', handleParticipantDisconnectedEvent)\n .on('dataReceived', handleDataReceivedEvent);\n room.unregisterRpcMethod(GET_TOOLS_RPC_METHOD);\n room.unregisterRpcMethod(EXECUTE_TOOL_RPC_METHOD);\n room.registerRpcMethod(GET_TOOLS_RPC_METHOD, handleGetToolsRpc);\n room.registerRpcMethod(EXECUTE_TOOL_RPC_METHOD, handleExecuteToolRpc);\n }\n\n function unregisterRoomEvents() {\n room.unregisterRpcMethod(GET_TOOLS_RPC_METHOD);\n room.unregisterRpcMethod(EXECUTE_TOOL_RPC_METHOD);\n room.off('connected', handleConnectedEvent);\n room.off('encryptionError', handleEncryptionErrorEvent);\n room.off('disconnected', handleDisconnectedEvent);\n room.off('transcriptionReceived', handleTranscriptionReceivedEvent);\n room.off('participantConnected', handleParticipantConnectedEvent);\n room.off('participantDisconnected', handleParticipantDisconnectedEvent);\n room.off('dataReceived', handleDataReceivedEvent);\n }\n\n return {\n status: conversationStatus,\n conversation: conversation.data,\n join,\n send,\n interrupt,\n dismissInactivity,\n leave,\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -15,4 +15,7 @@ export function checkIsInactivityWarningData(data) {
|
|
|
15
15
|
export function checkIsInactivityTimeoutData(data) {
|
|
16
16
|
return typeof data === 'object' && data !== null && 'type' in data && data.type === 'inactivity_timeout';
|
|
17
17
|
}
|
|
18
|
+
export function checkIsCreditExhaustedMessage(data, topic) {
|
|
19
|
+
return topic === 'billing' && typeof data === 'object' && data !== null && data.type === 'ended' && data.reason === 'insufficient_credit';
|
|
20
|
+
}
|
|
18
21
|
//# sourceMappingURL=dataChannel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["decodeDataPayload","data","JSON","parse","TextDecoder","decode","error","console","checkIsTurnDetectionData","checkIsInactivityWarningData","type","grace_period_sec","checkIsInactivityTimeoutData"],"sources":["../../../../../../src/hooks/useConversation/livekit/utils/dataChannel.ts"],"sourcesContent":["import type {\n InactivityWarningData,\n InactivityTimeoutData,\n TurnDetectionData,\n} from '../types';\n\nexport function decodeDataPayload(data: Uint8Array): unknown {\n try {\n return JSON.parse(new TextDecoder().decode(data));\n } catch (error) {\n console.error('Failed to decode data received payload', error);\n return null;\n }\n}\n\nexport function checkIsTurnDetectionData(\n data: unknown,\n): data is TurnDetectionData {\n return (\n typeof data === 'object' &&\n data !== null &&\n 'participantKind' in data &&\n 'state' in data\n );\n}\n\nexport function checkIsInactivityWarningData(\n data: unknown,\n): data is InactivityWarningData {\n return (\n typeof data === 'object' &&\n data !== null &&\n 'type' in data &&\n (data as Record<string, unknown>).type === 'inactivity_warning' &&\n 'grace_period_sec' in data &&\n typeof (data as Record<string, unknown>).grace_period_sec === 'number'\n );\n}\n\nexport function checkIsInactivityTimeoutData(\n data: unknown,\n): data is InactivityTimeoutData {\n return (\n typeof data === 'object' &&\n data !== null &&\n 'type' in data &&\n (data as Record<string, unknown>).type === 'inactivity_timeout'\n );\n}\n"],"mappings":"AAMA,OAAO,SAASA,iBAAiBA,CAACC,IAAgB,EAAW;EAC3D,IAAI;IACF,OAAOC,IAAI,CAACC,KAAK,CAAC,IAAIC,WAAW,CAAC,CAAC,CAACC,MAAM,CAACJ,IAAI,CAAC,CAAC;EACnD,CAAC,CAAC,OAAOK,KAAK,EAAE;IACdC,OAAO,CAACD,KAAK,CAAC,wCAAwC,EAAEA,KAAK,CAAC;IAC9D,OAAO,IAAI;EACb;AACF;AAEA,OAAO,SAASE,wBAAwBA,CACtCP,IAAa,EACc;EAC3B,OACE,OAAOA,IAAI,KAAK,QAAQ,IACxBA,IAAI,KAAK,IAAI,IACb,iBAAiB,IAAIA,IAAI,IACzB,OAAO,IAAIA,IAAI;AAEnB;AAEA,OAAO,SAASQ,4BAA4BA,CAC1CR,IAAa,EACkB;EAC/B,OACE,OAAOA,IAAI,KAAK,QAAQ,IACxBA,IAAI,KAAK,IAAI,IACb,MAAM,IAAIA,IAAI,IACbA,IAAI,CAA6BS,IAAI,KAAK,oBAAoB,IAC/D,kBAAkB,IAAIT,IAAI,IAC1B,OAAQA,IAAI,CAA6BU,gBAAgB,KAAK,QAAQ;AAE1E;AAEA,OAAO,SAASC,4BAA4BA,CAC1CX,IAAa,EACkB;EAC/B,OACE,OAAOA,IAAI,KAAK,QAAQ,IACxBA,IAAI,KAAK,IAAI,IACb,MAAM,IAAIA,IAAI,IACbA,IAAI,CAA6BS,IAAI,KAAK,oBAAoB;AAEnE","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["decodeDataPayload","data","JSON","parse","TextDecoder","decode","error","console","checkIsTurnDetectionData","checkIsInactivityWarningData","type","grace_period_sec","checkIsInactivityTimeoutData","checkIsCreditExhaustedMessage","topic","reason"],"sources":["../../../../../../src/hooks/useConversation/livekit/utils/dataChannel.ts"],"sourcesContent":["import type {\n InactivityWarningData,\n InactivityTimeoutData,\n TurnDetectionData,\n} from '../types';\n\nexport function decodeDataPayload(data: Uint8Array): unknown {\n try {\n return JSON.parse(new TextDecoder().decode(data));\n } catch (error) {\n console.error('Failed to decode data received payload', error);\n return null;\n }\n}\n\nexport function checkIsTurnDetectionData(\n data: unknown,\n): data is TurnDetectionData {\n return (\n typeof data === 'object' &&\n data !== null &&\n 'participantKind' in data &&\n 'state' in data\n );\n}\n\nexport function checkIsInactivityWarningData(\n data: unknown,\n): data is InactivityWarningData {\n return (\n typeof data === 'object' &&\n data !== null &&\n 'type' in data &&\n (data as Record<string, unknown>).type === 'inactivity_warning' &&\n 'grace_period_sec' in data &&\n typeof (data as Record<string, unknown>).grace_period_sec === 'number'\n );\n}\n\nexport function checkIsInactivityTimeoutData(\n data: unknown,\n): data is InactivityTimeoutData {\n return (\n typeof data === 'object' &&\n data !== null &&\n 'type' in data &&\n (data as Record<string, unknown>).type === 'inactivity_timeout'\n );\n}\n\nexport function checkIsCreditExhaustedMessage(\n data: unknown,\n topic: string | undefined,\n): boolean {\n return (\n topic === 'billing' &&\n typeof data === 'object' &&\n data !== null &&\n (data as Record<string, unknown>).type === 'ended' &&\n (data as Record<string, unknown>).reason === 'insufficient_credit'\n );\n}\n"],"mappings":"AAMA,OAAO,SAASA,iBAAiBA,CAACC,IAAgB,EAAW;EAC3D,IAAI;IACF,OAAOC,IAAI,CAACC,KAAK,CAAC,IAAIC,WAAW,CAAC,CAAC,CAACC,MAAM,CAACJ,IAAI,CAAC,CAAC;EACnD,CAAC,CAAC,OAAOK,KAAK,EAAE;IACdC,OAAO,CAACD,KAAK,CAAC,wCAAwC,EAAEA,KAAK,CAAC;IAC9D,OAAO,IAAI;EACb;AACF;AAEA,OAAO,SAASE,wBAAwBA,CACtCP,IAAa,EACc;EAC3B,OACE,OAAOA,IAAI,KAAK,QAAQ,IACxBA,IAAI,KAAK,IAAI,IACb,iBAAiB,IAAIA,IAAI,IACzB,OAAO,IAAIA,IAAI;AAEnB;AAEA,OAAO,SAASQ,4BAA4BA,CAC1CR,IAAa,EACkB;EAC/B,OACE,OAAOA,IAAI,KAAK,QAAQ,IACxBA,IAAI,KAAK,IAAI,IACb,MAAM,IAAIA,IAAI,IACbA,IAAI,CAA6BS,IAAI,KAAK,oBAAoB,IAC/D,kBAAkB,IAAIT,IAAI,IAC1B,OAAQA,IAAI,CAA6BU,gBAAgB,KAAK,QAAQ;AAE1E;AAEA,OAAO,SAASC,4BAA4BA,CAC1CX,IAAa,EACkB;EAC/B,OACE,OAAOA,IAAI,KAAK,QAAQ,IACxBA,IAAI,KAAK,IAAI,IACb,MAAM,IAAIA,IAAI,IACbA,IAAI,CAA6BS,IAAI,KAAK,oBAAoB;AAEnE;AAEA,OAAO,SAASG,6BAA6BA,CAC3CZ,IAAa,EACba,KAAyB,EAChB;EACT,OACEA,KAAK,KAAK,SAAS,IACnB,OAAOb,IAAI,KAAK,QAAQ,IACxBA,IAAI,KAAK,IAAI,IACZA,IAAI,CAA6BS,IAAI,KAAK,OAAO,IACjDT,IAAI,CAA6Bc,MAAM,KAAK,qBAAqB;AAEtE","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["../../../../src/hooks/useConversationEvents/types.tsx"],"sourcesContent":["import React from 'react';\nimport type { RemoteParticipant } from 'livekit-client';\n\nexport type UserSpeakStartPayload = {\n conversationId: string;\n};\n\nexport type TimeExceededPayload = {\n conversationId: string;\n limit: number;\n};\n\nexport type UserSpeakStopPayload = {\n conversationId: string;\n};\n\nexport type AgentSpeakStartPayload = {\n conversationId: string;\n};\n\nexport type AgentSpeakStopPayload = {\n conversationId: string;\n};\n\nexport type ResponseLatencyPayload = {\n conversationId: string;\n latencyMs: number;\n turnDetectionStrategy: string;\n sequence?: number;\n speechId?: string;\n};\n\nexport type ConversationTurnLatencyPayload = {\n conversationId: string;\n speechId?: string;\n sequence?: number;\n clientAcousticLatencyMs: number;\n rttMs?: number;\n jitterBufferDelayMs?: number;\n userPacketsLost?: number;\n agentPacketsLost?: number;\n};\n\nexport type InterruptPayload = {\n conversationId: string;\n};\n\nexport type CallStartedPayload = {\n conversationId: string;\n};\n\nexport type CallEndedPayload = {\n conversationId: string;\n};\n\nexport type UserSendMessagePayload = {\n conversationId: string;\n message: string;\n};\n\nexport type AgentJoinedPayload = {\n conversationId: string;\n participant: RemoteParticipant;\n};\n\nexport type AgentLeftPayload = {\n conversationId: string;\n participant?: RemoteParticipant;\n};\n\nexport type AgentVideoLoadedPayload = {\n videoRef: React.RefObject<HTMLVideoElement>;\n};\n\nexport type InactivityWarningPayload = {\n conversationId: string;\n gracePeriodSec: number;\n};\n\nexport type InactivityTimeoutPayload = {\n conversationId: string;\n};\n\nexport type ConversationEventMap = {\n userSpeakStart: UserSpeakStartPayload;\n userSpeakStop: UserSpeakStopPayload;\n agentSpeakStart: AgentSpeakStartPayload;\n agentSpeakStop: AgentSpeakStopPayload;\n responseLatency: ResponseLatencyPayload;\n conversationTurnLatency: ConversationTurnLatencyPayload;\n interrupt: InterruptPayload;\n callStarted: CallStartedPayload;\n callEnded: CallEndedPayload;\n userSendMessage: UserSendMessagePayload;\n agentJoined: AgentJoinedPayload;\n agentLeft: AgentLeftPayload;\n timeExceeded: TimeExceededPayload;\n agentVideoLoaded: AgentVideoLoadedPayload;\n inactivityWarning: InactivityWarningPayload;\n inactivityTimeout: InactivityTimeoutPayload;\n};\n\nexport type ConversationEvent = keyof ConversationEventMap;\n\nexport type EventPayload<T extends ConversationEvent> = ConversationEventMap[T];\n"],"mappings":"","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["../../../../src/hooks/useConversationEvents/types.tsx"],"sourcesContent":["import React from 'react';\nimport type { RemoteParticipant } from 'livekit-client';\n\nexport type UserSpeakStartPayload = {\n conversationId: string;\n};\n\nexport type TimeExceededPayload = {\n conversationId: string;\n limit: number;\n};\n\nexport type UserSpeakStopPayload = {\n conversationId: string;\n};\n\nexport type AgentSpeakStartPayload = {\n conversationId: string;\n};\n\nexport type AgentSpeakStopPayload = {\n conversationId: string;\n};\n\nexport type ResponseLatencyPayload = {\n conversationId: string;\n latencyMs: number;\n turnDetectionStrategy: string;\n sequence?: number;\n speechId?: string;\n};\n\nexport type ConversationTurnLatencyPayload = {\n conversationId: string;\n speechId?: string;\n sequence?: number;\n clientAcousticLatencyMs: number;\n rttMs?: number;\n jitterBufferDelayMs?: number;\n userPacketsLost?: number;\n agentPacketsLost?: number;\n};\n\nexport type InterruptPayload = {\n conversationId: string;\n};\n\nexport type CallStartedPayload = {\n conversationId: string;\n};\n\nexport type CallEndedPayload = {\n conversationId: string;\n};\n\nexport type UserSendMessagePayload = {\n conversationId: string;\n message: string;\n};\n\nexport type AgentJoinedPayload = {\n conversationId: string;\n participant: RemoteParticipant;\n};\n\nexport type AgentLeftPayload = {\n conversationId: string;\n participant?: RemoteParticipant;\n};\n\nexport type AgentVideoLoadedPayload = {\n videoRef: React.RefObject<HTMLVideoElement>;\n};\n\nexport type InactivityWarningPayload = {\n conversationId: string;\n gracePeriodSec: number;\n};\n\nexport type InactivityTimeoutPayload = {\n conversationId: string;\n};\n\nexport type CreditExhaustedPayload = {\n conversationId: string;\n};\n\nexport type ConversationEventMap = {\n userSpeakStart: UserSpeakStartPayload;\n userSpeakStop: UserSpeakStopPayload;\n agentSpeakStart: AgentSpeakStartPayload;\n agentSpeakStop: AgentSpeakStopPayload;\n responseLatency: ResponseLatencyPayload;\n conversationTurnLatency: ConversationTurnLatencyPayload;\n interrupt: InterruptPayload;\n callStarted: CallStartedPayload;\n callEnded: CallEndedPayload;\n userSendMessage: UserSendMessagePayload;\n agentJoined: AgentJoinedPayload;\n agentLeft: AgentLeftPayload;\n timeExceeded: TimeExceededPayload;\n agentVideoLoaded: AgentVideoLoadedPayload;\n inactivityWarning: InactivityWarningPayload;\n inactivityTimeout: InactivityTimeoutPayload;\n creditExhausted: CreditExhaustedPayload;\n};\n\nexport type ConversationEvent = keyof ConversationEventMap;\n\nexport type EventPayload<T extends ConversationEvent> = ConversationEventMap[T];\n"],"mappings":"","ignoreList":[]}
|
|
@@ -32,6 +32,17 @@ export function extractContent(frame) {
|
|
|
32
32
|
return null;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
// Same lookup order as extractContent: top level first, then the gateway body.
|
|
36
|
+
export function extractCanSendChatMessage(frame) {
|
|
37
|
+
try {
|
|
38
|
+
const parsed = JSON.parse(frame);
|
|
39
|
+
const payload = typeof parsed.canSendChatMessage === 'boolean' || typeof parsed.body !== 'string' ? parsed : JSON.parse(new TextDecoder().decode(Uint8Array.from(atob(parsed.body), char => char.charCodeAt(0))));
|
|
40
|
+
return typeof payload.canSendChatMessage === 'boolean' ? payload.canSendChatMessage : null;
|
|
41
|
+
} catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
35
46
|
// Feeds decoded text through a running scanner that emits each complete
|
|
36
47
|
// top-level `{…}` object as its closing brace arrives.
|
|
37
48
|
export function createObjectScanner(onObject) {
|
|
@@ -82,7 +93,8 @@ export async function streamChatMessage(params, callbacks, signal) {
|
|
|
82
93
|
headers = params.headers;
|
|
83
94
|
const onChunk = callbacks.onChunk,
|
|
84
95
|
onDone = callbacks.onDone,
|
|
85
|
-
onError = callbacks.onError
|
|
96
|
+
onError = callbacks.onError,
|
|
97
|
+
onCanSendChatMessage = callbacks.onCanSendChatMessage;
|
|
86
98
|
const xsrfToken = readCookie('XSRF-TOKEN');
|
|
87
99
|
const autoXsrf = !(headers != null && headers['x-xsrf-token']) && xsrfToken ? {
|
|
88
100
|
'x-xsrf-token': xsrfToken
|
|
@@ -116,6 +128,10 @@ export async function streamChatMessage(params, callbacks, signal) {
|
|
|
116
128
|
if (content !== null) {
|
|
117
129
|
onChunk(content);
|
|
118
130
|
}
|
|
131
|
+
const canSend = extractCanSendChatMessage(frame);
|
|
132
|
+
if (canSend !== null) {
|
|
133
|
+
onCanSendChatMessage == null || onCanSendChatMessage(canSend);
|
|
134
|
+
}
|
|
119
135
|
});
|
|
120
136
|
const reader = response.body.getReader();
|
|
121
137
|
const decoder = new TextDecoder();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["DEFAULT_STREAM_PATH","readCookie","name","_document$cookie$spli","document","undefined","cookie","split","map","part","trim","find","startsWith","slice","length","extractContent","frame","parsed","JSON","parse","content","body","decoded","TextDecoder","decode","Uint8Array","from","atob","char","charCodeAt","inner","createObjectScanner","onObject","buffer","cursor","braceDepth","objectStart","inString","escaped","feed","text","streamChatMessage","params","callbacks","signal","chatId","message","namespace","chatConfig","attachments","metadata","headers","onChunk","onDone","onError","xsrfToken","autoXsrf","response","fetch","method","credentials","stringify","ok","Error","status","scanForObjects","reader","getReader","decoder","_await$reader$read","read","done","value","stream","err"],"sources":["../../../../src/hooks/useTextChat/streamChatMessage.ts"],"sourcesContent":["// Same-origin Wix persona-chat gateway path. The transport always posts here\n// with `credentials: 'include'`, so the session cookie rides along and a\n// consumer needs no proxy route of its own.\nconst DEFAULT_STREAM_PATH =\n '/_api/persona-chat-service/v1/chat/messages/stream';\n\nexport type StreamCallbacks = {\n onChunk: (token: string) => void;\n onDone: () => void;\n onError: (err: Error) => void;\n};\n\nexport type StreamChatMessageParams = {\n chatId: string;\n message: string;\n namespace: string;\n chatConfig?: object;\n attachments?: object[];\n // Request metadata forwarded to the RPC (e.g. `additionalMetadata` carrying\n // opening-message context). Mirrors the top-level `metadata` object the unary\n // `sendChatMessage` request accepts, so a streamed send carries it identically.\n metadata?: object;\n // Extra request headers merged onto the POST. Lets the caller satisfy the\n // host's transport requirements the SDK can't know about — e.g. an\n // `x-xsrf-token` when the endpoint sits behind a CSRF-protected gateway.\n headers?: Record<string, string>;\n};\n\n// Read a cookie value by name in the browser. Returns undefined outside a\n// browser or when the cookie is absent.\nfunction readCookie(name: string): string | undefined {\n if (typeof document === 'undefined') {\n return undefined;\n }\n return document.cookie\n .split(';')\n .map((part) => part.trim())\n .find((part) => part.startsWith(`${name}=`))\n ?.slice(name.length + 1);\n}\n\n// Pull the assistant text out of one streamed frame. Two framings reach us: the\n// proxy route yields `{ content }` objects, while the gateway wraps each frame\n// as `{ body: base64(json) }`. Returns null for frames without content.\nexport function extractContent(frame: string): string | null {\n try {\n const parsed = JSON.parse(frame);\n if (typeof parsed.content === 'string') {\n return parsed.content;\n }\n if (typeof parsed.body === 'string') {\n const decoded = new TextDecoder().decode(\n Uint8Array.from(atob(parsed.body), (char) => char.charCodeAt(0)),\n );\n const inner = JSON.parse(decoded);\n return typeof inner.content === 'string' ? inner.content : null;\n }\n } catch {\n // Incomplete or non-object frame — skip it.\n }\n return null;\n}\n\n// Feeds decoded text through a running scanner that emits each complete\n// top-level `{…}` object as its closing brace arrives.\nexport function createObjectScanner(onObject: (frame: string) => void) {\n let buffer = '';\n let cursor = 0;\n let braceDepth = 0;\n let objectStart = -1;\n let inString = false;\n let escaped = false;\n\n return function feed(text: string) {\n buffer += text;\n for (; cursor < buffer.length; cursor++) {\n const char = buffer[cursor];\n if (inString) {\n if (escaped) {\n escaped = false;\n } else if (char === '\\\\') {\n escaped = true;\n } else if (char === '\"') {\n inString = false;\n }\n continue;\n }\n if (char === '\"') {\n inString = true;\n } else if (char === '{') {\n if (braceDepth === 0) {\n objectStart = cursor;\n }\n braceDepth++;\n } else if (char === '}' && braceDepth > 0) {\n braceDepth--;\n if (braceDepth === 0 && objectStart >= 0) {\n onObject(buffer.slice(objectStart, cursor + 1));\n objectStart = -1;\n }\n }\n }\n };\n}\n\nexport async function streamChatMessage(\n params: StreamChatMessageParams,\n callbacks: StreamCallbacks,\n signal?: AbortSignal,\n): Promise<void> {\n const {\n chatId,\n message,\n namespace,\n chatConfig,\n attachments,\n metadata,\n headers,\n } = params;\n const { onChunk, onDone, onError } = callbacks;\n\n const xsrfToken = readCookie('XSRF-TOKEN');\n const autoXsrf =\n !headers?.['x-xsrf-token'] && xsrfToken\n ? { 'x-xsrf-token': xsrfToken }\n : undefined;\n\n try {\n // eslint-disable-next-line no-undef\n const response = await fetch(DEFAULT_STREAM_PATH, {\n method: 'POST',\n credentials: 'include',\n headers: { 'Content-Type': 'application/json', ...autoXsrf, ...headers },\n body: JSON.stringify({\n chatId,\n message,\n namespace,\n chatConfig,\n attachments,\n metadata,\n }),\n signal,\n });\n\n if (!response.ok || !response.body) {\n onError(new Error(`Stream request failed: ${response.status}`));\n return;\n }\n\n const scanForObjects = createObjectScanner((frame) => {\n const content = extractContent(frame);\n if (content !== null) {\n onChunk(content);\n }\n });\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n for (;;) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n scanForObjects(decoder.decode(value, { stream: true }));\n }\n scanForObjects(decoder.decode());\n onDone();\n } catch (err) {\n if ((err as Error).name !== 'AbortError') {\n onError(err as Error);\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["DEFAULT_STREAM_PATH","readCookie","name","_document$cookie$spli","document","undefined","cookie","split","map","part","trim","find","startsWith","slice","length","extractContent","frame","parsed","JSON","parse","content","body","decoded","TextDecoder","decode","Uint8Array","from","atob","char","charCodeAt","inner","extractCanSendChatMessage","payload","canSendChatMessage","createObjectScanner","onObject","buffer","cursor","braceDepth","objectStart","inString","escaped","feed","text","streamChatMessage","params","callbacks","signal","chatId","message","namespace","chatConfig","attachments","metadata","headers","onChunk","onDone","onError","onCanSendChatMessage","xsrfToken","autoXsrf","response","fetch","method","credentials","stringify","ok","Error","status","scanForObjects","canSend","reader","getReader","decoder","_await$reader$read","read","done","value","stream","err"],"sources":["../../../../src/hooks/useTextChat/streamChatMessage.ts"],"sourcesContent":["// Same-origin Wix persona-chat gateway path. The transport always posts here\n// with `credentials: 'include'`, so the session cookie rides along and a\n// consumer needs no proxy route of its own.\nconst DEFAULT_STREAM_PATH =\n '/_api/persona-chat-service/v1/chat/messages/stream';\n\nexport type StreamCallbacks = {\n onChunk: (token: string) => void;\n onDone: () => void;\n onError: (err: Error) => void;\n onCanSendChatMessage?: (canSend: boolean) => void;\n};\n\nexport type StreamChatMessageParams = {\n chatId: string;\n message: string;\n namespace: string;\n chatConfig?: object;\n attachments?: object[];\n // Request metadata forwarded to the RPC (e.g. `additionalMetadata` carrying\n // opening-message context). Mirrors the top-level `metadata` object the unary\n // `sendChatMessage` request accepts, so a streamed send carries it identically.\n metadata?: object;\n // Extra request headers merged onto the POST. Lets the caller satisfy the\n // host's transport requirements the SDK can't know about — e.g. an\n // `x-xsrf-token` when the endpoint sits behind a CSRF-protected gateway.\n headers?: Record<string, string>;\n};\n\n// Read a cookie value by name in the browser. Returns undefined outside a\n// browser or when the cookie is absent.\nfunction readCookie(name: string): string | undefined {\n if (typeof document === 'undefined') {\n return undefined;\n }\n return document.cookie\n .split(';')\n .map((part) => part.trim())\n .find((part) => part.startsWith(`${name}=`))\n ?.slice(name.length + 1);\n}\n\n// Pull the assistant text out of one streamed frame. Two framings reach us: the\n// proxy route yields `{ content }` objects, while the gateway wraps each frame\n// as `{ body: base64(json) }`. Returns null for frames without content.\nexport function extractContent(frame: string): string | null {\n try {\n const parsed = JSON.parse(frame);\n if (typeof parsed.content === 'string') {\n return parsed.content;\n }\n if (typeof parsed.body === 'string') {\n const decoded = new TextDecoder().decode(\n Uint8Array.from(atob(parsed.body), (char) => char.charCodeAt(0)),\n );\n const inner = JSON.parse(decoded);\n return typeof inner.content === 'string' ? inner.content : null;\n }\n } catch {\n // Incomplete or non-object frame — skip it.\n }\n return null;\n}\n\n// Same lookup order as extractContent: top level first, then the gateway body.\nexport function extractCanSendChatMessage(frame: string): boolean | null {\n try {\n const parsed = JSON.parse(frame);\n const payload =\n typeof parsed.canSendChatMessage === 'boolean' ||\n typeof parsed.body !== 'string'\n ? parsed\n : JSON.parse(\n new TextDecoder().decode(\n Uint8Array.from(atob(parsed.body), (char) => char.charCodeAt(0)),\n ),\n );\n return typeof payload.canSendChatMessage === 'boolean'\n ? payload.canSendChatMessage\n : null;\n } catch {\n return null;\n }\n}\n\n// Feeds decoded text through a running scanner that emits each complete\n// top-level `{…}` object as its closing brace arrives.\nexport function createObjectScanner(onObject: (frame: string) => void) {\n let buffer = '';\n let cursor = 0;\n let braceDepth = 0;\n let objectStart = -1;\n let inString = false;\n let escaped = false;\n\n return function feed(text: string) {\n buffer += text;\n for (; cursor < buffer.length; cursor++) {\n const char = buffer[cursor];\n if (inString) {\n if (escaped) {\n escaped = false;\n } else if (char === '\\\\') {\n escaped = true;\n } else if (char === '\"') {\n inString = false;\n }\n continue;\n }\n if (char === '\"') {\n inString = true;\n } else if (char === '{') {\n if (braceDepth === 0) {\n objectStart = cursor;\n }\n braceDepth++;\n } else if (char === '}' && braceDepth > 0) {\n braceDepth--;\n if (braceDepth === 0 && objectStart >= 0) {\n onObject(buffer.slice(objectStart, cursor + 1));\n objectStart = -1;\n }\n }\n }\n };\n}\n\nexport async function streamChatMessage(\n params: StreamChatMessageParams,\n callbacks: StreamCallbacks,\n signal?: AbortSignal,\n): Promise<void> {\n const {\n chatId,\n message,\n namespace,\n chatConfig,\n attachments,\n metadata,\n headers,\n } = params;\n const { onChunk, onDone, onError, onCanSendChatMessage } = callbacks;\n\n const xsrfToken = readCookie('XSRF-TOKEN');\n const autoXsrf =\n !headers?.['x-xsrf-token'] && xsrfToken\n ? { 'x-xsrf-token': xsrfToken }\n : undefined;\n\n try {\n // eslint-disable-next-line no-undef\n const response = await fetch(DEFAULT_STREAM_PATH, {\n method: 'POST',\n credentials: 'include',\n headers: { 'Content-Type': 'application/json', ...autoXsrf, ...headers },\n body: JSON.stringify({\n chatId,\n message,\n namespace,\n chatConfig,\n attachments,\n metadata,\n }),\n signal,\n });\n\n if (!response.ok || !response.body) {\n onError(new Error(`Stream request failed: ${response.status}`));\n return;\n }\n\n const scanForObjects = createObjectScanner((frame) => {\n const content = extractContent(frame);\n if (content !== null) {\n onChunk(content);\n }\n const canSend = extractCanSendChatMessage(frame);\n if (canSend !== null) {\n onCanSendChatMessage?.(canSend);\n }\n });\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n for (;;) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n scanForObjects(decoder.decode(value, { stream: true }));\n }\n scanForObjects(decoder.decode());\n onDone();\n } catch (err) {\n if ((err as Error).name !== 'AbortError') {\n onError(err as Error);\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
|