@lobehub/chat 0.147.21 → 0.148.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.
- package/CHANGELOG.md +42 -0
- package/locales/ar/setting.json +4 -0
- package/locales/bg-BG/setting.json +4 -0
- package/locales/de-DE/setting.json +4 -0
- package/locales/en-US/setting.json +4 -0
- package/locales/es-ES/setting.json +4 -0
- package/locales/fr-FR/setting.json +4 -0
- package/locales/it-IT/setting.json +4 -0
- package/locales/ja-JP/setting.json +4 -0
- package/locales/ko-KR/setting.json +4 -0
- package/locales/nl-NL/setting.json +4 -0
- package/locales/pl-PL/setting.json +4 -0
- package/locales/pt-BR/setting.json +4 -0
- package/locales/ru-RU/setting.json +4 -0
- package/locales/tr-TR/setting.json +4 -0
- package/locales/vi-VN/setting.json +4 -0
- package/locales/zh-CN/setting.json +4 -0
- package/locales/zh-TW/setting.json +4 -0
- package/package.json +3 -2
- package/public/favicon-32x32.ico +0 -0
- package/public/favicon.ico +0 -0
- package/public/icons/apple-touch-icon.png +0 -0
- package/src/app/api/chat/[provider]/route.test.ts +5 -7
- package/src/app/api/chat/[provider]/route.ts +13 -7
- package/src/app/api/chat/agentRuntime.test.ts +195 -451
- package/src/app/api/chat/agentRuntime.ts +197 -280
- package/src/app/api/chat/models/[provider]/route.ts +2 -2
- package/src/app/chat/features/TopicListContent/Topic/TopicContent.tsx +2 -2
- package/src/app/metadata.ts +3 -5
- package/src/app/settings/llm/components/ProviderConfig/index.tsx +23 -1
- package/src/app/settings/llm/index.tsx +2 -2
- package/src/app/settings/llm/page.tsx +1 -5
- package/src/features/ChatInput/Topic/index.tsx +6 -2
- package/src/features/Conversation/components/ChatItem/index.tsx +8 -3
- package/src/libs/agent-runtime/AgentRuntime.test.ts +400 -0
- package/src/libs/agent-runtime/AgentRuntime.ts +192 -0
- package/src/libs/agent-runtime/index.ts +1 -0
- package/src/libs/swr/index.ts +9 -0
- package/src/locales/default/setting.ts +4 -0
- package/src/services/__tests__/chat.test.ts +287 -1
- package/src/services/chat.ts +148 -2
- package/src/store/chat/slices/message/action.ts +80 -42
- package/src/store/chat/slices/message/initialState.ts +1 -1
- package/src/store/chat/slices/message/reducer.ts +32 -1
- package/src/store/chat/slices/topic/action.test.ts +25 -2
- package/src/store/chat/slices/topic/action.ts +24 -7
- package/src/store/chat/slices/topic/reducer.test.ts +141 -0
- package/src/store/chat/slices/topic/reducer.ts +67 -0
- package/src/store/global/slices/settings/selectors/modelConfig.ts +13 -0
- package/src/store/session/slices/session/action.ts +4 -5
- package/src/types/settings/modelProvider.ts +4 -0
- package/vercel.json +1 -1
|
@@ -7,25 +7,7 @@ import {
|
|
|
7
7
|
TracePayload,
|
|
8
8
|
TraceTagMap,
|
|
9
9
|
} from '@/const/trace';
|
|
10
|
-
import {
|
|
11
|
-
ChatStreamPayload,
|
|
12
|
-
LobeAnthropicAI,
|
|
13
|
-
LobeAzureOpenAI,
|
|
14
|
-
LobeBedrockAI,
|
|
15
|
-
LobeGoogleAI,
|
|
16
|
-
LobeGroq,
|
|
17
|
-
LobeMistralAI,
|
|
18
|
-
LobeMoonshotAI,
|
|
19
|
-
LobeOllamaAI,
|
|
20
|
-
LobeOpenAI,
|
|
21
|
-
LobeOpenRouterAI,
|
|
22
|
-
LobePerplexityAI,
|
|
23
|
-
LobeRuntimeAI,
|
|
24
|
-
LobeTogetherAI,
|
|
25
|
-
LobeZeroOneAI,
|
|
26
|
-
LobeZhipuAI,
|
|
27
|
-
ModelProvider,
|
|
28
|
-
} from '@/libs/agent-runtime';
|
|
10
|
+
import { AgentRuntime, ChatStreamPayload, ModelProvider } from '@/libs/agent-runtime';
|
|
29
11
|
import { TraceClient } from '@/libs/traces';
|
|
30
12
|
|
|
31
13
|
import apiKeyManager from './apiKeyManager';
|
|
@@ -36,272 +18,207 @@ export interface AgentChatOptions {
|
|
|
36
18
|
trace?: TracePayload;
|
|
37
19
|
}
|
|
38
20
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
},
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
async models() {
|
|
110
|
-
return this._runtime.models?.();
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
static async initializeWithUserPayload(provider: string, payload: JWTPayload) {
|
|
114
|
-
let runtimeModel: LobeRuntimeAI;
|
|
115
|
-
|
|
116
|
-
switch (provider) {
|
|
117
|
-
default:
|
|
118
|
-
case 'oneapi':
|
|
119
|
-
case ModelProvider.OpenAI: {
|
|
120
|
-
runtimeModel = this.initOpenAI(payload);
|
|
121
|
-
break;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
case ModelProvider.Azure: {
|
|
125
|
-
runtimeModel = this.initAzureOpenAI(payload);
|
|
126
|
-
break;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
case ModelProvider.ZhiPu: {
|
|
130
|
-
runtimeModel = await this.initZhipu(payload);
|
|
131
|
-
break;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
case ModelProvider.Google: {
|
|
135
|
-
runtimeModel = this.initGoogle(payload);
|
|
136
|
-
break;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
case ModelProvider.Moonshot: {
|
|
140
|
-
runtimeModel = this.initMoonshot(payload);
|
|
141
|
-
break;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
case ModelProvider.Bedrock: {
|
|
145
|
-
runtimeModel = this.initBedrock(payload);
|
|
146
|
-
break;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
case ModelProvider.Ollama: {
|
|
150
|
-
runtimeModel = this.initOllama(payload);
|
|
151
|
-
break;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
case ModelProvider.Perplexity: {
|
|
155
|
-
runtimeModel = this.initPerplexity(payload);
|
|
156
|
-
break;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
case ModelProvider.Anthropic: {
|
|
160
|
-
runtimeModel = this.initAnthropic(payload);
|
|
161
|
-
break;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
case ModelProvider.Mistral: {
|
|
165
|
-
runtimeModel = this.initMistral(payload);
|
|
166
|
-
break;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
case ModelProvider.Groq: {
|
|
170
|
-
runtimeModel = this.initGroq(payload);
|
|
171
|
-
break;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
case ModelProvider.OpenRouter: {
|
|
175
|
-
runtimeModel = this.initOpenRouter(payload);
|
|
176
|
-
break;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
case ModelProvider.TogetherAI: {
|
|
180
|
-
runtimeModel = this.initTogetherAI(payload);
|
|
181
|
-
break;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
case ModelProvider.ZeroOne: {
|
|
185
|
-
runtimeModel = this.initZeroOne(payload);
|
|
186
|
-
break;
|
|
21
|
+
/**
|
|
22
|
+
* Retrieves the options object from environment and apikeymanager
|
|
23
|
+
* based on the provider and payload.
|
|
24
|
+
*
|
|
25
|
+
* @param provider - The model provider.
|
|
26
|
+
* @param payload - The JWT payload.
|
|
27
|
+
* @returns The options object.
|
|
28
|
+
*/
|
|
29
|
+
const getLlmOptionsFromPayload = (provider: string, payload: JWTPayload) => {
|
|
30
|
+
switch (provider) {
|
|
31
|
+
default: // Use Openai options as default
|
|
32
|
+
case ModelProvider.OpenAI: {
|
|
33
|
+
const { OPENAI_API_KEY, OPENAI_PROXY_URL } = getServerConfig();
|
|
34
|
+
const openaiApiKey = payload?.apiKey || OPENAI_API_KEY;
|
|
35
|
+
const baseURL = payload?.endpoint || OPENAI_PROXY_URL;
|
|
36
|
+
const apiKey = apiKeyManager.pick(openaiApiKey);
|
|
37
|
+
return {
|
|
38
|
+
apiKey,
|
|
39
|
+
baseURL,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
case ModelProvider.Azure: {
|
|
43
|
+
const { AZURE_API_KEY, AZURE_API_VERSION, AZURE_ENDPOINT } = getServerConfig();
|
|
44
|
+
const apiKey = apiKeyManager.pick(payload?.apiKey || AZURE_API_KEY);
|
|
45
|
+
const endpoint = payload?.endpoint || AZURE_ENDPOINT;
|
|
46
|
+
const apiVersion = payload?.azureApiVersion || AZURE_API_VERSION;
|
|
47
|
+
return {
|
|
48
|
+
apiVersion,
|
|
49
|
+
apikey: apiKey,
|
|
50
|
+
endpoint,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
case ModelProvider.ZhiPu: {
|
|
54
|
+
const { ZHIPU_API_KEY } = getServerConfig();
|
|
55
|
+
const apiKey = apiKeyManager.pick(payload?.apiKey || ZHIPU_API_KEY);
|
|
56
|
+
return {
|
|
57
|
+
apiKey,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
case ModelProvider.Google: {
|
|
61
|
+
const { GOOGLE_API_KEY, GOOGLE_PROXY_URL } = getServerConfig();
|
|
62
|
+
const apiKey = apiKeyManager.pick(payload?.apiKey || GOOGLE_API_KEY);
|
|
63
|
+
const baseURL = payload?.endpoint || GOOGLE_PROXY_URL;
|
|
64
|
+
return {
|
|
65
|
+
apiKey,
|
|
66
|
+
baseURL,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
case ModelProvider.Moonshot: {
|
|
70
|
+
const { MOONSHOT_API_KEY, MOONSHOT_PROXY_URL } = getServerConfig();
|
|
71
|
+
const apiKey = apiKeyManager.pick(payload?.apiKey || MOONSHOT_API_KEY);
|
|
72
|
+
return {
|
|
73
|
+
apiKey,
|
|
74
|
+
baseURL: MOONSHOT_PROXY_URL,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
case ModelProvider.Bedrock: {
|
|
78
|
+
const { AWS_SECRET_ACCESS_KEY, AWS_ACCESS_KEY_ID, AWS_REGION } = getServerConfig();
|
|
79
|
+
let accessKeyId: string | undefined = AWS_ACCESS_KEY_ID;
|
|
80
|
+
let accessKeySecret: string | undefined = AWS_SECRET_ACCESS_KEY;
|
|
81
|
+
let region = AWS_REGION;
|
|
82
|
+
// if the payload has the api key, use user
|
|
83
|
+
if (payload.apiKey) {
|
|
84
|
+
accessKeyId = payload?.awsAccessKeyId;
|
|
85
|
+
accessKeySecret = payload?.awsSecretAccessKey;
|
|
86
|
+
region = payload?.awsRegion;
|
|
187
87
|
}
|
|
88
|
+
return {
|
|
89
|
+
accessKeyId,
|
|
90
|
+
accessKeySecret,
|
|
91
|
+
region,
|
|
92
|
+
};
|
|
188
93
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
94
|
+
case ModelProvider.Ollama: {
|
|
95
|
+
const { OLLAMA_PROXY_URL } = getServerConfig();
|
|
96
|
+
const baseURL = payload?.endpoint || OLLAMA_PROXY_URL;
|
|
97
|
+
return {
|
|
98
|
+
baseURL,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
case ModelProvider.Perplexity: {
|
|
102
|
+
const { PERPLEXITY_API_KEY } = getServerConfig();
|
|
103
|
+
const apiKey = apiKeyManager.pick(payload?.apiKey || PERPLEXITY_API_KEY);
|
|
104
|
+
return {
|
|
105
|
+
apiKey,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
case ModelProvider.Anthropic: {
|
|
109
|
+
const { ANTHROPIC_API_KEY, ANTHROPIC_PROXY_URL } = getServerConfig();
|
|
110
|
+
const apiKey = apiKeyManager.pick(payload?.apiKey || ANTHROPIC_API_KEY);
|
|
111
|
+
const baseURL = payload?.endpoint || ANTHROPIC_PROXY_URL;
|
|
112
|
+
return {
|
|
113
|
+
apiKey,
|
|
114
|
+
baseURL,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
case ModelProvider.Mistral: {
|
|
118
|
+
const { MISTRAL_API_KEY } = getServerConfig();
|
|
119
|
+
const apiKey = apiKeyManager.pick(payload?.apiKey || MISTRAL_API_KEY);
|
|
120
|
+
return {
|
|
121
|
+
apiKey,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
case ModelProvider.Groq: {
|
|
125
|
+
const { GROQ_API_KEY } = getServerConfig();
|
|
126
|
+
const apiKey = apiKeyManager.pick(payload?.apiKey || GROQ_API_KEY);
|
|
127
|
+
return {
|
|
128
|
+
apiKey,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
case ModelProvider.OpenRouter: {
|
|
132
|
+
const { OPENROUTER_API_KEY } = getServerConfig();
|
|
133
|
+
const apiKey = apiKeyManager.pick(payload?.apiKey || OPENROUTER_API_KEY);
|
|
134
|
+
return {
|
|
135
|
+
apiKey,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
case ModelProvider.TogetherAI: {
|
|
139
|
+
const { TOGETHERAI_API_KEY } = getServerConfig();
|
|
140
|
+
const apiKey = apiKeyManager.pick(payload?.apiKey || TOGETHERAI_API_KEY);
|
|
141
|
+
return {
|
|
142
|
+
apiKey,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
case ModelProvider.ZeroOne: {
|
|
146
|
+
const { ZEROONE_API_KEY } = getServerConfig();
|
|
147
|
+
const apiKey = apiKeyManager.pick(payload?.apiKey || ZEROONE_API_KEY);
|
|
148
|
+
return {
|
|
149
|
+
apiKey,
|
|
150
|
+
};
|
|
245
151
|
}
|
|
246
|
-
|
|
247
|
-
return new LobeBedrockAI({ accessKeyId, accessKeySecret, region });
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
private static initOllama(payload: JWTPayload) {
|
|
251
|
-
const { OLLAMA_PROXY_URL } = getServerConfig();
|
|
252
|
-
const baseURL = payload?.endpoint || OLLAMA_PROXY_URL;
|
|
253
|
-
|
|
254
|
-
return new LobeOllamaAI({ baseURL });
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
private static initPerplexity(payload: JWTPayload) {
|
|
258
|
-
const { PERPLEXITY_API_KEY } = getServerConfig();
|
|
259
|
-
const apiKey = apiKeyManager.pick(payload?.apiKey || PERPLEXITY_API_KEY);
|
|
260
|
-
|
|
261
|
-
return new LobePerplexityAI({ apiKey });
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
private static initAnthropic(payload: JWTPayload) {
|
|
265
|
-
const { ANTHROPIC_API_KEY, ANTHROPIC_PROXY_URL } = getServerConfig();
|
|
266
|
-
const apiKey = apiKeyManager.pick(payload?.apiKey || ANTHROPIC_API_KEY);
|
|
267
|
-
const baseURL = payload?.endpoint || ANTHROPIC_PROXY_URL;
|
|
268
|
-
return new LobeAnthropicAI({ apiKey, baseURL });
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
private static initMistral(payload: JWTPayload) {
|
|
272
|
-
const { MISTRAL_API_KEY } = getServerConfig();
|
|
273
|
-
const apiKey = apiKeyManager.pick(payload?.apiKey || MISTRAL_API_KEY);
|
|
274
|
-
|
|
275
|
-
return new LobeMistralAI({ apiKey });
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
private static initGroq(payload: JWTPayload) {
|
|
279
|
-
const { GROQ_API_KEY } = getServerConfig();
|
|
280
|
-
const apiKey = apiKeyManager.pick(payload?.apiKey || GROQ_API_KEY);
|
|
281
|
-
|
|
282
|
-
return new LobeGroq({ apiKey });
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
private static initOpenRouter(payload: JWTPayload) {
|
|
286
|
-
const { OPENROUTER_API_KEY } = getServerConfig();
|
|
287
|
-
const apiKey = apiKeyManager.pick(payload?.apiKey || OPENROUTER_API_KEY);
|
|
288
|
-
|
|
289
|
-
return new LobeOpenRouterAI({ apiKey });
|
|
290
152
|
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Initializes the agent runtime with the user payload in backend
|
|
157
|
+
* @param provider - The provider name.
|
|
158
|
+
* @param payload - The JWT payload.
|
|
159
|
+
* @returns A promise that resolves when the agent runtime is initialized.
|
|
160
|
+
*/
|
|
161
|
+
export const initAgentRuntimeWithUserPayload = (provider: string, payload: JWTPayload) => {
|
|
162
|
+
return AgentRuntime.initializeWithProviderOptions(provider, {
|
|
163
|
+
[provider]: getLlmOptionsFromPayload(provider, payload),
|
|
164
|
+
});
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
export const createTraceOptions = (
|
|
168
|
+
payload: ChatStreamPayload,
|
|
169
|
+
{ trace: tracePayload, provider }: AgentChatOptions,
|
|
170
|
+
) => {
|
|
171
|
+
const { messages, model, tools, ...parameters } = payload;
|
|
172
|
+
// create a trace to monitor the completion
|
|
173
|
+
const traceClient = new TraceClient();
|
|
174
|
+
const trace = traceClient.createTrace({
|
|
175
|
+
id: tracePayload?.traceId,
|
|
176
|
+
input: messages,
|
|
177
|
+
metadata: { provider },
|
|
178
|
+
name: tracePayload?.traceName,
|
|
179
|
+
sessionId: `${tracePayload?.sessionId || INBOX_SESSION_ID}@${tracePayload?.topicId || 'start'}`,
|
|
180
|
+
tags: tracePayload?.tags,
|
|
181
|
+
userId: tracePayload?.userId,
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
const generation = trace?.generation({
|
|
185
|
+
input: messages,
|
|
186
|
+
metadata: { provider },
|
|
187
|
+
model,
|
|
188
|
+
modelParameters: parameters as any,
|
|
189
|
+
name: `Chat Completion (${provider})`,
|
|
190
|
+
startTime: new Date(),
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
callback: {
|
|
195
|
+
experimental_onToolCall: async () => {
|
|
196
|
+
trace?.update({
|
|
197
|
+
tags: [...(tracePayload?.tags || []), TraceTagMap.ToolsCall],
|
|
198
|
+
});
|
|
199
|
+
},
|
|
291
200
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
201
|
+
onCompletion: async (completion: string) => {
|
|
202
|
+
generation?.update({
|
|
203
|
+
endTime: new Date(),
|
|
204
|
+
metadata: { provider, tools },
|
|
205
|
+
output: completion,
|
|
206
|
+
});
|
|
298
207
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
const apiKey = apiKeyManager.pick(payload?.apiKey || ZEROONE_API_KEY);
|
|
208
|
+
trace?.update({ output: completion });
|
|
209
|
+
},
|
|
302
210
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
}
|
|
211
|
+
onFinal: async () => {
|
|
212
|
+
await traceClient.shutdownAsync();
|
|
213
|
+
},
|
|
306
214
|
|
|
307
|
-
|
|
215
|
+
onStart: () => {
|
|
216
|
+
generation?.update({ completionStartTime: new Date() });
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
headers: {
|
|
220
|
+
[LOBE_CHAT_OBSERVATION_ID]: generation?.id,
|
|
221
|
+
[LOBE_CHAT_TRACE_ID]: trace?.id,
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
};
|
|
@@ -5,7 +5,7 @@ import { createErrorResponse } from '@/app/api/errorResponse';
|
|
|
5
5
|
import { ChatCompletionErrorPayload, ModelProvider } from '@/libs/agent-runtime';
|
|
6
6
|
import { ChatErrorType } from '@/types/fetch';
|
|
7
7
|
|
|
8
|
-
import
|
|
8
|
+
import { initAgentRuntimeWithUserPayload } from '../../agentRuntime';
|
|
9
9
|
import { checkAuth } from '../../auth';
|
|
10
10
|
|
|
11
11
|
export const runtime = 'edge';
|
|
@@ -21,7 +21,7 @@ export const GET = checkAuth(async (req, { params, jwtPayload }) => {
|
|
|
21
21
|
try {
|
|
22
22
|
const hasDefaultApiKey = jwtPayload.apiKey || 'dont-need-api-key-for-model-list';
|
|
23
23
|
|
|
24
|
-
const agentRuntime = await
|
|
24
|
+
const agentRuntime = await initAgentRuntimeWithUserPayload(provider, {
|
|
25
25
|
...jwtPayload,
|
|
26
26
|
apiKey: noNeedAPIKey(provider) ? hasDefaultApiKey : jwtPayload.apiKey,
|
|
27
27
|
});
|
|
@@ -114,8 +114,8 @@ const TopicContent = memo<TopicContentProps>(({ id, title, fav, showMore }) => {
|
|
|
114
114
|
modal.confirm({
|
|
115
115
|
centered: true,
|
|
116
116
|
okButtonProps: { danger: true },
|
|
117
|
-
onOk: () => {
|
|
118
|
-
removeTopic(id);
|
|
117
|
+
onOk: async () => {
|
|
118
|
+
await removeTopic(id);
|
|
119
119
|
},
|
|
120
120
|
title: t('topic.confirmRemoveTopic', { ns: 'chat' }),
|
|
121
121
|
});
|
package/src/app/metadata.ts
CHANGED
|
@@ -22,11 +22,9 @@ const metadata: Metadata = {
|
|
|
22
22
|
},
|
|
23
23
|
description,
|
|
24
24
|
icons: {
|
|
25
|
-
apple:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
shortcut:
|
|
29
|
-
'https://registry.npmmirror.com/@lobehub/assets-favicons/latest/files/assets/favicon.ico',
|
|
25
|
+
apple:'icons/apple-touch-icon.png',
|
|
26
|
+
icon:'favicon.ico',
|
|
27
|
+
shortcut:'favicon-32x32.ico',
|
|
30
28
|
},
|
|
31
29
|
manifest: noManifest ? undefined : '/manifest.json',
|
|
32
30
|
metadataBase: new URL(SITE_URL),
|
|
@@ -51,10 +51,18 @@ const ProviderConfig = memo<ProviderConfigProps>(
|
|
|
51
51
|
const { t } = useTranslation('setting');
|
|
52
52
|
const { t: modelT } = useTranslation('modelProvider');
|
|
53
53
|
const [form] = AntForm.useForm();
|
|
54
|
-
const [
|
|
54
|
+
const [
|
|
55
|
+
toggleProviderEnabled,
|
|
56
|
+
setSettings,
|
|
57
|
+
enabled,
|
|
58
|
+
isFetchOnClient,
|
|
59
|
+
isProviderEndpointNotEmpty,
|
|
60
|
+
] = useGlobalStore((s) => [
|
|
55
61
|
s.toggleProviderEnabled,
|
|
56
62
|
s.setSettings,
|
|
57
63
|
modelConfigSelectors.isProviderEnabled(provider)(s),
|
|
64
|
+
modelConfigSelectors.isProviderFetchOnClient(provider)(s),
|
|
65
|
+
modelConfigSelectors.isProviderEndpointNotEmpty(provider)(s),
|
|
58
66
|
]);
|
|
59
67
|
|
|
60
68
|
useSyncSettings(form);
|
|
@@ -99,6 +107,20 @@ const ProviderConfig = memo<ProviderConfigProps>(
|
|
|
99
107
|
label: t('llm.modelList.title'),
|
|
100
108
|
name: [LLMProviderConfigKey, provider, LLMProviderModelListKey],
|
|
101
109
|
},
|
|
110
|
+
showEndpoint &&
|
|
111
|
+
isProviderEndpointNotEmpty && {
|
|
112
|
+
children: (
|
|
113
|
+
<Switch
|
|
114
|
+
onChange={(enabled) => {
|
|
115
|
+
setSettings({ [LLMProviderConfigKey]: { [provider]: { fetchOnClient: enabled } } });
|
|
116
|
+
}}
|
|
117
|
+
value={isFetchOnClient}
|
|
118
|
+
/>
|
|
119
|
+
),
|
|
120
|
+
desc: t('llm.fetchOnClient.desc'),
|
|
121
|
+
label: t('llm.fetchOnClient.title'),
|
|
122
|
+
minWidth: undefined,
|
|
123
|
+
},
|
|
102
124
|
checkerItem ?? {
|
|
103
125
|
children: <Checker model={checkModel!} provider={provider} />,
|
|
104
126
|
desc: t('llm.checker.desc'),
|
|
@@ -23,7 +23,7 @@ import TogetherAI from './TogetherAI';
|
|
|
23
23
|
import ZeroOne from './ZeroOne';
|
|
24
24
|
import Zhipu from './Zhipu';
|
|
25
25
|
|
|
26
|
-
export default memo
|
|
26
|
+
export default memo(() => {
|
|
27
27
|
const { t } = useTranslation('setting');
|
|
28
28
|
|
|
29
29
|
return (
|
|
@@ -31,7 +31,7 @@ export default memo<{ showOllama: boolean }>(({ showOllama }) => {
|
|
|
31
31
|
<PageTitle title={t('tab.llm')} />
|
|
32
32
|
<OpenAI />
|
|
33
33
|
<Azure />
|
|
34
|
-
|
|
34
|
+
<Ollama />
|
|
35
35
|
<Google />
|
|
36
36
|
<Anthropic />
|
|
37
37
|
<Bedrock />
|
|
@@ -7,6 +7,7 @@ import { useTranslation } from 'react-i18next';
|
|
|
7
7
|
|
|
8
8
|
import HotKeys from '@/components/HotKeys';
|
|
9
9
|
import { PREFIX_KEY, SAVE_TOPIC_KEY } from '@/const/hotkeys';
|
|
10
|
+
import { useActionSWR } from '@/libs/swr';
|
|
10
11
|
import { useChatStore } from '@/store/chat';
|
|
11
12
|
|
|
12
13
|
const SaveTopic = memo<{ mobile?: boolean }>(({ mobile }) => {
|
|
@@ -16,20 +17,23 @@ const SaveTopic = memo<{ mobile?: boolean }>(({ mobile }) => {
|
|
|
16
17
|
s.openNewTopicOrSaveTopic,
|
|
17
18
|
]);
|
|
18
19
|
|
|
20
|
+
const { mutate, isValidating } = useActionSWR('openNewTopicOrSaveTopic', openNewTopicOrSaveTopic);
|
|
21
|
+
|
|
19
22
|
const icon = hasTopic ? LucideMessageSquarePlus : LucideGalleryVerticalEnd;
|
|
20
23
|
const Render = mobile ? ActionIcon : Button;
|
|
21
24
|
const iconRender: any = mobile ? icon : <Icon icon={icon} />;
|
|
22
25
|
const desc = t(hasTopic ? 'topic.openNewTopic' : 'topic.saveCurrentMessages');
|
|
23
26
|
|
|
24
27
|
const hotkeys = [PREFIX_KEY, SAVE_TOPIC_KEY].join('+');
|
|
25
|
-
|
|
28
|
+
|
|
29
|
+
useHotkeys(hotkeys, () => mutate(), {
|
|
26
30
|
enableOnFormTags: true,
|
|
27
31
|
preventDefault: true,
|
|
28
32
|
});
|
|
29
33
|
|
|
30
34
|
return (
|
|
31
35
|
<Tooltip title={<HotKeys desc={desc} keys={hotkeys} />}>
|
|
32
|
-
<Render aria-label={desc} icon={iconRender} onClick={
|
|
36
|
+
<Render aria-label={desc} icon={iconRender} loading={isValidating} onClick={() => mutate()} />
|
|
33
37
|
</Tooltip>
|
|
34
38
|
);
|
|
35
39
|
});
|