@lobehub/chat 0.161.0 → 0.161.2

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 (51) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/README.md +8 -8
  3. package/README.zh-CN.md +8 -8
  4. package/locales/ar/setting.json +8 -0
  5. package/locales/bg-BG/setting.json +8 -0
  6. package/locales/de-DE/setting.json +8 -0
  7. package/locales/en-US/setting.json +8 -0
  8. package/locales/es-ES/setting.json +8 -0
  9. package/locales/fr-FR/setting.json +8 -0
  10. package/locales/it-IT/setting.json +8 -0
  11. package/locales/ja-JP/setting.json +8 -0
  12. package/locales/ko-KR/setting.json +8 -0
  13. package/locales/nl-NL/setting.json +8 -0
  14. package/locales/pl-PL/setting.json +8 -1
  15. package/locales/pt-BR/setting.json +8 -0
  16. package/locales/ru-RU/setting.json +8 -0
  17. package/locales/tr-TR/setting.json +8 -0
  18. package/locales/vi-VN/setting.json +8 -0
  19. package/locales/zh-CN/clerk.json +1 -1
  20. package/locales/zh-CN/setting.json +8 -0
  21. package/locales/zh-TW/clerk.json +1 -1
  22. package/locales/zh-TW/setting.json +8 -0
  23. package/package.json +23 -23
  24. package/src/app/(main)/settings/_layout/Desktop/Header.tsx +58 -25
  25. package/src/app/(main)/settings/_layout/Desktop/index.tsx +18 -1
  26. package/src/app/@modal/(.)settings/modal/layout.tsx +13 -1
  27. package/src/app/@modal/_layout/SettingModalLayout.tsx +45 -41
  28. package/src/app/@modal/chat/(.)settings/modal/features/CategoryContent.tsx +1 -1
  29. package/src/app/@modal/chat/(.)settings/modal/features/useCategory.tsx +6 -6
  30. package/src/app/@modal/chat/(.)settings/modal/layout.tsx +4 -0
  31. package/src/app/@modal/layout.tsx +1 -0
  32. package/src/app/api/chat/[provider]/route.test.ts +1 -1
  33. package/src/app/api/chat/agentRuntime.test.ts +4 -4
  34. package/src/app/api/chat/agentRuntime.ts +17 -17
  35. package/src/app/api/chat/apiKeyManager.test.ts +1 -0
  36. package/src/app/api/chat/apiKeyManager.ts +2 -2
  37. package/src/app/api/config.test.ts +1 -1
  38. package/src/app/api/config.ts +3 -4
  39. package/src/app/api/openai/createBizOpenAI/createAzureOpenai.ts +2 -2
  40. package/src/app/api/openai/createBizOpenAI/createOpenai.ts +2 -2
  41. package/src/config/__tests__/server.test.ts +5 -5
  42. package/src/config/llm.ts +217 -0
  43. package/src/config/server/index.ts +1 -5
  44. package/src/layout/AuthProvider/Clerk/useAppearance.ts +4 -0
  45. package/src/libs/agent-runtime/minimax/index.test.ts +0 -1
  46. package/src/libs/agent-runtime/zhipu/index.test.ts +0 -3
  47. package/src/locales/default/clerk.ts +1 -1
  48. package/src/locales/default/setting.ts +8 -0
  49. package/src/server/globalConfig/index.ts +6 -7
  50. package/src/server/translation.ts +22 -8
  51. package/src/config/server/provider.ts +0 -229
@@ -1,9 +1,14 @@
1
1
  'use client';
2
2
 
3
+ import { Tag } from 'antd';
3
4
  import { useResponsive } from 'antd-style';
4
5
  import { memo, useRef } from 'react';
6
+ import { useTranslation } from 'react-i18next';
5
7
  import { Flexbox } from 'react-layout-kit';
6
8
 
