nsarrazin HF staff commited on
Commit
d8e839e
1 Parent(s): 00443e1

Use `uuid` for message ID generation instead of crypto method (#882)

Browse files

Because `crypto.randomUUID()` is not available on non-secure contexts
(for example `http` versions of chat-ui), this would break on non-https
deployments of chat-ui.


This should fix #870 and fix #868

package-lock.json CHANGED
@@ -35,6 +35,7 @@
35
  "sharp": "^0.33.2",
36
  "tailwind-scrollbar": "^3.0.0",
37
  "tailwindcss": "^3.4.0",
 
38
  "zod": "^3.22.3"
39
  },
40
  "devDependencies": {
@@ -46,6 +47,7 @@
46
  "@types/jsdom": "^21.1.1",
47
  "@types/marked": "^4.0.8",
48
  "@types/parquetjs": "^0.10.3",
 
49
  "@typescript-eslint/eslint-plugin": "^6.x",
50
  "@typescript-eslint/parser": "^6.x",
51
  "eslint": "^8.28.0",
@@ -1847,6 +1849,12 @@
1847
  "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==",
1848
  "dev": true
1849
  },
 
 
 
 
 
 
1850
  "node_modules/@types/webidl-conversions": {
1851
  "version": "7.0.0",
1852
  "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
@@ -7249,6 +7257,18 @@
7249
  "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
7250
  "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
7251
  },
 
 
 
 
 
 
 
 
 
 
 
 
7252
  "node_modules/v8-compile-cache-lib": {
7253
  "version": "3.0.1",
7254
  "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
35
  "sharp": "^0.33.2",
36
  "tailwind-scrollbar": "^3.0.0",
37
  "tailwindcss": "^3.4.0",
38
+ "uuid": "^9.0.1",
39
  "zod": "^3.22.3"
40
  },
41
  "devDependencies": {
47
  "@types/jsdom": "^21.1.1",
48
  "@types/marked": "^4.0.8",
49
  "@types/parquetjs": "^0.10.3",
50
+ "@types/uuid": "^9.0.8",
51
  "@typescript-eslint/eslint-plugin": "^6.x",
52
  "@typescript-eslint/parser": "^6.x",
53
  "eslint": "^8.28.0",
1849
  "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==",
1850
  "dev": true
1851
  },
1852
+ "node_modules/@types/uuid": {
1853
+ "version": "9.0.8",
1854
+ "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
1855
+ "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==",
1856
+ "dev": true
1857
+ },
1858
  "node_modules/@types/webidl-conversions": {
1859
  "version": "7.0.0",
1860
  "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
7257
  "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
7258
  "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
7259
  },
7260
+ "node_modules/uuid": {
7261
+ "version": "9.0.1",
7262
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
7263
+ "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
7264
+ "funding": [
7265
+ "https://github.com/sponsors/broofa",
7266
+ "https://github.com/sponsors/ctavan"
7267
+ ],
7268
+ "bin": {
7269
+ "uuid": "dist/bin/uuid"
7270
+ }
7271
+ },
7272
  "node_modules/v8-compile-cache-lib": {
7273
  "version": "3.0.1",
7274
  "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
package.json CHANGED
@@ -24,6 +24,7 @@
24
  "@types/jsdom": "^21.1.1",
25
  "@types/marked": "^4.0.8",
26
  "@types/parquetjs": "^0.10.3",
 
27
  "@typescript-eslint/eslint-plugin": "^6.x",
28
  "@typescript-eslint/parser": "^6.x",
29
  "eslint": "^8.28.0",
@@ -71,6 +72,7 @@
71
  "sharp": "^0.33.2",
72
  "tailwind-scrollbar": "^3.0.0",
73
  "tailwindcss": "^3.4.0",
 
74
  "zod": "^3.22.3"
75
  },
76
  "optionalDependencies": {
24
  "@types/jsdom": "^21.1.1",
25
  "@types/marked": "^4.0.8",
26
  "@types/parquetjs": "^0.10.3",
27
+ "@types/uuid": "^9.0.8",
28
  "@typescript-eslint/eslint-plugin": "^6.x",
29
  "@typescript-eslint/parser": "^6.x",
30
  "eslint": "^8.28.0",
72
  "sharp": "^0.33.2",
73
  "tailwind-scrollbar": "^3.0.0",
74
  "tailwindcss": "^3.4.0",
75
+ "uuid": "^9.0.1",
76
  "zod": "^3.22.3"
77
  },
