@lobehub/lobehub 2.0.0-next.15 → 2.0.0-next.17

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 (111) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/README.md +2 -45
  3. package/README.zh-CN.md +2 -45
  4. package/changelog/v1.json +18 -0
  5. package/docs/self-hosting/advanced/feature-flags.mdx +0 -1
  6. package/docs/self-hosting/advanced/feature-flags.zh-CN.mdx +0 -1
  7. package/e2e/src/features/discover/smoke.feature +34 -1
  8. package/e2e/src/steps/discover/smoke.steps.ts +116 -4
  9. package/package.json +1 -1
  10. package/packages/model-runtime/src/utils/googleErrorParser.test.ts +125 -0
  11. package/packages/model-runtime/src/utils/googleErrorParser.ts +103 -77
  12. package/packages/types/src/serverConfig.ts +2 -6
  13. package/src/app/[variants]/(auth)/signup/[[...signup]]/page.tsx +1 -8
  14. package/src/app/[variants]/(main)/(mobile)/me/(home)/features/UserBanner.tsx +3 -6
  15. package/src/app/[variants]/(main)/discover/(list)/features/Pagination.tsx +1 -0
  16. package/src/app/[variants]/(main)/discover/(list)/features/SortButton/index.tsx +1 -1
  17. package/src/app/[variants]/(main)/discover/(list)/mcp/features/List/Item.tsx +1 -0
  18. package/src/app/[variants]/(main)/discover/(list)/model/features/List/Item.tsx +1 -0
  19. package/src/app/[variants]/(main)/discover/(list)/provider/features/List/Item.tsx +1 -0
  20. package/src/app/[variants]/(main)/discover/components/CategoryMenu.tsx +9 -1
  21. package/src/app/[variants]/(main)/labs/components/LabCard.tsx +3 -1
  22. package/src/app/[variants]/(main)/settings/provider/detail/azure/index.tsx +5 -7
  23. package/src/components/InvalidAPIKey/APIKeyForm/Bedrock.tsx +8 -13
  24. package/src/config/featureFlags/schema.test.ts +0 -2
  25. package/src/config/featureFlags/schema.ts +0 -6
  26. package/src/config/modelProviders/ai21.ts +1 -16
  27. package/src/config/modelProviders/ai302.ts +1 -128
  28. package/src/config/modelProviders/ai360.ts +1 -32
  29. package/src/config/modelProviders/anthropic.ts +1 -71
  30. package/src/config/modelProviders/azure.ts +1 -51
  31. package/src/config/modelProviders/baichuan.ts +1 -57
  32. package/src/config/modelProviders/bedrock.ts +1 -276
  33. package/src/config/modelProviders/cloudflare.ts +1 -64
  34. package/src/config/modelProviders/deepseek.ts +1 -19
  35. package/src/config/modelProviders/fireworksai.ts +1 -174
  36. package/src/config/modelProviders/giteeai.ts +1 -135
  37. package/src/config/modelProviders/github.ts +1 -254
  38. package/src/config/modelProviders/google.ts +1 -130
  39. package/src/config/modelProviders/groq.ts +1 -119
  40. package/src/config/modelProviders/higress.ts +1 -1713
  41. package/src/config/modelProviders/huggingface.ts +1 -54
  42. package/src/config/modelProviders/hunyuan.ts +1 -83
  43. package/src/config/modelProviders/infiniai.ts +1 -74
  44. package/src/config/modelProviders/internlm.ts +1 -20
  45. package/src/config/modelProviders/mistral.ts +1 -95
  46. package/src/config/modelProviders/modelscope.ts +1 -27
  47. package/src/config/modelProviders/moonshot.ts +1 -29
  48. package/src/config/modelProviders/novita.ts +1 -105
  49. package/src/config/modelProviders/ollama.ts +1 -325
  50. package/src/config/modelProviders/openai.ts +1 -242
  51. package/src/config/modelProviders/openrouter.ts +1 -240
  52. package/src/config/modelProviders/perplexity.ts +1 -45
  53. package/src/config/modelProviders/ppio.ts +1 -152
  54. package/src/config/modelProviders/qiniu.ts +1 -18
  55. package/src/config/modelProviders/qwen.ts +1 -245
  56. package/src/config/modelProviders/search1api.ts +1 -34
  57. package/src/config/modelProviders/sensenova.ts +1 -69
  58. package/src/config/modelProviders/siliconcloud.ts +1 -417
  59. package/src/config/modelProviders/spark.ts +1 -59
  60. package/src/config/modelProviders/stepfun.ts +1 -98
  61. package/src/config/modelProviders/taichu.ts +1 -18
  62. package/src/config/modelProviders/togetherai.ts +1 -274
  63. package/src/config/modelProviders/upstage.ts +1 -28
  64. package/src/config/modelProviders/wenxin.ts +1 -140
  65. package/src/config/modelProviders/xai.ts +1 -38
  66. package/src/config/modelProviders/zeroone.ts +1 -81
  67. package/src/config/modelProviders/zhipu.ts +1 -108
  68. package/src/helpers/isCanUseFC.ts +0 -8
  69. package/src/hooks/useEnabledChatModels.ts +0 -8
  70. package/src/hooks/useModelContextWindowTokens.ts +0 -8
  71. package/src/hooks/useModelHasContextWindowToken.ts +1 -10
  72. package/src/hooks/useModelSupportFiles.ts +1 -11
  73. package/src/hooks/useModelSupportReasoning.ts +1 -11
  74. package/src/hooks/useModelSupportToolUse.ts +1 -11
  75. package/src/hooks/useModelSupportVision.ts +1 -11
  76. package/src/layout/AuthProvider/Clerk/index.tsx +2 -16
  77. package/src/server/globalConfig/index.ts +0 -23
  78. package/src/server/routers/lambda/config/__snapshots__/index.test.ts.snap +175 -12
  79. package/src/server/routers/lambda/config/index.test.ts +36 -28
  80. package/src/services/chat/chat.test.ts +12 -0
  81. package/src/services/chat/helper.ts +7 -31
  82. package/src/services/models.ts +2 -11
  83. package/src/store/chat/slices/aiChat/actions/generateAIChat.ts +41 -14
  84. package/src/store/global/store.ts +1 -7
  85. package/src/store/user/initialState.ts +1 -7
  86. package/src/store/user/selectors.ts +1 -5
  87. package/src/store/user/slices/common/action.ts +5 -4
  88. package/src/store/user/slices/settings/selectors/index.ts +1 -0
  89. package/src/store/user/slices/settings/selectors/keyVaults.ts +21 -0
  90. package/src/store/user/store.ts +0 -3
  91. package/src/tools/web-browsing/Render/Search/ConfigForm/Form.tsx +1 -1
  92. package/packages/utils/src/_deprecated/__snapshots__/parseModels.test.ts.snap +0 -104
  93. package/packages/utils/src/_deprecated/parseModels.test.ts +0 -287
  94. package/packages/utils/src/_deprecated/parseModels.ts +0 -165
  95. package/src/hooks/_header.ts +0 -23
  96. package/src/server/globalConfig/_deprecated.test.ts +0 -92
  97. package/src/server/globalConfig/_deprecated.ts +0 -41
  98. package/src/store/global/actions/clientDb.ts +0 -67
  99. package/src/store/user/slices/modelList/__snapshots__/action.test.ts.snap +0 -12
  100. package/src/store/user/slices/modelList/action.test.ts +0 -359
  101. package/src/store/user/slices/modelList/action.ts +0 -223
  102. package/src/store/user/slices/modelList/initialState.ts +0 -15
  103. package/src/store/user/slices/modelList/reducers/customModelCard.test.ts +0 -204
  104. package/src/store/user/slices/modelList/reducers/customModelCard.ts +0 -64
  105. package/src/store/user/slices/modelList/selectors/index.ts +0 -3
  106. package/src/store/user/slices/modelList/selectors/keyVaults.test.ts +0 -201
  107. package/src/store/user/slices/modelList/selectors/keyVaults.ts +0 -50
  108. package/src/store/user/slices/modelList/selectors/modelConfig.test.ts +0 -219
  109. package/src/store/user/slices/modelList/selectors/modelConfig.ts +0 -95
  110. package/src/store/user/slices/modelList/selectors/modelProvider.test.ts +0 -138
  111. package/src/store/user/slices/modelList/selectors/modelProvider.ts +0 -170