9
+ import { useActiveSettingsKey } from '@/hooks/useActiveSettingsKey';
10
+ import { SettingsTabs } from '@/store/global/initialState';
11
+
7
12
  import { LayoutProps } from '../type';
8
13
  import Header from './Header';
9
14
  import SideBar from './SideBar';
@@ -11,6 +16,8 @@ import SideBar from './SideBar';
11
16
  const Layout = memo<LayoutProps>(({ children, category }) => {
12
17
  const ref = useRef<any>(null);
13
18
  const { md = true, mobile = false } = useResponsive();
19
+ const { t } = useTranslation('setting');
20
+ const activeKey = useActiveSettingsKey();
14
21
 
15
22
  return (
16
23
  <Flexbox
@@ -23,7 +30,17 @@ const Layout = memo<LayoutProps>(({ children, category }) => {
23
30
  {md ? (
24
31
  <SideBar>{category}</SideBar>
25
32
  ) : (
26
- <Header getContainer={() => ref.current}>{category}</Header>
33
+ <Header
34
+ getContainer={() => ref.current}
35
+ title={
36
+ <>
37
+ {t(`tab.${activeKey}`)}
38
+ {activeKey === SettingsTabs.Sync && <Tag color={'gold'}>{t('tab.experiment')}</Tag>}
39
+ </>
40
+ }
41
+ >
42
+ {category}
43
+ </Header>
27
44
  )}
28
45
  <Flexbox
29
46
  align={'center'}
@@ -1,8 +1,12 @@
1
1
  'use client';
2
2
 
3
- import { Skeleton } from 'antd';
3
+ import { Skeleton, Tag } from 'antd';
4
4
  import dynamic from 'next/dynamic';
5
5
  import { PropsWithChildren, memo } from 'react';
6
+ import { useTranslation } from 'react-i18next';
7
+
8
+ import { useActiveSettingsKey } from '@/hooks/useActiveSettingsKey';
9
+ import { SettingsTabs } from '@/store/global/initialState';
6
10
 
7
11
  import SettingModalLayout from '../../_layout/SettingModalLayout';
8
12
 
@@ -15,8 +19,16 @@ const UpgradeAlert = dynamic(() => import('@/app/(main)/settings/features/Upgrad
15
19
  });
16
20
 
17
21
  const Layout = memo<PropsWithChildren>(({ children }) => {
22
+ const { t } = useTranslation('setting');
23
+ const activeKey = useActiveSettingsKey();
18
24
  return (
19
25
  <SettingModalLayout
26
+ activeTitle={
27
+ <>
28
+ {t(`tab.${activeKey}`)}
29
+ {activeKey === SettingsTabs.Sync && <Tag color={'gold'}>{t('tab.experiment')}</Tag>}
30
+ </>
31
+ }
20
32
  category={
21
33
  <>
22
34
  <CategoryContent modal />
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { useResponsive, useTheme, useThemeMode } from 'antd-style';
3
+ import { useResponsive, useTheme } from 'antd-style';
4
4
  import { ReactNode, memo, useRef } from 'react';
5
5
  import { Flexbox } from 'react-layout-kit';
6
6
 
@@ -8,57 +8,61 @@ import Header from '@/app/(main)/settings/_layout/Desktop/Header';
8
8
  import SideBar from '@/app/(main)/settings/_layout/Desktop/SideBar';
9
9
 
10
10
  interface SettingLayoutProps {
11
+ activeTitle?: ReactNode;
11
12
  category: ReactNode;
12
13
  children: ReactNode;
13
14
  desc?: string;
14
15
  title?: string;
15
16
  }
16
17
 
17
- const SettingModalLayout = memo<SettingLayoutProps>(({ children, category, desc, title }) => {
18
- const ref = useRef<any>(null);
19
- const theme = useTheme();
20
- const { isDarkMode } = useThemeMode();
21
- const { mobile = false } = useResponsive();
18
+ const SettingModalLayout = memo<SettingLayoutProps>(
19
+ ({ children, category, desc, title, activeTitle }) => {
20
+ const ref = useRef<any>(null);
21
+ const theme = useTheme();
22
+ const { md = true, mobile = false } = useResponsive();
22
23
 
23
- return (
24
- <Flexbox horizontal={!mobile} width={'100%'}>
25
- {!mobile ? (
26
- <SideBar
27
- desc={desc}
24
+ return (
25
+ <Flexbox horizontal={md} width={'100%'}>
26
+ {md ? (
27
+ <SideBar
28
+ desc={desc}
29
+ style={{
30
+ background: theme.isDarkMode ? theme.colorBgContainer : theme.colorFillTertiary,
31
+ borderColor: theme.colorFillTertiary,
32
+ }}
33
+ title={title}
34
+ >
35
+ {category}
36
+ </SideBar>
37
+ ) : (
38
+ <Header getContainer={() => ref.current} title={activeTitle}>
39
+ {category}
40
+ </Header>
41
+ )}
42
+ <Flexbox
43
+ align={'center'}
44
+ gap={mobile ? 0 : 64}
45
+ ref={ref}
28
46
  style={{
29
- background: isDarkMode ? theme.colorBgContainer : theme.colorFillTertiary,
30
- borderColor: theme.colorFillTertiary,
47
+ background: mobile
48
+ ? theme.colorBgContainer
49
+ : theme.isDarkMode
50
+ ? theme.colorFillQuaternary
51
+ : theme.colorBgElevated,
52
+ minHeight: '100%',
53
+ overflowX: 'hidden',
54
+ overflowY: 'auto',
55
+ paddingBlock: mobile ? 0 : 40,
56
+ paddingInline: mobile ? 0 : 56,
31
57
  }}
32
- title={title}
58
+ width={'100%'}
33
59
  >
34
- {category}
35
- </SideBar>
36
- ) : (
37
- <Header getContainer={() => ref.current}>{category}</Header>
38
- )}
39
- <Flexbox
40
- align={'center'}
41
- gap={mobile ? 0 : 64}
42
- ref={ref}
43
- style={{
44
- background: mobile
45
- ? theme.colorBgContainer
46
- : isDarkMode
47
- ? theme.colorFillQuaternary
48
- : theme.colorBgElevated,
49
- minHeight: '100%',
50
- overflowX: 'hidden',
51
- overflowY: 'auto',
52
- paddingBlock: mobile ? 0 : 40,
53
- paddingInline: mobile ? 0 : 56,
54
- }}
55
- width={'100%'}
56
- >
57
- {children}
60
+ {children}
61
+ </Flexbox>
58
62
  </Flexbox>
59
- </Flexbox>
60
- );
61
- });
63
+ );
64
+ },
65
+ );
62
66
 
63
67
  SettingModalLayout.displayName = 'SettingModalLayout';
64
68
 
@@ -13,8 +13,8 @@ import { useCategory } from './useCategory';
13
13
 
14
14
  const CategoryContent = memo(() => {
15
15
  const cateItems = useCategory();
16
- const router = useQueryRoute();
17
16
  const { tab = ChatSettingsTabs.Meta } = useQuery();
17
+ const router = useQueryRoute();
18
18
 
19
19
  return (
20
20
  <>
@@ -19,32 +19,32 @@ export const useCategory = ({ mobile }: UseCategoryOptions = {}) => {
19
19
  {
20
20
  icon: <Icon icon={UserCircle} size={iconSize} />,
21
21
  key: ChatSettingsTabs.Meta,
22
- label: t('settingAgent.title'),
22
+ label: t('agentTab.meta'),
23
23
  },
24
24
  {
25
25
  icon: <Icon icon={Bot} size={iconSize} />,
26
26
  key: ChatSettingsTabs.Prompt,
27
- label: t('settingAgent.prompt.title'),
27
+ label: t('agentTab.prompt'),
28
28
  },
29
29
  {
30
30
  icon: <Icon icon={MessagesSquare} size={iconSize} />,
31
31
  key: ChatSettingsTabs.Chat,
32
- label: t('settingChat.title'),
32
+ label: t('agentTab.chat'),
33
33
  },
34
34
  {
35
35
  icon: <Icon icon={BrainCog} size={iconSize} />,
36
36
  key: ChatSettingsTabs.Modal,
37
- label: t('settingModel.title'),
37
+ label: t('agentTab.modal'),
38
38
  },
39
39
  {
40
40
  icon: <Icon icon={Mic2} size={iconSize} />,
41
41
  key: ChatSettingsTabs.TTS,
42
- label: t('settingTTS.title'),
42
+ label: t('agentTab.tts'),
43
43
  },
44
44
  {
45
45
  icon: <Icon icon={Blocks} size={iconSize} />,
46
46
  key: ChatSettingsTabs.Plugin,
47
- label: t('settingPlugin.title'),
47
+ label: t('agentTab.plugin'),
48
48
  },
49
49
  ],
50
50
  [t],
@@ -8,8 +8,10 @@ import { useTranslation } from 'react-i18next';
8
8
 
9
9
  import StoreUpdater from '@/features/AgentSetting/StoreUpdater';
10
10
  import { Provider, createStore } from '@/features/AgentSetting/store';
11
+ import { useQuery } from '@/hooks/useQuery';
11
12
  import { useAgentStore } from '@/store/agent';
12
13
  import { agentSelectors } from '@/store/agent/slices/chat';
14
+ import { ChatSettingsTabs } from '@/store/global/initialState';
13
15
  import { useSessionStore } from '@/store/session';
14
16
  import { sessionMetaSelectors } from '@/store/session/selectors';
15
17
 
@@ -21,6 +23,7 @@ const CategoryContent = dynamic(() => import('./features/CategoryContent'), {
21
23
  });
22
24
 
23
25
  const Layout = memo<PropsWithChildren>(({ children }) => {
26
+ const { tab = ChatSettingsTabs.Meta } = useQuery();
24
27
  const { t } = useTranslation('setting');
25
28
  const id = useSessionStore((s) => s.activeId);
26
29
  const config = useAgentStore(agentSelectors.currentAgentConfig, isEqual);
@@ -34,6 +37,7 @@ const Layout = memo<PropsWithChildren>(({ children }) => {
34
37
 
35
38
  return (
36
39
  <SettingModalLayout
40
+ activeTitle={t(`agentTab.${tab as ChatSettingsTabs}`)}
37
41
  category={<CategoryContent />}
38
42
  desc={t('header.sessionDesc')}
39
43
  title={t('header.session')}
@@ -15,6 +15,7 @@ const SessionSettingsModal = memo<PropsWithChildren>(({ children }) => {
15
15
  afterClose={() => {
16
16
  router.back();
17
17
  }}
18
+ enableResponsive={false}
18
19
  footer={null}
19
20
  onCancel={() => setOpen(false)}
20
21
  open={open}
@@ -1,4 +1,4 @@
1
- // @vitest-environment edge-runtime
1
+ // @vitest-environment node
2
2
  import { getAuth } from '@clerk/nextjs/server';
3
3
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
4
4
 
@@ -6,6 +6,7 @@ import {
6
6
  LobeAnthropicAI,
7
7
  LobeAzureOpenAI,
8
8
  LobeBedrockAI,
9
+ LobeDeepSeekAI,
9
10
  LobeGoogleAI,
10
11
  LobeGroq,
11
12
  LobeMinimaxAI,
@@ -16,7 +17,6 @@ import {
16
17
  LobeOpenRouterAI,
17
18
  LobePerplexityAI,
18
19
  LobeRuntimeAI,
19
- LobeDeepSeekAI,
20
20
  LobeTogetherAI,
21
21
  LobeZeroOneAI,
22
22
  LobeZhipuAI,
@@ -27,8 +27,8 @@ import { AgentRuntime } from '@/libs/agent-runtime';
27
27
  import { initAgentRuntimeWithUserPayload } from './agentRuntime';
28
28
 
29
29
  // 模拟依赖项
30
- vi.mock('@/config/server', () => ({
31
- getServerConfig: vi.fn(() => ({
30
+ vi.mock('@/config/llm', () => ({
31
+ getLLMConfig: vi.fn(() => ({
32
32
  // 确保为每个provider提供必要的配置信息
33
33
  OPENAI_API_KEY: 'test-openai-key',
34
34
  GOOGLE_API_KEY: 'test-google-key',
@@ -295,7 +295,7 @@ describe('initAgentRuntimeWithUserPayload method', () => {
295
295
  // 假设 LobeDeepSeekAI 是 DeepSeek 提供者的实现类
296
296
  expect(runtime['_runtime']).toBeInstanceOf(LobeDeepSeekAI);
297
297
  });
298
-
298
+
299
299
  it('Together AI provider: without apikey', async () => {
300
300
  const jwtPayload = {};
301
301
  const runtime = await initAgentRuntimeWithUserPayload(ModelProvider.TogetherAI, jwtPayload);
@@ -1,4 +1,4 @@
1
- import { getServerConfig } from '@/config/server';
1
+ import { getLLMConfig } from '@/config/llm';
2
2
  import { JWTPayload } from '@/const/auth';
3
3
  import { INBOX_SESSION_ID } from '@/const/session';
4
4
  import {
@@ -30,7 +30,7 @@ const getLlmOptionsFromPayload = (provider: string, payload: JWTPayload) => {
30
30
  switch (provider) {
31
31
  default: // Use Openai options as default
32
32
  case ModelProvider.OpenAI: {
33
- const { OPENAI_API_KEY, OPENAI_PROXY_URL } = getServerConfig();
33
+ const { OPENAI_API_KEY, OPENAI_PROXY_URL } = getLLMConfig();
34
34
  const openaiApiKey = payload?.apiKey || OPENAI_API_KEY;
35
35
  const baseURL = payload?.endpoint || OPENAI_PROXY_URL;
36
36
  const apiKey = apiKeyManager.pick(openaiApiKey);
@@ -40,7 +40,7 @@ const getLlmOptionsFromPayload = (provider: string, payload: JWTPayload) => {
40
40
  };
41
41
  }
42
42
  case ModelProvider.Azure: {
43
- const { AZURE_API_KEY, AZURE_API_VERSION, AZURE_ENDPOINT } = getServerConfig();
43
+ const { AZURE_API_KEY, AZURE_API_VERSION, AZURE_ENDPOINT } = getLLMConfig();
44
44
  const apiKey = apiKeyManager.pick(payload?.apiKey || AZURE_API_KEY);
45
45
  const endpoint = payload?.endpoint || AZURE_ENDPOINT;
46
46
  const apiVersion = payload?.azureApiVersion || AZURE_API_VERSION;
@@ -51,14 +51,14 @@ const getLlmOptionsFromPayload = (provider: string, payload: JWTPayload) => {
51
51
  };
52
52
  }
53
53
  case ModelProvider.ZhiPu: {
54
- const { ZHIPU_API_KEY } = getServerConfig();
54
+ const { ZHIPU_API_KEY } = getLLMConfig();
55
55
  const apiKey = apiKeyManager.pick(payload?.apiKey || ZHIPU_API_KEY);
56
56
  return {
57
57
  apiKey,
58
58
  };
59
59
  }
60
60
  case ModelProvider.Google: {
61
- const { GOOGLE_API_KEY, GOOGLE_PROXY_URL } = getServerConfig();
61
+ const { GOOGLE_API_KEY, GOOGLE_PROXY_URL } = getLLMConfig();
62
62
  const apiKey = apiKeyManager.pick(payload?.apiKey || GOOGLE_API_KEY);
63
63
  const baseURL = payload?.endpoint || GOOGLE_PROXY_URL;
64
64
  return {
@@ -67,7 +67,7 @@ const getLlmOptionsFromPayload = (provider: string, payload: JWTPayload) => {
67
67
  };
68
68
  }
69
69
  case ModelProvider.Moonshot: {
70
- const { MOONSHOT_API_KEY, MOONSHOT_PROXY_URL } = getServerConfig();
70
+ const { MOONSHOT_API_KEY, MOONSHOT_PROXY_URL } = getLLMConfig();
71
71
  const apiKey = apiKeyManager.pick(payload?.apiKey || MOONSHOT_API_KEY);
72
72
  return {
73
73
  apiKey,
@@ -75,7 +75,7 @@ const getLlmOptionsFromPayload = (provider: string, payload: JWTPayload) => {
75
75
  };
76
76
  }
77
77
  case ModelProvider.Bedrock: {
78
- const { AWS_SECRET_ACCESS_KEY, AWS_ACCESS_KEY_ID, AWS_REGION } = getServerConfig();
78
+ const { AWS_SECRET_ACCESS_KEY, AWS_ACCESS_KEY_ID, AWS_REGION } = getLLMConfig();
79
79
  let accessKeyId: string | undefined = AWS_ACCESS_KEY_ID;
80
80
  let accessKeySecret: string | undefined = AWS_SECRET_ACCESS_KEY;
81
81
  let region = AWS_REGION;
@@ -88,12 +88,12 @@ const getLlmOptionsFromPayload = (provider: string, payload: JWTPayload) => {
88
88
  return { accessKeyId, accessKeySecret, region };
89
89
  }
90
90
  case ModelProvider.Ollama: {
91
- const { OLLAMA_PROXY_URL } = getServerConfig();
91
+ const { OLLAMA_PROXY_URL } = getLLMConfig();
92
92
  const baseURL = payload?.endpoint || OLLAMA_PROXY_URL;
93
93
  return { baseURL };
94
94
  }
95
95
  case ModelProvider.Perplexity: {
96
- const { PERPLEXITY_API_KEY, PERPLEXITY_PROXY_URL } = getServerConfig();
96
+ const { PERPLEXITY_API_KEY, PERPLEXITY_PROXY_URL } = getLLMConfig();
97
97
 
98
98
  const apiKey = apiKeyManager.pick(payload?.apiKey || PERPLEXITY_API_KEY);
99
99
  const baseURL = payload?.endpoint || PERPLEXITY_PROXY_URL;
@@ -101,7 +101,7 @@ const getLlmOptionsFromPayload = (provider: string, payload: JWTPayload) => {
101
101
  return { apiKey, baseURL };
102
102
  }
103
103
  case ModelProvider.Anthropic: {
104
- const { ANTHROPIC_API_KEY, ANTHROPIC_PROXY_URL } = getServerConfig();
104
+ const { ANTHROPIC_API_KEY, ANTHROPIC_PROXY_URL } = getLLMConfig();
105
105
 
106
106
  const apiKey = apiKeyManager.pick(payload?.apiKey || ANTHROPIC_API_KEY);
107
107
  const baseURL = payload?.endpoint || ANTHROPIC_PROXY_URL;
@@ -109,21 +109,21 @@ const getLlmOptionsFromPayload = (provider: string, payload: JWTPayload) => {
109
109
  return { apiKey, baseURL };
110
110
  }
111
111
  case ModelProvider.Minimax: {
112
- const { MINIMAX_API_KEY } = getServerConfig();
112
+ const { MINIMAX_API_KEY } = getLLMConfig();
113
113
 
114
114
  const apiKey = apiKeyManager.pick(payload?.apiKey || MINIMAX_API_KEY);
115
115
 
116
116
  return { apiKey };
117
117
  }
118
118
  case ModelProvider.Mistral: {
119
- const { MISTRAL_API_KEY } = getServerConfig();
119
+ const { MISTRAL_API_KEY } = getLLMConfig();
120
120
 
121
121
  const apiKey = apiKeyManager.pick(payload?.apiKey || MISTRAL_API_KEY);
122
122
 
123
123
  return { apiKey };
124
124
  }
125
125
  case ModelProvider.Groq: {
126
- const { GROQ_API_KEY, GROQ_PROXY_URL } = getServerConfig();
126
+ const { GROQ_API_KEY, GROQ_PROXY_URL } = getLLMConfig();
127
127
 
128
128
  const apiKey = apiKeyManager.pick(payload?.apiKey || GROQ_API_KEY);
129
129
  const baseURL = payload?.endpoint || GROQ_PROXY_URL;
@@ -131,28 +131,28 @@ const getLlmOptionsFromPayload = (provider: string, payload: JWTPayload) => {
131
131
  return { apiKey, baseURL };
132
132
  }
133
133
  case ModelProvider.OpenRouter: {
134
- const { OPENROUTER_API_KEY } = getServerConfig();
134
+ const { OPENROUTER_API_KEY } = getLLMConfig();
135
135
 
136
136
  const apiKey = apiKeyManager.pick(payload?.apiKey || OPENROUTER_API_KEY);
137
137
 
138
138
  return { apiKey };
139
139
  }
140
140
  case ModelProvider.DeepSeek: {
141
- const { DEEPSEEK_API_KEY } = getServerConfig();
141
+ const { DEEPSEEK_API_KEY } = getLLMConfig();
142
142
 
143
143
  const apiKey = apiKeyManager.pick(payload?.apiKey || DEEPSEEK_API_KEY);
144
144
 
145
145
  return { apiKey };
146
146
  }
147
147
  case ModelProvider.TogetherAI: {
148
- const { TOGETHERAI_API_KEY } = getServerConfig();
148
+ const { TOGETHERAI_API_KEY } = getLLMConfig();
149
149
 
150
150
  const apiKey = apiKeyManager.pick(payload?.apiKey || TOGETHERAI_API_KEY);
151
151
 
152
152
  return { apiKey };
153
153
  }
154
154
  case ModelProvider.ZeroOne: {
155
- const { ZEROONE_API_KEY } = getServerConfig();
155
+ const { ZEROONE_API_KEY } = getLLMConfig();
156
156
 
157
157
  const apiKey = apiKeyManager.pick(payload?.apiKey || ZEROONE_API_KEY);
158
158
 
@@ -1,3 +1,4 @@
1
+ // @vitest-environment node
1
2
  import { nanoid } from 'nanoid';
2
3
  import { beforeEach, describe, expect, it, vi } from 'vitest';
3
4
 
@@ -1,4 +1,4 @@
1
- import { getServerConfig } from '@/config/server';
1
+ import { getLLMConfig } from '@/config/llm';
2
2
 
3
3
  interface KeyStore {
4
4
  index: number;
@@ -12,7 +12,7 @@ export class ApiKeyManager {
12
12
  private _mode: string;
13
13
 
14
14
  constructor() {
15
- const { API_KEY_SELECT_MODE: mode = 'random' } = getServerConfig();
15
+ const { API_KEY_SELECT_MODE: mode = 'random' } = getLLMConfig();
16
16
 
17
17
  this._mode = mode;
18
18
  }
@@ -1,7 +1,7 @@
1
+ // @vitest-environment node
1
2
  import { describe, expect, it, vi } from 'vitest';
2
3
 
3
4
  import { getPreferredRegion } from './config';
4
- import { checkAuth } from './openai/createBizOpenAI/auth';
5
5
 
6
6
  // Stub the global process object to safely mock environment variables
7
7
  vi.stubGlobal('process', {
@@ -1,13 +1,12 @@
1
- import { getServerConfig } from '@/config/server';
1
+ import { getLLMConfig } from '@/config/llm';
2
2
 
3
3
  export const getPreferredRegion = (region: string | string[] = 'auto') => {
4
4
  try {
5
- const cfg = getServerConfig();
6
- if (cfg.OPENAI_FUNCTION_REGIONS.length <= 0) {
5
+ if (getLLMConfig().OPENAI_FUNCTION_REGIONS.length <= 0) {
7
6
  return region;
8
7
  }
9
8
 
10
- return cfg.OPENAI_FUNCTION_REGIONS;
9
+ return getLLMConfig().OPENAI_FUNCTION_REGIONS;
11
10
  } catch (error) {
12
11
  console.error('get server config failed, error:', error);
13
12
  return region;
@@ -1,7 +1,7 @@
1
1
  import OpenAI, { ClientOptions } from 'openai';
2
2
  import urlJoin from 'url-join';
3
3
 
4
- import { getServerConfig } from '@/config/server';
4
+ import { getLLMConfig } from '@/config/llm';
5
5
  import { ChatErrorType } from '@/types/fetch';
6
6
 
7
7
  // create Azure OpenAI Instance
@@ -11,7 +11,7 @@ export const createAzureOpenai = (params: {
11
11
  model: string;
12
12
  userApiKey?: string | null;
13
13
  }) => {
14
- const { OPENAI_PROXY_URL = '', AZURE_API_VERSION, AZURE_API_KEY } = getServerConfig();
14
+ const { OPENAI_PROXY_URL = '', AZURE_API_VERSION, AZURE_API_KEY } = getLLMConfig();
15
15
 
16
16
  const endpoint = !params.endpoint ? OPENAI_PROXY_URL : params.endpoint;
17
17
  const baseURL = urlJoin(endpoint, `/openai/deployments/${params.model.replace('.', '')}`); // refs: https://test-001.openai.azure.com/openai/deployments/gpt-35-turbo
@@ -1,11 +1,11 @@
1
1
  import OpenAI from 'openai';
2
2
 
3
- import { getServerConfig } from '@/config/server';
3
+ import { getLLMConfig } from '@/config/llm';
4
4
  import { ChatErrorType } from '@/types/fetch';
5
5
 
6
6
  // create OpenAI instance
7
7
  export const createOpenai = (userApiKey: string | null, endpoint?: string | null) => {
8
- const { OPENAI_API_KEY, OPENAI_PROXY_URL } = getServerConfig();
8
+ const { OPENAI_API_KEY, OPENAI_PROXY_URL } = getLLMConfig();
9
9
 
10
10
  const baseURL = endpoint ? endpoint : OPENAI_PROXY_URL ? OPENAI_PROXY_URL : undefined;
11
11
 
@@ -27,11 +27,11 @@ describe('getServerConfig', () => {
27
27
  global.process = originalProcess; // Restore the original process object
28
28
  });
29
29
 
30
- it('correctly handles values for OPENAI_FUNCTION_REGIONS', () => {
31
- process.env.OPENAI_FUNCTION_REGIONS = 'iad1,sfo1';
32
- const config = getServerConfig();
33
- expect(config.OPENAI_FUNCTION_REGIONS).toStrictEqual(['iad1', 'sfo1']);
34
- });
30
+ // it('correctly handles values for OPENAI_FUNCTION_REGIONS', () => {
31
+ // process.env.OPENAI_FUNCTION_REGIONS = 'iad1,sfo1';
32
+ // const config = getServerConfig();
33
+ // expect(config.OPENAI_FUNCTION_REGIONS).toStrictEqual(['iad1', 'sfo1']);
34
+ // });
35
35
 
36
36
  describe('index url', () => {
37
37
  it('should return default URLs when no environment variables are set', () => {