78
  "optionalDependencies": {
src/lib/types/Message.ts CHANGED
@@ -1,10 +1,11 @@
1
  import type { MessageUpdate } from "./MessageUpdate";
2
  import type { Timestamps } from "./Timestamps";
3
  import type { WebSearch } from "./WebSearch";
 
4
 
5
  export type Message = Partial<Timestamps> & {
6
  from: "user" | "assistant" | "system";
7
- id: ReturnType<typeof crypto.randomUUID>;
8
  content: string;
9
  updates?: MessageUpdate[];
10
  webSearchId?: WebSearch["_id"]; // legacy version
1
  import type { MessageUpdate } from "./MessageUpdate";
2
  import type { Timestamps } from "./Timestamps";
3
  import type { WebSearch } from "./WebSearch";
4
+ import type { v4 } from "uuid";
5
 
6
  export type Message = Partial<Timestamps> & {
7
  from: "user" | "assistant" | "system";
8
+ id: ReturnType<typeof v4>;
9
  content: string;
10
  updates?: MessageUpdate[];
11
  webSearchId?: WebSearch["_id"]; // legacy version
src/lib/utils/tree/addChildren.ts CHANGED
@@ -1,5 +1,6 @@
1
  import type { Conversation } from "$lib/types/Conversation";
2
  import type { Message } from "$lib/types/Message";
 
3
 
4
  export function addChildren(
5
  conv: Pick<Conversation, "messages" | "rootMessageId">,
@@ -8,7 +9,7 @@ export function addChildren(
8
  ): Message["id"] {
9
  // if this is the first message we just push it
10
  if (conv.messages.length === 0) {
11
- const messageId = crypto.randomUUID();
12
  conv.rootMessageId = messageId;
13
  conv.messages.push({
14
  ...message,
@@ -22,7 +23,7 @@ export function addChildren(
22
  throw new Error("You need to specify a parentId if this is not the first message");
23
  }
24
 
25
- const messageId = crypto.randomUUID();
26
  if (!conv.rootMessageId) {
27
  // if there is no parentId we just push the message
28
  if (!!parentId && parentId !== conv.messages[conv.messages.length - 1].id) {
1
  import type { Conversation } from "$lib/types/Conversation";
2
  import type { Message } from "$lib/types/Message";
3
+ import { v4 } from "uuid";
4
 
5
  export function addChildren(
6
  conv: Pick<Conversation, "messages" | "rootMessageId">,
9
  ): Message["id"] {
10
  // if this is the first message we just push it
11
  if (conv.messages.length === 0) {
12
+ const messageId = v4();
13
  conv.rootMessageId = messageId;
14
  conv.messages.push({
15
  ...message,
23
  throw new Error("You need to specify a parentId if this is not the first message");
24
  }
25
 
26
+ const messageId = v4();
27
  if (!conv.rootMessageId) {
28
  // if there is no parentId we just push the message
29
  if (!!parentId && parentId !== conv.messages[conv.messages.length - 1].id) {
src/lib/utils/tree/addSibling.ts CHANGED
@@ -1,5 +1,6 @@
1
  import type { Conversation } from "$lib/types/Conversation";
2
  import type { Message } from "$lib/types/Message";
 
3
 
4
  export function addSibling(
5
  conv: Pick<Conversation, "messages" | "rootMessageId">,
@@ -23,7 +24,7 @@ export function addSibling(
23
  throw new Error("The sibling message is the root message, therefore we can't add a sibling");
24
  }
25
 
26
- const messageId = crypto.randomUUID();
27
 
28
  conv.messages.push({
29
  ...message,
1
  import type { Conversation } from "$lib/types/Conversation";
2
  import type { Message } from "$lib/types/Message";
3
+ import { v4 } from "uuid";
4
 
5
  export function addSibling(
6
  conv: Pick<Conversation, "messages" | "rootMessageId">,
24
  throw new Error("The sibling message is the root message, therefore we can't add a sibling");
25
  }
26
 
27
+ const messageId = v4();
28
 
29
  conv.messages.push({
30
  ...message,
src/lib/utils/tree/convertLegacyConversation.ts CHANGED
@@ -1,5 +1,6 @@
1
  import type { Conversation } from "$lib/types/Conversation";
2
  import type { Message } from "$lib/types/Message";
 
3
 
4
  export function convertLegacyConversation(
5
  conv: Pick<Conversation, "messages" | "rootMessageId" | "preprompt">
@@ -12,7 +13,7 @@ export function convertLegacyConversation(
12
  content: conv.preprompt ?? "",
13
  createdAt: new Date(),
14
  updatedAt: new Date(),
15
- id: crypto.randomUUID(),
16
  } satisfies Message,
17
  ...conv.messages,
18
  ];
1
  import type { Conversation } from "$lib/types/Conversation";
2
  import type { Message } from "$lib/types/Message";
3
+ import { v4 } from "uuid";
4
 
5
  export function convertLegacyConversation(
6
  conv: Pick<Conversation, "messages" | "rootMessageId" | "preprompt">
13
  content: conv.preprompt ?? "",
14
  createdAt: new Date(),
15
  updatedAt: new Date(),
16
+ id: v4(),
17
  } satisfies Message,
18
  ...conv.messages,
19
  ];
src/lib/utils/tree/isMessageId.spec.ts CHANGED
@@ -1,9 +1,10 @@
1
  import { describe, expect, it } from "vitest";
2
  import { isMessageId } from "./isMessageId";
 
3
 
4
  describe("isMessageId", () => {
5
  it("should return true for a valid message id", () => {
6
- expect(isMessageId(crypto.randomUUID())).toBe(true);
7
  });
8
  it("should return false for an invalid message id", () => {
9
  expect(isMessageId("1-2-3-4")).toBe(false);
1
  import { describe, expect, it } from "vitest";
2
  import { isMessageId } from "./isMessageId";
3
+ import { v4 } from "uuid";
4
 
5
  describe("isMessageId", () => {
6
  it("should return true for a valid message id", () => {
7
+ expect(isMessageId(v4())).toBe(true);
8
  });
9
  it("should return false for an invalid message id", () => {
10
  expect(isMessageId("1-2-3-4")).toBe(false);
src/routes/conversation/+server.ts CHANGED
@@ -7,6 +7,7 @@ import { z } from "zod";
7
  import type { Message } from "$lib/types/Message";
8
  import { models, validateModel } from "$lib/server/models";
9
  import { defaultEmbeddingModel } from "$lib/server/embeddingModels";
 
10
 
11
  export const POST: RequestHandler = async ({ locals, request }) => {
12
  const body = await request.text();
@@ -24,7 +25,7 @@ export const POST: RequestHandler = async ({ locals, request }) => {
24
 
25
  let messages: Message[] = [
26
  {
27
- id: crypto.randomUUID(),
28
  from: "system",
29
  content: values.preprompt ?? "",
30
  createdAt: new Date(),
7
  import type { Message } from "$lib/types/Message";
8
  import { models, validateModel } from "$lib/server/models";
9
  import { defaultEmbeddingModel } from "$lib/server/embeddingModels";
10
+ import { v4 } from "uuid";
11
 
12
  export const POST: RequestHandler = async ({ locals, request }) => {
13
  const body = await request.text();
25
 
26
  let messages: Message[] = [
27
  {
28
+ id: v4(),
29
  from: "system",
30
  content: values.preprompt ?? "",
31
  createdAt: new Date(),
src/routes/conversation/[id]/+page.svelte CHANGED
@@ -18,6 +18,7 @@
18
  import { addChildren } from "$lib/utils/tree/addChildren";
19
  import { addSibling } from "$lib/utils/tree/addSibling";
20
  import { createConvTreeStore } from "$lib/stores/convTree";
 
21
 
22
  export let data;
23
 
@@ -72,7 +73,7 @@
72
  isContinue = false,
73
  }: {
74
  prompt?: string;
75
- messageId?: ReturnType<typeof crypto.randomUUID>;
76
  isRetry?: boolean;
77
  isContinue?: boolean;
78
  }): Promise<void> {
18
  import { addChildren } from "$lib/utils/tree/addChildren";
19
  import { addSibling } from "$lib/utils/tree/addSibling";
20
  import { createConvTreeStore } from "$lib/stores/convTree";
21
+ import type { v4 } from "uuid";
22
 
23
  export let data;
24
 
73
  isContinue = false,
74
  }: {
75
  prompt?: string;
76
+ messageId?: ReturnType<typeof v4>;
77
  isRetry?: boolean;
78
  isContinue?: boolean;
79
  }): Promise<void> {
vite.config.ts CHANGED
@@ -26,6 +26,6 @@ export default defineConfig({
26
  loadTTFAsArrayBuffer(),
27
  ],
28
  optimizeDeps: {
29
- include: ["browser-image-resizer"],
30
  },
31
  });
26
  loadTTFAsArrayBuffer(),
27
  ],
28
  optimizeDeps: {
29
+ include: ["browser-image-resizer", "uuid"],
30
  },
31
  });