@lobehub/chat 1.19.30 → 1.19.32

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 (34) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/locales/ar/models.json +12 -0
  3. package/locales/bg-BG/models.json +12 -0
  4. package/locales/de-DE/models.json +12 -0
  5. package/locales/en-US/models.json +12 -0
  6. package/locales/es-ES/models.json +12 -0
  7. package/locales/fr-FR/models.json +12 -0
  8. package/locales/it-IT/models.json +12 -0
  9. package/locales/ja-JP/models.json +12 -0
  10. package/locales/ko-KR/models.json +12 -0
  11. package/locales/nl-NL/models.json +12 -0
  12. package/locales/pl-PL/models.json +12 -0
  13. package/locales/pt-BR/models.json +12 -0
  14. package/locales/ru-RU/models.json +12 -0
  15. package/locales/tr-TR/models.json +12 -0
  16. package/locales/vi-VN/models.json +12 -0
  17. package/locales/zh-CN/models.json +13 -1
  18. package/locales/zh-TW/models.json +12 -0
  19. package/next.config.mjs +5 -7
  20. package/package.json +3 -2
  21. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/TextArea.test.tsx +1 -0
  22. package/src/app/sw.ts +26 -0
  23. package/src/config/modelProviders/google.ts +54 -2
  24. package/src/config/modelProviders/taichu.ts +5 -2
  25. package/src/features/FileViewer/Renderer/Image/index.tsx +1 -0
  26. package/src/features/PWAInstall/Install.tsx +80 -0
  27. package/src/features/PWAInstall/index.tsx +6 -61
  28. package/src/libs/agent-runtime/google/index.test.ts +99 -5
  29. package/src/libs/agent-runtime/google/index.ts +58 -30
  30. package/src/server/services/discover/index.ts +1 -1
  31. package/src/services/message/server.ts +1 -1
  32. package/src/services/session/server.ts +2 -2
  33. package/src/store/chat/slices/plugin/action.ts +3 -1
  34. package/tsconfig.json +3 -3
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  Content,
3
+ FunctionCallPart,
3
4
  FunctionDeclaration,
4
5
  FunctionDeclarationSchemaProperty,
5
6
  FunctionDeclarationSchemaType,
@@ -11,6 +12,7 @@ import { JSONSchema7 } from 'json-schema';
11
12
  import { transform } from 'lodash-es';
12
13
 
13
14
  import { imageUrlToBase64 } from '@/utils/imageToBase64';
15
+ import { safeParseJSON } from '@/utils/safeParseJSON';
14
16
 
15
17
  import { LobeRuntimeAI } from '../BaseAI';
16
18
  import { AgentRuntimeErrorType, ILobeAgentRuntimeErrorType } from '../error';
@@ -50,8 +52,9 @@ export class LobeGoogleAI implements LobeRuntimeAI {
50
52
  this.baseURL = baseURL;
51
53
  }
52
54
 
