@wix/legends-platform-sdk 1.25.0 → 1.26.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/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/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/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
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
4
|
exports.createObjectScanner = createObjectScanner;
|
|
5
|
+
exports.extractCanSendChatMessage = extractCanSendChatMessage;
|
|
5
6
|
exports.extractContent = extractContent;
|
|
6
7
|
exports.streamChatMessage = streamChatMessage;
|
|
7
8
|
// Same-origin Wix persona-chat gateway path. The transport always posts here
|
|
@@ -38,6 +39,17 @@ function extractContent(frame) {
|
|
|
38
39
|
return null;
|
|
39
40
|
}
|
|
40
41
|
|
|
42
|
+
// Same lookup order as extractContent: top level first, then the gateway body.
|
|
43
|
+
function extractCanSendChatMessage(frame) {
|
|
44
|
+
try {
|
|
45
|
+
const parsed = JSON.parse(frame);
|
|
46
|
+
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))));
|
|
47
|
+
return typeof payload.canSendChatMessage === 'boolean' ? payload.canSendChatMessage : null;
|
|
48
|
+
} catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
41
53
|
// Feeds decoded text through a running scanner that emits each complete
|
|
42
54
|
// top-level `{…}` object as its closing brace arrives.
|
|
43
55
|
function createObjectScanner(onObject) {
|
|
@@ -91,7 +103,8 @@ async function streamChatMessage(params, callbacks, signal) {
|
|
|
91
103
|
const {
|
|
92
104
|
onChunk,
|
|
93
105
|
onDone,
|
|
94
|
-
onError
|
|
106
|
+
onError,
|
|
107
|
+
onCanSendChatMessage
|
|
95
108
|
} = callbacks;
|
|
96
109
|
const xsrfToken = readCookie('XSRF-TOKEN');
|
|
97
110
|
const autoXsrf = !(headers != null && headers['x-xsrf-token']) && xsrfToken ? {
|
|
@@ -126,6 +139,10 @@ async function streamChatMessage(params, callbacks, signal) {
|
|
|
126
139
|
if (content !== null) {
|
|
127
140
|
onChunk(content);
|
|
128
141
|
}
|
|
142
|
+
const canSend = extractCanSendChatMessage(frame);
|
|
143
|
+
if (canSend !== null) {
|
|
144
|
+
onCanSendChatMessage == null || onCanSendChatMessage(canSend);
|
|
145
|
+
}
|
|
129
146
|
});
|
|
130
147
|
const reader = response.body.getReader();
|
|
131
148
|
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","done","value","read","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","done","value","read","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":[]}
|
|
@@ -139,6 +139,7 @@ function useTextChatStream(options = {}) {
|
|
|
139
139
|
let lastFrameTime = 0;
|
|
140
140
|
let receivedContent = false;
|
|
141
141
|
let errored = false;
|
|
142
|
+
let canSendChatMessage;
|
|
142
143
|
const settle = () => {
|
|
143
144
|
stopRaf();
|
|
144
145
|
const finalAssistantMsg = {
|
|
@@ -205,12 +206,14 @@ function useTextChatStream(options = {}) {
|
|
|
205
206
|
stopRaf();
|
|
206
207
|
onError == null || onError(err);
|
|
207
208
|
setStreamingMessages([]);
|
|
208
|
-
}
|
|
209
|
+
},
|
|
210
|
+
onCanSendChatMessage: canSend => canSendChatMessage = canSend
|
|
209
211
|
}, controller.signal);
|
|
210
212
|
return {
|
|
211
213
|
ok: streamDone && !errored,
|
|
212
214
|
producedContent: receivedContent,
|
|
213
|
-
aborted: !streamDone && !errored
|
|
215
|
+
aborted: !streamDone && !errored,
|
|
216
|
+
canSendChatMessage
|
|
214
217
|
};
|
|
215
218
|
}, [chatId, namespace, headers, onError, refetch, revealMsPerChar, stopRaf]);
|
|
216
219
|
return {
|
|
@@ -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":"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","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":[]}
|
|
@@ -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":[]}
|
|
@@ -141,6 +141,7 @@ export function useTextChatStream(options) {
|
|
|
141
141
|
let lastFrameTime = 0;
|
|
142
142
|
let receivedContent = false;
|
|
143
143
|
let errored = false;
|
|
144
|
+
let canSendChatMessage;
|
|
144
145
|
const settle = () => {
|
|
145
146
|
stopRaf();
|
|
146
147
|
const finalAssistantMsg = {
|
|
@@ -207,12 +208,14 @@ export function useTextChatStream(options) {
|
|
|
207
208
|
stopRaf();
|
|
208
209
|
onError == null || onError(err);
|
|
209
210
|
setStreamingMessages([]);
|
|
210
|
-
}
|
|
211
|
+
},
|
|
212
|
+
onCanSendChatMessage: canSend => canSendChatMessage = canSend
|
|
211
213
|
}, controller.signal);
|
|
212
214
|
return {
|
|
213
215
|
ok: streamDone && !errored,
|
|
214
216
|
producedContent: receivedContent,
|
|
215
|
-
aborted: !streamDone && !errored
|
|
217
|
+
aborted: !streamDone && !errored,
|
|
218
|
+
canSendChatMessage
|
|
216
219
|
};
|
|
217
220
|
}, [chatId, namespace, headers, onError, refetch, revealMsPerChar, stopRaf]);
|
|
218
221
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useCallback","useEffect","useMemo","useRef","useState","useInfiniteQuery","useSdkConsumer","streamChatMessage","messageKey","m","role","content","trim","useTextChatStream","options","_options","_options$limit","limit","headers","onError","_options$revealMsPerC","revealMsPerChar","_useSdkConsumer","chatId","namespace","personaChatService","_useInfiniteQuery","queryKey","queryFn","_ref","pageParam","messages","nextCursor","undefined","queryChatMessages","cursor","getNextPageParam","lastPage","initialPageParam","select","data","pages","flatMap","page","_useInfiniteQuery$dat","sdkMessages","status","fetchNextPage","refetch","_useState","streamingMessages","setStreamingMessages","_useState2","completedMessages","setCompletedMessages","abortRef","rafRef","lastConfirmedRef","sendSeqRef","stopRaf","current","cancelAnimationFrame","_abortRef$current","abort","converted","reverse","confirmedMessages","length","completedKeys","Set","map","confirmedShown","filter","has","chronological","send","_ref2","_abortRef$current2","message","chatConfig","attachments","metadata","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","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":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["useCallback","useEffect","useMemo","useRef","useState","useInfiniteQuery","useSdkConsumer","streamChatMessage","messageKey","m","role","content","trim","useTextChatStream","options","_options","_options$limit","limit","headers","onError","_options$revealMsPerC","revealMsPerChar","_useSdkConsumer","chatId","namespace","personaChatService","_useInfiniteQuery","queryKey","queryFn","_ref","pageParam","messages","nextCursor","undefined","queryChatMessages","cursor","getNextPageParam","lastPage","initialPageParam","select","data","pages","flatMap","page","_useInfiniteQuery$dat","sdkMessages","status","fetchNextPage","refetch","_useState","streamingMessages","setStreamingMessages","_useState2","completedMessages","setCompletedMessages","abortRef","rafRef","lastConfirmedRef","sendSeqRef","stopRaf","current","cancelAnimationFrame","_abortRef$current","abort","converted","reverse","confirmedMessages","length","completedKeys","Set","map","confirmedShown","filter","has","chronological","send","_ref2","_abortRef$current2","message","chatConfig","attachments","metadata","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","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":[]}
|
|
@@ -2,6 +2,7 @@ export type StreamCallbacks = {
|
|
|
2
2
|
onChunk: (token: string) => void;
|
|
3
3
|
onDone: () => void;
|
|
4
4
|
onError: (err: Error) => void;
|
|
5
|
+
onCanSendChatMessage?: (canSend: boolean) => void;
|
|
5
6
|
};
|
|
6
7
|
export type StreamChatMessageParams = {
|
|
7
8
|
chatId: string;
|
|
@@ -13,6 +14,7 @@ export type StreamChatMessageParams = {
|
|
|
13
14
|
headers?: Record<string, string>;
|
|
14
15
|
};
|
|
15
16
|
export declare function extractContent(frame: string): string | null;
|
|
17
|
+
export declare function extractCanSendChatMessage(frame: string): boolean | null;
|
|
16
18
|
export declare function createObjectScanner(onObject: (frame: string) => void): (text: string) => void;
|
|
17
19
|
export declare function streamChatMessage(params: StreamChatMessageParams, callbacks: StreamCallbacks, signal?: AbortSignal): Promise<void>;
|
|
18
20
|
//# sourceMappingURL=streamChatMessage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streamChatMessage.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useTextChat/streamChatMessage.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,OAAO,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"streamChatMessage.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useTextChat/streamChatMessage.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,OAAO,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;IAC9B,oBAAoB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACnD,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAIvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAIlB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,CAAC;AAkBF,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiB3D;AAGD,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAkBvE;AAID,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,UAQxC,MAAM,UA8BlC;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,uBAAuB,EAC/B,SAAS,EAAE,eAAe,EAC1B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAmEf"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTextChatStream.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useTextChat/useTextChatStream.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAItE,YAAY,EACV,eAAe,EACf,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAE7B;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,WAAW,GAAG;IAC/C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CACxC,CAAC;AAEF,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IAGf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;IAG/B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,qBAAqB,EAAE,CAAC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,eAAe,EAAE,OAAO,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"useTextChatStream.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useTextChat/useTextChatStream.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAItE,YAAY,EACV,eAAe,EACf,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAE7B;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,WAAW,GAAG;IAC/C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CACxC,CAAC;AAEF,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IAGf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;IAG/B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,qBAAqB,EAAE,CAAC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,eAAe,EAAE,OAAO,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC;AAKF;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,wBAA6B;;aAyNrD,KAAK,EAAE;;;;4DApInB,uBAAuB,KAAG,OAAO,CAAC,gBAAgB,CAAC;EA8IzD"}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
2
|
+
"version": "1.26.0",
|
|
3
3
|
"name": "@wix/legends-platform-sdk",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": {
|
|
@@ -103,5 +103,5 @@
|
|
|
103
103
|
"wallaby": {
|
|
104
104
|
"autoDetect": true
|
|
105
105
|
},
|
|
106
|
-
"falconPackageHash": "
|
|
106
|
+
"falconPackageHash": "e79a376cad81d2f6e6c35e56d6c095adcd4b26694b23c2a581c8b9a6"
|
|
107
107
|
}
|