diff --git a/package.json b/package.json index 1f3fd93..331ad4d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@magicul/react-chat-stream", "description": "A React hook that lets you easily integrate your custom ChatGPT-like chat in React.", - "version": "0.5.0", + "version": "0.5.1", "main": "dist/index.js", "types": "dist/index.d.ts", "homepage": "https://github.com/XD2Sketch/react-chat-stream#readme", diff --git a/src/hooks/useChatStream.ts b/src/hooks/useChatStream.ts index 9fb66f6..423c492 100644 --- a/src/hooks/useChatStream.ts +++ b/src/hooks/useChatStream.ts @@ -1,6 +1,7 @@ import { ChangeEvent, FormEvent, useState } from 'react'; import { decodeStreamToJson, getStream } from '../utils/streams'; import { UseChatStreamChatMessage, UseChatStreamInput } from '../types'; +import { extractJsonFromEnd } from '../utils/json'; const BOT_ERROR_MESSAGE = 'Something went wrong fetching AI response.'; @@ -41,7 +42,6 @@ const useChatStream = (input: UseChatStreamInput) => { const stream = await getStream(message, input.options, input.method); const initialMessage = addMessage({ content: '', role: 'bot' }); let response = ''; - let metadata = {}; for await (const chunk of decodeStreamToJson(stream)) { if (!charactersPerSecond) { @@ -51,10 +51,10 @@ const useChatStream = (input: UseChatStreamInput) => { } if (input.options.useMetadata) { - try { - metadata = JSON.parse(chunk.trim()); + const metadata = extractJsonFromEnd(chunk); + if (metadata) { return { ...initialMessage, content: response, metadata: metadata }; - } catch {} + } } // Stream characters one by one based on the characters per second that is set. diff --git a/src/utils/json.ts b/src/utils/json.ts new file mode 100644 index 0000000..215d0fd --- /dev/null +++ b/src/utils/json.ts @@ -0,0 +1,20 @@ +export const extractJsonFromEnd = (chunk: string) => { + const chunkTrimmed = chunk.trim(); + + const jsonObjectRegex = /({[^]*})\s*$/; + const match = chunkTrimmed.match(jsonObjectRegex); + + if (!match) { + return null; + } + + const jsonStr = match[1]; + try { + const parsedData = JSON.parse(jsonStr); + if (typeof parsedData === 'object' && parsedData !== null && !Array.isArray(parsedData)) { + return parsedData; + } + } catch {} + + return null; +};