@@ -1,204 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
-
3
- import { ChatModelCard } from '@/types/llm';
4
-
5
- import {
6
- AddCustomModelCard,
7
- DeleteCustomModelCard,
8
- UpdateCustomModelCard,
9
- customModelCardsReducer,
10
- } from './customModelCard';
11
-
12
- describe('customModelCardsReducer', () => {
13
- const initialState: ChatModelCard[] = [
14
- {
15
- id: 'model1',
16
- displayName: 'Model 1',
17
- description: 'A helpful assistant',
18
- files: true,
19
- functionCall: false,
20
- enabled: true,
21
- isCustom: true,
22
- legacy: false,
23
- maxOutput: 1000,
24
- contextWindowTokens: 2048,
25
- vision: false,
26
- },
27
- {
28
- id: 'model2',
29
- displayName: 'Model 2',
30
- description: 'A friendly chatbot',
31
- files: false,
32
- functionCall: true,
33
- isCustom: true,
34
- legacy: true,
35
- maxOutput: 500,
36
- contextWindowTokens: 1024,
37
- vision: true,
38
- },
39
- ];
40
-
41
- it('should add a new custom model card', () => {
42
- const newModelCard: ChatModelCard = {
43
- id: 'model3',
44
- displayName: 'Model 3',
45
- description: 'A versatile assistant',
46
- files: true,
47
- functionCall: true,
48
- enabled: true,
49
- isCustom: true,
50
- legacy: false,
51
- maxOutput: 2000,
52
- contextWindowTokens: 4096,
53
- vision: false,
54
- };
55
-
56
- const action: AddCustomModelCard = {
57
- type: 'add',
58
- modelCard: newModelCard,
59
- };
60
-
61
- const newState = customModelCardsReducer(initialState, action);
62
-
63
- expect(newState).toContainEqual(newModelCard);
64
- expect(newState.length).toBe(initialState.length + 1);
65
- });
66
-
67
- it('should not add a duplicate custom model card', () => {
68
- const duplicateModelCard: ChatModelCard = {
69
- id: 'model1',
70
- displayName: 'Duplicate Model 1',
71
- description: 'A duplicate model',
72
- files: true,
73
- functionCall: false,
74
- enabled: true,
75
- isCustom: true,
76
- legacy: false,
77
- maxOutput: 1000,
78
- contextWindowTokens: 2048,
79
- vision: false,
80
- };
81
-
82
- const action: AddCustomModelCard = {
83
- type: 'add',
84
- modelCard: duplicateModelCard,
85
- };
86
-
87
- const newState = customModelCardsReducer(initialState, action);
88
-
89
- expect(newState).toEqual(initialState);
90
- });
91
-
92
- it('should delete a custom model card', () => {
93
- const action: DeleteCustomModelCard = {
94
- type: 'delete',
95
- id: 'model1',
96
- };
97
-
98
- const newState = customModelCardsReducer(initialState, action);
99
-
100
- expect(newState).not.toContainEqual(initialState[0]);
101
- expect(newState.length).toBe(initialState.length - 1);
102
- });
103
-
104
- it('should update a custom model card', () => {
105
- const action: UpdateCustomModelCard = {
106
- type: 'update',
107
- id: 'model1',
108
- value: { displayName: 'Updated Model 1' },
109
- };
110
-
111
- const newState = customModelCardsReducer(initialState, action);
112
-
113
- expect(newState.find((card) => card.id === 'model1')?.displayName).toBe('Updated Model 1');
114
- expect(newState.length).toBe(initialState.length);
115
- });
116
-
117
- it('should throw an error for unhandled action type', () => {
118
- const invalidAction = {
119
- type: 'invalid',
120
- };
121
-
122
- expect(() => customModelCardsReducer(initialState, invalidAction as any)).toThrowError(
123
- 'Unhandled action type in customModelCardsReducer',
124
- );
125
- });
126
-
127
- it('should return the original state if the model card is not found during update', () => {
128
- const action: UpdateCustomModelCard = {
129
- type: 'update',
130
- id: 'nonexistent',
131
- value: { displayName: 'Updated Nonexistent Model' },
132
- };
133
-
134
- const newState = customModelCardsReducer(initialState, action);
135
-
136
- expect(newState).toEqual(initialState);
137
- });
138
-
139
- it('should return the original state if the model card ID is missing during add', () => {
140
- const newModelCard: ChatModelCard = {
141
- id: '',
142
- displayName: 'Model 4',
143
- description: 'A new model',
144
- files: false,
145
- functionCall: false,
146
- enabled: true,
147
- isCustom: true,
148
- legacy: false,
149
- maxOutput: 1500,
150
- contextWindowTokens: 2048,
151
- vision: false,
152
- };
153
-
154
- const action: AddCustomModelCard = {
155
- type: 'add',
156
- modelCard: newModelCard,
157
- };
158
-
159
- const newState = customModelCardsReducer(initialState, action);
160
-
161
- expect(newState).toEqual(initialState);
162
- });
163
-
164
- it('should handle optional properties correctly', () => {
165
- const newModelCard: ChatModelCard = {
166
- id: 'model4',
167
- };
168
-
169
- const action: AddCustomModelCard = {
170
- type: 'add',
171
- modelCard: newModelCard,
172
- };
173
-
174
- const newState = customModelCardsReducer(initialState, action);
175
-
176
- expect(newState).toContainEqual(newModelCard);
177
- });
178
-
179
- it('should handle an undefined initial state', () => {
180
- const newModelCard: ChatModelCard = {
181
- id: 'model4',
182
- displayName: 'Model 4',
183
- description: 'A new model',
184
- files: false,
185
- functionCall: false,
186
- enabled: true,
187
- isCustom: true,
188
- legacy: false,
189
- maxOutput: 1500,
190
- contextWindowTokens: 2048,
191
- vision: false,
192
- };
193
-
194
- const action: AddCustomModelCard = {
195
- type: 'add',
196
- modelCard: newModelCard,
197
- };
198
-
199
- const newState = customModelCardsReducer(undefined, action);
200
-
201
- expect(newState).toContainEqual(newModelCard);
202
- expect(newState.length).toBe(1);
203
- });
204
- });
@@ -1,64 +0,0 @@
1
- import { produce } from 'immer';
2
-
3
- import { ChatModelCard } from '@/types/llm';
4
-
5
- export interface AddCustomModelCard {
6
- modelCard: ChatModelCard;
7
- type: 'add';
8
- }
9
-
10
- export interface DeleteCustomModelCard {
11
- id: string;
12
- type: 'delete';
13
- }
14
-
15
- export interface UpdateCustomModelCard {
16
- id: string;
17
- type: 'update';
18
- value: Partial<ChatModelCard>;
19
- }
20
-
21
- export type CustomModelCardDispatch =
22
- | AddCustomModelCard
23
- | DeleteCustomModelCard
24
- | UpdateCustomModelCard;
25
-
26
- export const customModelCardsReducer = (
27
- state: ChatModelCard[] | undefined,
28
- payload: CustomModelCardDispatch,
29
- ): ChatModelCard[] => {
30
- switch (payload.type) {
31
- case 'add': {
32
- return produce(state || [], (draftState) => {
33
- const { id } = payload.modelCard;
34
- if (!id) return;
35
- if (draftState.some((card) => card.id === id)) return;
36
-
37
- draftState.push(payload.modelCard);
38
- });
39
- }
40
-
41
- case 'delete': {
42
- return produce(state || [], (draftState) => {
43
- const index = draftState.findIndex((card) => card.id === payload.id);
44
- if (index !== -1) {
45
- draftState.splice(index, 1);
46
- }
47
- });
48
- }
49
-
50
- case 'update': {
51
- return produce(state || [], (draftState) => {
52
- const index = draftState.findIndex((card) => card.id === payload.id);
53
- if (index !== -1) {
54
- const card = draftState[index];
55
- Object.assign(card, payload.value);
56
- }
57
- });
58
- }
59
-
60
- default: {
61
- throw new Error('Unhandled action type in customModelCardsReducer');
62
- }
63
- }
64
- };
@@ -1,3 +0,0 @@
1
- export { keyVaultsConfigSelectors } from './keyVaults';
2
- export { modelConfigSelectors } from './modelConfig';
3
- export { modelProviderSelectors } from './modelProvider';
@@ -1,201 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
-
3
- import { UserStore } from '@/store/user';
4
- import {
5
- AWSBedrockKeyVault,
6
- AzureOpenAIKeyVault,
7
- OpenAICompatibleKeyVault,
8
- } from '@/types/user/settings';
9
- import { merge } from '@/utils/merge';
10
-
11
- import { initialSettingsState } from '../../settings/initialState';
12
- import { keyVaultsConfigSelectors } from './keyVaults';
13
-
14
- describe('keyVaultsConfigSelectors', () => {
15
- describe('isProviderEndpointNotEmpty', () => {
16
- describe('OpenAICompatibleKeyVault', () => {
17
- it('should return true if provider endpoint is not empty', () => {
18
- const s = merge(initialSettingsState, {
19
- settings: {
20
- keyVaults: {
21
- openai: {
22
- endpoint: 'endpoint',
23
- } as OpenAICompatibleKeyVault,
24
- },
25
- },
26
- }) as unknown as UserStore;
27
- expect(keyVaultsConfigSelectors.isProviderEndpointNotEmpty('openai')(s)).toBe(true);
28
- });
29
-
30
- it('should return false if provider endpoint is empty', () => {
31
- const s = merge(initialSettingsState, {
32
- settings: {
33
- keyVaults: {
34
- openai: {
35
- endpoint: undefined,
36
- } as OpenAICompatibleKeyVault,
37
- },
38
- },
39
- }) as unknown as UserStore;
40
- expect(keyVaultsConfigSelectors.isProviderEndpointNotEmpty('openai')(s)).toBe(false);
41
- });
42
- });
43
-
44
- describe('AzureOpenAIKeyVault', () => {
45
- it('should return true if provider endpoint is not empty', () => {
46
- const s = merge(initialSettingsState, {
47
- settings: {
48
- keyVaults: {
49
- azure: {
50
- baseURL: 'baseURL',
51
- } as AzureOpenAIKeyVault,
52
- },
53
- },
54
- }) as unknown as UserStore;
55
- expect(keyVaultsConfigSelectors.isProviderEndpointNotEmpty('azure')(s)).toBe(true);
56
- });
57
-
58
- it('should return false if provider endpoint is empty', () => {
59
- const s = merge(initialSettingsState, {
60
- settings: {
61
- keyVaults: {
62
- azure: {
63
- baseURL: undefined,
64
- } as AzureOpenAIKeyVault,
65
- },
66
- },
67
- }) as unknown as UserStore;
68
- expect(keyVaultsConfigSelectors.isProviderEndpointNotEmpty('azure')(s)).toBe(false);
69
- });
70
- });
71
-
72
- // Always return false for AWSBedrockKeyVault
73
- describe('AWSBedrockKeyVault', () => {
74
- it('should return false if provider region is not empty for AWSBedrockKeyVault', () => {
75
- const s = merge(initialSettingsState, {
76
- settings: {
77
- keyVaults: {
78
- bedrock: {
79
- region: 'region',
80
- } as AWSBedrockKeyVault,
81
- },
82
- },
83
- }) as unknown as UserStore;
84
- expect(keyVaultsConfigSelectors.isProviderEndpointNotEmpty('bedrock')(s)).toBe(false);
85
- });
86
-
87
- it('should return false if provider region is empty for AWSBedrockKeyVault', () => {
88
- const s = merge(initialSettingsState, {
89
- settings: {
90
- keyVaults: {
91
- bedrock: {
92
- region: undefined,
93
- } as AWSBedrockKeyVault,
94
- },
95
- },
96
- }) as unknown as UserStore;
97
- expect(keyVaultsConfigSelectors.isProviderEndpointNotEmpty('bedrock')(s)).toBe(false);
98
- });
99
- });
100
- });
101
-
102
- describe('isProviderApiKeyNotEmpty', () => {
103
- describe('OpenAICompatibleKeyVault', () => {
104
- it('should return true if provider apikey is not empty', () => {
105
- const s = merge(initialSettingsState, {
106
- settings: {
107
- keyVaults: {
108
- openai: {
109
- apiKey: 'apikey',
110
- } as OpenAICompatibleKeyVault,
111
- },
112
- },
113
- }) as unknown as UserStore;
114
- expect(keyVaultsConfigSelectors.isProviderApiKeyNotEmpty('openai')(s)).toBe(true);
115
- });
116
-
117
- it('should return false if provider apikey is empty', () => {
118
- const s = merge(initialSettingsState, {
119
- settings: {
120
- keyVaults: {
121
- openai: {
122
- apiKey: undefined,
123
- } as OpenAICompatibleKeyVault,
124
- },
125
- },
126
- }) as unknown as UserStore;
127
- expect(keyVaultsConfigSelectors.isProviderApiKeyNotEmpty('openai')(s)).toBe(false);
128
- });
129
- });
130
-
131
- describe('AzureOpenAIKeyVault', () => {
132
- it('should return true if provider apikey is not empty', () => {
133
- const s = merge(initialSettingsState, {
134
- settings: {
135
- keyVaults: {
136
- azure: {
137
- apiKey: 'apikey',
138
- } as AzureOpenAIKeyVault,
139
- },
140
- },
141
- }) as unknown as UserStore;
142
- expect(keyVaultsConfigSelectors.isProviderApiKeyNotEmpty('azure')(s)).toBe(true);
143
- });
144
-
145
- it('should return false if provider apikey is empty', () => {
146
- const s = merge(initialSettingsState, {
147
- settings: {
148
- keyVaults: {
149
- azure: {
150
- apiKey: undefined,
151
- } as AzureOpenAIKeyVault,
152
- },
153
- },
154
- }) as unknown as UserStore;
155
- expect(keyVaultsConfigSelectors.isProviderApiKeyNotEmpty('azure')(s)).toBe(false);
156
- });
157
- });
158
-
159
- describe('AWSBedrockKeyVault', () => {
160
- it('should return true if provider accessKeyId is not empty for AWSBedrockKeyVault', () => {
161
- const s = merge(initialSettingsState, {
162
- settings: {
163
- keyVaults: {
164
- bedrock: {
165
- accessKeyId: 'accessKeyId',
166
- } as AWSBedrockKeyVault,
167
- },
168
- },
169
- }) as unknown as UserStore;
170
- expect(keyVaultsConfigSelectors.isProviderApiKeyNotEmpty('bedrock')(s)).toBe(true);
171
- });
172
-
173
- it('should return true if provider secretAccessKey is not empty for AWSBedrockKeyVault', () => {
174
- const s = merge(initialSettingsState, {
175
- settings: {
176
- keyVaults: {
177
- bedrock: {
178
- secretAccessKey: 'secretAccessKey',
179
- } as AWSBedrockKeyVault,
180
- },
181
- },
182
- }) as unknown as UserStore;
183
- expect(keyVaultsConfigSelectors.isProviderApiKeyNotEmpty('bedrock')(s)).toBe(true);
184
- });
185
-
186
- it('should return false if provider accessKeyId and secretAccessKey are both empty for AWSBedrockKeyVault', () => {
187
- const s = merge(initialSettingsState, {
188
- settings: {
189
- keyVaults: {
190
- bedrock: {
191
- accessKeyId: undefined,
192
- secretAccessKey: undefined,
193
- } as AWSBedrockKeyVault,
194
- },
195
- },
196
- }) as unknown as UserStore;
197
- expect(keyVaultsConfigSelectors.isProviderApiKeyNotEmpty('bedrock')(s)).toBe(false);
198
- });
199
- });
200
- });
201
- });
@@ -1,50 +0,0 @@
1
- import { UserStore } from '@/store/user';
2
- import {
3
- AWSBedrockKeyVault,
4
- AzureOpenAIKeyVault,
5
- ComfyUIKeyVault,
6
- GlobalLLMProviderKey,
7
- OpenAICompatibleKeyVault,
8
- UserKeyVaults,
9
- } from '@/types/user/settings';
10
-
11
- import { currentSettings } from '../../settings/selectors/settings';
12
-
13
- export const keyVaultsSettings = (s: UserStore): UserKeyVaults =>
14
- currentSettings(s).keyVaults || {};
15
-
16
- const openAIConfig = (s: UserStore) => keyVaultsSettings(s).openai || {};
17
- const bedrockConfig = (s: UserStore) => keyVaultsSettings(s).bedrock || {};
18
- const ollamaConfig = (s: UserStore) => keyVaultsSettings(s).ollama || {};
19
- const azureConfig = (s: UserStore) => keyVaultsSettings(s).azure || {};
20
- const cloudflareConfig = (s: UserStore) => keyVaultsSettings(s).cloudflare || {};
21
- const getVaultByProvider = (provider: GlobalLLMProviderKey) => (s: UserStore) =>
22
- (keyVaultsSettings(s)[provider] || {}) as OpenAICompatibleKeyVault &
23
- AzureOpenAIKeyVault &
24
- AWSBedrockKeyVault &
25
- ComfyUIKeyVault;
26
-
27
- const isProviderEndpointNotEmpty = (provider: string) => (s: UserStore) => {
28
- const vault = getVaultByProvider(provider as GlobalLLMProviderKey)(s);
29
- return !!vault?.baseURL || !!vault?.endpoint;
30
- };
31
-
32
- const isProviderApiKeyNotEmpty = (provider: string) => (s: UserStore) => {
33
- const vault = getVaultByProvider(provider as GlobalLLMProviderKey)(s);
34
- return !!vault?.apiKey || !!vault?.accessKeyId || !!vault?.secretAccessKey;
35
- };
36
-
37
- const password = (s: UserStore) => keyVaultsSettings(s).password || '';
38
-
39
- export const keyVaultsConfigSelectors = {
40
- azureConfig,
41
- bedrockConfig,
42
- cloudflareConfig,
43
- getVaultByProvider,
44
- isProviderApiKeyNotEmpty,
45
- isProviderEndpointNotEmpty,
46
- keyVaultsSettings,
47
- ollamaConfig,
48
- openAIConfig,
49
- password,
50
- };