53
- async chat(payload: ChatStreamPayload, options?: ChatCompetitionOptions) {
55
+ async chat(rawPayload: ChatStreamPayload, options?: ChatCompetitionOptions) {
54
56
  try {
57
+ const payload = this.buildPayload(rawPayload);
55
58
  const model = payload.model;
56
59
 
57
60
  const contents = await this.buildGoogleMessages(payload.messages, model);
@@ -88,7 +91,11 @@ export class LobeGoogleAI implements LobeRuntimeAI {
88
91
  },
89
92
  { apiVersion: 'v1beta', baseUrl: this.baseURL },
90
93
  )
91
- .generateContentStream({ contents, tools: this.buildGoogleTools(payload.tools) });
94
+ .generateContentStream({
95
+ contents,
96
+ systemInstruction: payload.system as string,
97
+ tools: this.buildGoogleTools(payload.tools),
98
+ });
92
99
 
93
100
  const googleStream = googleGenAIResultToStream(geminiStreamResult);
94
101
  const [prod, useForDebug] = googleStream.tee();
@@ -111,6 +118,16 @@ export class LobeGoogleAI implements LobeRuntimeAI {
111
118
  }
112
119
  }
113
120
 
121
+ private buildPayload(payload: ChatStreamPayload) {
122
+ const system_message = payload.messages.find((m) => m.role === 'system');
123
+ const user_messages = payload.messages.filter((m) => m.role !== 'system');
124
+
125
+ return {
126
+ ...payload,
127
+ messages: user_messages,
128
+ system: system_message?.content,
129
+ };
130
+ }
114
131
  private convertContentToGooglePart = async (content: UserMessageContentPart): Promise<Part> => {
115
132
  switch (content.type) {
116
133
  case 'text': {
@@ -152,6 +169,17 @@ export class LobeGoogleAI implements LobeRuntimeAI {
152
169
  message: OpenAIChatMessage,
153
170
  ): Promise<Content> => {
154
171
  const content = message.content as string | UserMessageContentPart[];
172
+ if (!!message.tool_calls) {
173
+ return {
174
+ parts: message.tool_calls.map<FunctionCallPart>((tool) => ({
175
+ functionCall: {
176
+ args: safeParseJSON(tool.function.arguments)!,
177
+ name: tool.function.name,
178
+ },
179
+ })),
180
+ role: 'function',
181
+ };
182
+ }
155
183
 
156
184
  return {
157
185
  parts:
@@ -168,44 +196,44 @@ export class LobeGoogleAI implements LobeRuntimeAI {
168
196
  messages: OpenAIChatMessage[],
169
197
  model: string,
170
198
  ): Promise<Content[]> => {
171
- // if the model is gemini-1.5-pro-latest, we don't need any special handling
172
- if (model === 'gemini-1.5-pro-latest') {
173
- const pools = messages
174
- .filter((message) => message.role !== 'function')
175
- .map(async (msg) => await this.convertOAIMessagesToGoogleMessage(msg));
199
+ // if the model is gemini-1.0 we don't need to pair messages
200
+ if (model.startsWith('gemini-1.0')) {
201
+ const contents: Content[] = [];
202
+ let lastRole = 'model';
203
+
204
+ for (const message of messages) {
205
+ // current to filter function message
206
+ if (message.role === 'function') {
207
+ continue;
208
+ }
209
+ const googleMessage = await this.convertOAIMessagesToGoogleMessage(message);
176
210
 
177
- return Promise.all(pools);
178
- }
211
+ // if the last message is a model message and the current message is a model message
212
+ // then we need to add a user message to separate them
213
+ if (lastRole === googleMessage.role) {
214
+ contents.push({ parts: [{ text: '' }], role: lastRole === 'user' ? 'model' : 'user' });
215
+ }
179
216
 
180
- const contents: Content[] = [];
181
- let lastRole = 'model';
217
+ // add the current message to the contents
218
+ contents.push(googleMessage);
182
219
 
183
- for (const message of messages) {
184
- // current to filter function message
185
- if (message.role === 'function') {
186
- continue;
220
+ // update the last role
221
+ lastRole = googleMessage.role;
187
222
  }
188
- const googleMessage = await this.convertOAIMessagesToGoogleMessage(message);
189
223
 
190
- // if the last message is a model message and the current message is a model message
191
- // then we need to add a user message to separate them
192
- if (lastRole === googleMessage.role) {
193
- contents.push({ parts: [{ text: '' }], role: lastRole === 'user' ? 'model' : 'user' });
224
+ // if the last message is a user message, then we need to add a model message to separate them
225
+ if (lastRole === 'model') {
226
+ contents.push({ parts: [{ text: '' }], role: 'user' });
194
227
  }
195
228
 
196
- // add the current message to the contents
197
- contents.push(googleMessage);
198
-
199
- // update the last role
200
- lastRole = googleMessage.role;
229
+ return contents;
201
230
  }
202
231
 
203
- // if the last message is a user message, then we need to add a model message to separate them
204
- if (lastRole === 'model') {
205
- contents.push({ parts: [{ text: '' }], role: 'user' });
206
- }
232
+ const pools = messages
233
+ .filter((message) => message.role !== 'function')
234
+ .map(async (msg) => await this.convertOAIMessagesToGoogleMessage(msg));
207
235
 
208
- return contents;
236
+ return Promise.all(pools);
209
237
  };
210
238
 
211
239
  private parseErrorMessage(message: string): {
@@ -212,7 +212,7 @@ export class DiscoverService {
212
212
  // Providers
213
213
 
214
214
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
215
- getProviderList = async (locale: Locales): Promise<DiscoverProviderItem[]> => {
215
+ getProviderList = async (_locale: Locales): Promise<DiscoverProviderItem[]> => {
216
216
  const list = DEFAULT_MODEL_PROVIDER_LIST.filter((item) => item.chatModels.length > 0);
217
217
  return list.map((item) => {
218
218
  const provider = {
@@ -79,7 +79,7 @@ export class ServerService implements IMessageService {
79
79
  return lambdaClient.message.updatePluginState.mutate({ id, value });
80
80
  }
81
81
 
82
- bindMessagesToTopic(topicId: string, messageIds: string[]): Promise<any> {
82
+ bindMessagesToTopic(_topicId: string, _messageIds: string[]): Promise<any> {
83
83
  throw new Error('Method not implemented.');
84
84
  }
85
85
 
@@ -91,7 +91,7 @@ export class ServerService implements ISessionService {
91
91
  return lambdaClient.session.updateSessionChatConfig.mutate({ id, value }, { signal });
92
92
  }
93
93
 
94
- getSessionsByType(type: 'agent' | 'group' | 'all' = 'all'): Promise<LobeSessions> {
94
+ getSessionsByType(_type: 'agent' | 'group' | 'all' = 'all'): Promise<LobeSessions> {
95
95
  // TODO: need be fixed
96
96
  // @ts-ignore
97
97
  return lambdaClient.session.getSessions.query({});
@@ -121,7 +121,7 @@ export class ServerService implements ISessionService {
121
121
  return lambdaClient.sessionGroup.getSessionGroup.query();
122
122
  }
123
123
 
124
- batchCreateSessionGroups(groups: SessionGroups): Promise<BatchTaskResult> {
124
+ batchCreateSessionGroups(_groups: SessionGroups): Promise<BatchTaskResult> {
125
125
  return Promise.resolve({ added: 0, ids: [], skips: [], success: true });
126
126
  }
127
127
 
@@ -141,7 +141,9 @@ export const chatPlugin: StateCreator<
141
141
 
142
142
  try {
143
143
  content = JSON.parse(data);
144
- } catch {}
144
+ } catch {
145
+ /* empty block */
146
+ }
145
147
 
146
148
  if (!content) return;
147
149
 
package/tsconfig.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json.schemastore.org/tsconfig",
3
3
  "compilerOptions": {
4
4
  "target": "ESNext",
5
- "lib": ["dom", "dom.iterable", "esnext"],
5
+ "lib": ["dom", "dom.iterable", "esnext", "webworker"],
6
6
  "allowJs": true,
7
7
  "skipLibCheck": true,
8
8
  "strict": true,
@@ -16,7 +16,7 @@
16
16
  "jsx": "preserve",
17
17
  "incremental": true,
18
18
  "baseUrl": ".",
19
- "types": ["vitest/globals"],
19
+ "types": ["vitest/globals", "@serwist/next/typings"],
20
20
  "paths": {
21
21
  "@/*": ["./src/*"],
22
22
  "~test-utils": ["./tests/utils.tsx"]
@@ -27,7 +27,7 @@
27
27
  }
28
28
  ]
29
29
  },
30
- "exclude": ["node_modules"],
30
+ "exclude": ["node_modules", "public/sw.js"],
31
31
  "include": [
32
32
  "next-env.d.ts",
33
33
  "vitest.config.ts",