@lobehub/chat 0.162.25 → 0.163.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.
Files changed (84) hide show
  1. package/.github/workflows/release.yml +21 -2
  2. package/.github/workflows/sync.yml +1 -1
  3. package/.github/workflows/test.yml +35 -4
  4. package/CHANGELOG.md +25 -0
  5. package/LICENSE +38 -21
  6. package/codecov.yml +11 -0
  7. package/drizzle.config.ts +29 -0
  8. package/next.config.mjs +3 -0
  9. package/package.json +24 -4
  10. package/scripts/migrateServerDB/index.ts +30 -0
  11. package/src/app/(main)/(mobile)/me/(home)/features/useCategory.tsx +2 -1
  12. package/src/app/(main)/chat/@session/features/SessionListContent/List/Item/Actions.tsx +95 -88
  13. package/src/app/(main)/chat/settings/features/HeaderContent.tsx +37 -31
  14. package/src/app/api/webhooks/clerk/__tests__/fixtures/createUser.json +73 -0
  15. package/src/app/api/webhooks/clerk/route.ts +159 -0
  16. package/src/app/api/webhooks/clerk/validateRequest.ts +22 -0
  17. package/src/app/trpc/edge/[trpc]/route.ts +1 -1
  18. package/src/app/trpc/lambda/[trpc]/route.ts +26 -0
  19. package/src/config/auth.ts +2 -0
  20. package/src/config/db.ts +13 -1
  21. package/src/database/server/core/db.ts +44 -0
  22. package/src/database/server/core/dbForTest.ts +45 -0
  23. package/src/database/server/index.ts +1 -0
  24. package/src/database/server/migrations/0000_init.sql +439 -0
  25. package/src/database/server/migrations/0001_add_client_id.sql +9 -0
  26. package/src/database/server/migrations/0002_amusing_puma.sql +9 -0
  27. package/src/database/server/migrations/meta/0000_snapshot.json +1583 -0
  28. package/src/database/server/migrations/meta/0001_snapshot.json +1636 -0
  29. package/src/database/server/migrations/meta/0002_snapshot.json +1630 -0
  30. package/src/database/server/migrations/meta/_journal.json +27 -0
  31. package/src/database/server/models/__tests__/file.test.ts +140 -0
  32. package/src/database/server/models/__tests__/message.test.ts +847 -0
  33. package/src/database/server/models/__tests__/plugin.test.ts +172 -0
  34. package/src/database/server/models/__tests__/session.test.ts +595 -0
  35. package/src/database/server/models/__tests__/topic.test.ts +623 -0
  36. package/src/database/server/models/__tests__/user.test.ts +173 -0
  37. package/src/database/server/models/_template.ts +44 -0
  38. package/src/database/server/models/file.ts +51 -0
  39. package/src/database/server/models/message.ts +378 -0
  40. package/src/database/server/models/plugin.ts +63 -0
  41. package/src/database/server/models/session.ts +290 -0
  42. package/src/database/server/models/sessionGroup.ts +69 -0
  43. package/src/database/server/models/topic.ts +265 -0
  44. package/src/database/server/models/user.ts +138 -0
  45. package/src/database/server/modules/DataImporter/__tests__/fixtures/messages.json +1101 -0
  46. package/src/database/server/modules/DataImporter/__tests__/index.test.ts +954 -0
  47. package/src/database/server/modules/DataImporter/index.ts +333 -0
  48. package/src/database/server/schemas/_id.ts +15 -0
  49. package/src/database/server/schemas/lobechat.ts +601 -0
  50. package/src/database/server/utils/idGenerator.test.ts +39 -0
  51. package/src/database/server/utils/idGenerator.ts +26 -0
  52. package/src/features/User/UserPanel/useMenu.tsx +43 -37
  53. package/src/libs/trpc/client.ts +52 -3
  54. package/src/server/files/s3.ts +21 -1
  55. package/src/server/keyVaultsEncrypt/index.test.ts +62 -0
  56. package/src/server/keyVaultsEncrypt/index.ts +93 -0
  57. package/src/server/mock.ts +1 -1
  58. package/src/server/routers/{index.ts → edge/index.ts} +3 -3
  59. package/src/server/routers/lambda/file.ts +49 -0
  60. package/src/server/routers/lambda/importer.ts +54 -0
  61. package/src/server/routers/lambda/index.ts +28 -0
  62. package/src/server/routers/lambda/message.ts +165 -0
  63. package/src/server/routers/lambda/plugin.ts +100 -0
  64. package/src/server/routers/lambda/session.ts +194 -0
  65. package/src/server/routers/lambda/sessionGroup.ts +77 -0
  66. package/src/server/routers/lambda/topic.ts +134 -0
  67. package/src/server/routers/lambda/user.ts +57 -0
  68. package/src/services/file/index.ts +4 -7
  69. package/src/services/file/server.ts +45 -0
  70. package/src/services/import/index.ts +4 -1
  71. package/src/services/import/server.ts +115 -0
  72. package/src/services/message/index.ts +4 -8
  73. package/src/services/message/server.ts +93 -0
  74. package/src/services/plugin/index.ts +4 -9
  75. package/src/services/plugin/server.ts +46 -0
  76. package/src/services/session/index.ts +4 -8
  77. package/src/services/session/server.ts +148 -0
  78. package/src/services/topic/index.ts +4 -9
  79. package/src/services/topic/server.ts +68 -0
  80. package/src/services/user/index.ts +4 -9
  81. package/src/services/user/server.ts +28 -0
  82. package/tests/setup-db.ts +7 -0
  83. package/vitest.config.ts +2 -1
  84. package/vitest.server.config.ts +23 -0
