diff --git a/collector/__tests__/utils/extensions/YoutubeTranscript/YoutubeLoader/youtube-transcript.test.js b/collector/__tests__/utils/extensions/YoutubeTranscript/YoutubeLoader/youtube-transcript.test.js index 2423e736bee..1fca742fd53 100644 --- a/collector/__tests__/utils/extensions/YoutubeTranscript/YoutubeLoader/youtube-transcript.test.js +++ b/collector/__tests__/utils/extensions/YoutubeTranscript/YoutubeLoader/youtube-transcript.test.js @@ -10,9 +10,7 @@ describe("YoutubeTranscript", () => { expect(transcript).toBeDefined(); expect(typeof transcript).toBe("string"); expect(transcript.length).toBeGreaterThan(0); - - // Log the results for debugging purposes - console.log("Success! Transcript length:", transcript.length); - console.log("First 200 characters:", transcript.substring(0, 200) + "..."); - }, 30000); // 30 second timeout for network request + // console.log("Success! Transcript length:", transcript.length); + // console.log("First 200 characters:", transcript.substring(0, 200) + "..."); + }, 30000); }); diff --git a/server/__tests__/utils/safeJSONStringify/safeJSONStringify.test.js b/server/__tests__/utils/safeJSONStringify/safeJSONStringify.test.js new file mode 100644 index 00000000000..2165698035f --- /dev/null +++ b/server/__tests__/utils/safeJSONStringify/safeJSONStringify.test.js @@ -0,0 +1,60 @@ +/* eslint-env jest */ +const { safeJSONStringify } = require("../../../utils/helpers/chat/responses"); + +describe("safeJSONStringify", () => { + test("handles regular objects without BigInt", () => { + const obj = { a: 1, b: "test", c: true, d: null }; + expect(safeJSONStringify(obj)).toBe(JSON.stringify(obj)); + }); + + test("converts BigInt to string", () => { + const bigInt = BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1); + expect(safeJSONStringify(bigInt)).toBe(`"${bigInt.toString()}"`); + }); + + test("handles nested BigInt values", () => { + const obj = { + metrics: { + tokens: BigInt(123), + nested: { moreBigInt: BigInt(456) } + }, + normal: "value" + }; + expect(safeJSONStringify(obj)).toBe( + '{"metrics":{"tokens":"123","nested":{"moreBigInt":"456"}},"normal":"value"}' + ); + }); + + test("handles arrays with BigInt", () => { + const arr = [BigInt(1), 2, BigInt(3)]; + expect(safeJSONStringify(arr)).toBe('["1",2,"3"]'); + }); + + test("handles mixed complex objects", () => { + const obj = { + id: 1, + bigNums: [BigInt(123), BigInt(456)], + nested: { + more: { huge: BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1) } + }, + normal: { str: "test", num: 42, bool: true, nil: null, sub_arr: ["alpha", "beta", "gamma", 1, 2, BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1), { map: { a: BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1) } }] } + }; + const result = JSON.parse(safeJSONStringify(obj)); // Should parse back without errors + expect(typeof result.bigNums[0]).toBe("string"); + expect(result.bigNums[0]).toEqual("123"); + expect(typeof result.nested.more.huge).toBe("string"); + expect(result.normal).toEqual({ str: "test", num: 42, bool: true, nil: null, sub_arr: ["alpha", "beta", "gamma", 1, 2, (BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1)).toString(), { map: { a: (BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1)).toString() } }] }); + expect(result.normal.sub_arr[6].map.a).toEqual((BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1)).toString()); + }); + + test("handles invariants", () => { + expect(safeJSONStringify({})).toBe("{}"); + expect(safeJSONStringify(null)).toBe("null"); + expect(safeJSONStringify(undefined)).toBe(undefined); + expect(safeJSONStringify(true)).toBe("true"); + expect(safeJSONStringify(false)).toBe("false"); + expect(safeJSONStringify(0)).toBe("0"); + expect(safeJSONStringify(1)).toBe("1"); + expect(safeJSONStringify(-1)).toBe("-1"); + }); +}); \ No newline at end of file diff --git a/server/models/workspaceChats.js b/server/models/workspaceChats.js index dde98d1e899..e48807be71d 100644 --- a/server/models/workspaceChats.js +++ b/server/models/workspaceChats.js @@ -1,4 +1,5 @@ const prisma = require("../utils/prisma"); +const { safeJSONStringify } = require("../utils/helpers/chat/responses"); const WorkspaceChats = { new: async function ({ @@ -15,7 +16,7 @@ const WorkspaceChats = { data: { workspaceId, prompt, - response: JSON.stringify(response), + response: safeJSONStringify(response), user_id: user?.id || null, thread_id: threadId, api_session_id: apiSessionId, diff --git a/server/utils/helpers/chat/responses.js b/server/utils/helpers/chat/responses.js index 16a1e9af439..465d56fd2f6 100644 --- a/server/utils/helpers/chat/responses.js +++ b/server/utils/helpers/chat/responses.js @@ -207,8 +207,20 @@ function convertToPromptHistory(history = []) { return formattedHistory.flat(); } +/** + * Safely stringifies any object containing BigInt values + * @param {*} obj - Anything to stringify that might contain BigInt values + * @returns {string} JSON string with BigInt values converted to strings + */ +function safeJSONStringify(obj) { + return JSON.stringify(obj, (_, value) => { + if (typeof value === "bigint") return value.toString(); + return value; + }); +} + function writeResponseChunk(response, data) { - response.write(`data: ${JSON.stringify(data)}\n\n`); + response.write(`data: ${safeJSONStringify(data)}\n\n`); return; } @@ -262,4 +274,5 @@ module.exports = { writeResponseChunk, clientAbortedHandler, formatChatHistory, + safeJSONStringify, };