@@ -0,0 +1,138 @@
1
+ import { TRPCError } from '@trpc/server';
2
+ import { eq } from 'drizzle-orm';
3
+ import { DeepPartial } from 'utility-types';
4
+
5
+ import { serverDB } from '@/database/server';
6
+ import { KeyVaultsGateKeeper } from '@/server/keyVaultsEncrypt';
7
+ import { UserPreference } from '@/types/user';
8
+ import { UserSettings } from '@/types/user/settings';
9
+ import { merge } from '@/utils/merge';
10
+
11
+ import { NewUser, UserItem, userSettings, users } from '../schemas/lobechat';
12
+ import { SessionModel } from './session';
13
+
14
+ export class UserModel {
15
+ createUser = async (params: NewUser) => {
16
+ const [user] = await serverDB
17
+ .insert(users)
18
+ .values({ ...params })
19
+ .returning();
20
+
21
+ // Create an inbox session for the user
22
+ const model = new SessionModel(user.id);
23
+
24
+ await model.createInbox();
25
+ };
26
+
27
+ deleteUser = async (id: string) => {
28
+ return serverDB.delete(users).where(eq(users.id, id));
29
+ };
30
+
31
+ findById = async (id: string) => {
32
+ return serverDB.query.users.findFirst({ where: eq(users.id, id) });
33
+ };
34
+
35
+ getUserState = async (id: string) => {
36
+ const result = await serverDB
37
+ .select({
38
+ isOnboarded: users.isOnboarded,
39
+ preference: users.preference,
40
+
41
+ settingsDefaultAgent: userSettings.defaultAgent,
42
+ settingsGeneral: userSettings.general,
43
+ settingsKeyVaults: userSettings.keyVaults,
44
+ settingsLanguageModel: userSettings.languageModel,
45
+ settingsSystemAgent: userSettings.systemAgent,
46
+ settingsTTS: userSettings.tts,
47
+ settingsTool: userSettings.tool,
48
+ })
49
+ .from(users)
50
+ .where(eq(users.id, id))
51
+ .leftJoin(userSettings, eq(users.id, userSettings.id));
52
+
53
+ if (!result || !result[0]) {
54
+ throw new TRPCError({ code: 'UNAUTHORIZED', message: 'user not found' });
55
+ }
56
+
57
+ const state = result[0];
58
+
59
+ // Decrypt keyVaults
60
+ let decryptKeyVaults = {};
61
+ if (state.settingsKeyVaults) {
62
+ const gateKeeper = await KeyVaultsGateKeeper.initWithEnvKey();
63
+ const { wasAuthentic, plaintext } = await gateKeeper.decrypt(state.settingsKeyVaults);
64
+
65
+ if (wasAuthentic) {
66
+ try {
67
+ decryptKeyVaults = JSON.parse(plaintext);
68
+ } catch (e) {
69
+ console.error(`Failed to parse keyVaults ,userId: ${id}. Error:`, e);
70
+ }
71
+ }
72
+ }
73
+
74
+ const settings: DeepPartial<UserSettings> = {
75
+ defaultAgent: state.settingsDefaultAgent || {},
76
+ general: state.settingsGeneral || {},
77
+ keyVaults: decryptKeyVaults,
78
+ languageModel: state.settingsLanguageModel || {},
79
+ systemAgent: state.settingsSystemAgent || {},
80
+ tool: state.settingsTool || {},
81
+ tts: state.settingsTTS || {},
82
+ };
83
+
84
+ return {
85
+ isOnboarded: state.isOnboarded,
86
+ preference: state.preference as UserPreference,
87
+ settings,
88
+ userId: id,
89
+ };
90
+ };
91
+
92
+ async updateUser(id: string, value: Partial<UserItem>) {
93
+ return serverDB
94
+ .update(users)
95
+ .set({ ...value, updatedAt: new Date() })
96
+ .where(eq(users.id, id));
97
+ }
98
+
99
+ async deleteSetting(id: string) {
100
+ return serverDB.delete(userSettings).where(eq(userSettings.id, id));
101
+ }
102
+
103
+ async updateSetting(id: string, value: Partial<UserSettings>) {
104
+ const { keyVaults, ...res } = value;
105
+
106
+ // Encrypt keyVaults
107
+ let encryptedKeyVaults: string | null = null;
108
+
109
+ if (keyVaults) {
110
+ // TODO: better to add a validation
111
+ const data = JSON.stringify(keyVaults);
112
+ const gateKeeper = await KeyVaultsGateKeeper.initWithEnvKey();
113
+
114
+ encryptedKeyVaults = await gateKeeper.encrypt(data);
115
+ }
116
+
117
+ const newValue = { ...res, keyVaults: encryptedKeyVaults };
118
+
119
+ // update or create user settings
120
+ const settings = await serverDB.query.userSettings.findFirst({ where: eq(users.id, id) });
121
+ if (!settings) {
122
+ await serverDB.insert(userSettings).values({ id, ...newValue });
123
+ return;
124
+ }
125
+
126
+ return serverDB.update(userSettings).set(newValue).where(eq(userSettings.id, id));
127
+ }
128
+
129
+ async updatePreference(id: string, value: Partial<UserPreference>) {
130
+ const user = await serverDB.query.users.findFirst({ where: eq(users.id, id) });
131
+ if (!user) return;
132
+
133
+ return serverDB
134
+ .update(users)
135
+ .set({ preference: merge(user.preference, value) })
136
+ .where(eq(users.id, id));
137
+ }
138
+ }