@lobehub/lobehub 2.0.0-next.14 → 2.0.0-next.16

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 (108) hide show
  1. package/.github/workflows/desktop-pr-build.yml +6 -6
  2. package/.github/workflows/release-desktop-beta.yml +4 -4
  3. package/.github/workflows/release.yml +1 -2
  4. package/.github/workflows/test.yml +4 -5
  5. package/.nvmrc +1 -1
  6. package/CHANGELOG.md +42 -0
  7. package/apps/desktop/tsconfig.json +0 -1
  8. package/changelog/v1.json +14 -0
  9. package/docs/self-hosting/advanced/feature-flags.mdx +0 -1
  10. package/docs/self-hosting/advanced/feature-flags.zh-CN.mdx +0 -1
  11. package/e2e/tsconfig.json +0 -1
  12. package/package.json +58 -58
  13. package/packages/types/src/serverConfig.ts +2 -6
  14. package/packages/web-crawler/tsconfig.json +0 -1
  15. package/src/app/[variants]/(auth)/signup/[[...signup]]/page.tsx +1 -8
  16. package/src/app/[variants]/(main)/(mobile)/me/(home)/features/UserBanner.tsx +3 -6
  17. package/src/app/[variants]/(main)/labs/components/LabCard.tsx +3 -1
  18. package/src/app/[variants]/(main)/settings/provider/detail/azure/index.tsx +5 -7
  19. package/src/components/InvalidAPIKey/APIKeyForm/Bedrock.tsx +8 -13
  20. package/src/config/featureFlags/schema.test.ts +0 -2
  21. package/src/config/featureFlags/schema.ts +0 -6
  22. package/src/config/modelProviders/ai21.ts +1 -16
  23. package/src/config/modelProviders/ai302.ts +1 -128
  24. package/src/config/modelProviders/ai360.ts +1 -32
  25. package/src/config/modelProviders/anthropic.ts +1 -71
  26. package/src/config/modelProviders/azure.ts +1 -51
  27. package/src/config/modelProviders/baichuan.ts +1 -57
  28. package/src/config/modelProviders/bedrock.ts +1 -276
  29. package/src/config/modelProviders/cloudflare.ts +1 -64
  30. package/src/config/modelProviders/deepseek.ts +1 -19
  31. package/src/config/modelProviders/fireworksai.ts +1 -174
  32. package/src/config/modelProviders/giteeai.ts +1 -135
  33. package/src/config/modelProviders/github.ts +1 -254
  34. package/src/config/modelProviders/google.ts +1 -130
  35. package/src/config/modelProviders/groq.ts +1 -119
  36. package/src/config/modelProviders/higress.ts +1 -1713
  37. package/src/config/modelProviders/huggingface.ts +1 -54
  38. package/src/config/modelProviders/hunyuan.ts +1 -83
  39. package/src/config/modelProviders/infiniai.ts +1 -74
  40. package/src/config/modelProviders/internlm.ts +1 -20
  41. package/src/config/modelProviders/mistral.ts +1 -95
  42. package/src/config/modelProviders/modelscope.ts +1 -27
  43. package/src/config/modelProviders/moonshot.ts +1 -29
  44. package/src/config/modelProviders/novita.ts +1 -105
  45. package/src/config/modelProviders/ollama.ts +1 -325
  46. package/src/config/modelProviders/openai.ts +1 -242
  47. package/src/config/modelProviders/openrouter.ts +1 -240
  48. package/src/config/modelProviders/perplexity.ts +1 -45
  49. package/src/config/modelProviders/ppio.ts +1 -152
  50. package/src/config/modelProviders/qiniu.ts +1 -18
  51. package/src/config/modelProviders/qwen.ts +1 -245
  52. package/src/config/modelProviders/search1api.ts +1 -34
  53. package/src/config/modelProviders/sensenova.ts +1 -69
  54. package/src/config/modelProviders/siliconcloud.ts +1 -417
  55. package/src/config/modelProviders/spark.ts +1 -59
  56. package/src/config/modelProviders/stepfun.ts +1 -98
  57. package/src/config/modelProviders/taichu.ts +1 -18
  58. package/src/config/modelProviders/togetherai.ts +1 -274
  59. package/src/config/modelProviders/upstage.ts +1 -28
  60. package/src/config/modelProviders/wenxin.ts +1 -140
  61. package/src/config/modelProviders/xai.ts +1 -38
  62. package/src/config/modelProviders/zeroone.ts +1 -81
  63. package/src/config/modelProviders/zhipu.ts +1 -108
  64. package/src/helpers/isCanUseFC.ts +0 -8
  65. package/src/hooks/useEnabledChatModels.ts +0 -8
  66. package/src/hooks/useModelContextWindowTokens.ts +0 -8
  67. package/src/hooks/useModelHasContextWindowToken.ts +1 -10
  68. package/src/hooks/useModelSupportFiles.ts +1 -11
  69. package/src/hooks/useModelSupportReasoning.ts +1 -11
  70. package/src/hooks/useModelSupportToolUse.ts +1 -11
  71. package/src/hooks/useModelSupportVision.ts +1 -11
  72. package/src/layout/AuthProvider/Clerk/index.tsx +2 -16
  73. package/src/server/globalConfig/index.ts +0 -23
  74. package/src/server/routers/lambda/config/__snapshots__/index.test.ts.snap +175 -12
  75. package/src/server/routers/lambda/config/index.test.ts +36 -28
  76. package/src/services/chat/chat.test.ts +12 -0
  77. package/src/services/chat/helper.ts +7 -31
  78. package/src/services/models.ts +2 -11
  79. package/src/store/chat/slices/aiChat/actions/generateAIChat.ts +41 -14
  80. package/src/store/global/store.ts +1 -7
  81. package/src/store/user/initialState.ts +1 -7
  82. package/src/store/user/selectors.ts +1 -5
  83. package/src/store/user/slices/common/action.ts +5 -4
  84. package/src/store/user/slices/settings/selectors/index.ts +1 -0
  85. package/src/store/user/slices/settings/selectors/keyVaults.ts +21 -0
  86. package/src/store/user/store.ts +0 -3
  87. package/src/tools/web-browsing/Render/Search/ConfigForm/Form.tsx +1 -1
  88. package/tsconfig.json +0 -1
  89. package/packages/utils/src/_deprecated/__snapshots__/parseModels.test.ts.snap +0 -104
  90. package/packages/utils/src/_deprecated/parseModels.test.ts +0 -287
  91. package/packages/utils/src/_deprecated/parseModels.ts +0 -165
  92. package/src/hooks/_header.ts +0 -23
  93. package/src/server/globalConfig/_deprecated.test.ts +0 -92
  94. package/src/server/globalConfig/_deprecated.ts +0 -41
  95. package/src/store/global/actions/clientDb.ts +0 -67
  96. package/src/store/user/slices/modelList/__snapshots__/action.test.ts.snap +0 -12
  97. package/src/store/user/slices/modelList/action.test.ts +0 -359
  98. package/src/store/user/slices/modelList/action.ts +0 -223
  99. package/src/store/user/slices/modelList/initialState.ts +0 -15
  100. package/src/store/user/slices/modelList/reducers/customModelCard.test.ts +0 -204
  101. package/src/store/user/slices/modelList/reducers/customModelCard.ts +0 -64
  102. package/src/store/user/slices/modelList/selectors/index.ts +0 -3
  103. package/src/store/user/slices/modelList/selectors/keyVaults.test.ts +0 -201
  104. package/src/store/user/slices/modelList/selectors/keyVaults.ts +0 -50
  105. package/src/store/user/slices/modelList/selectors/modelConfig.test.ts +0 -219
  106. package/src/store/user/slices/modelList/selectors/modelConfig.ts +0 -95
  107. package/src/store/user/slices/modelList/selectors/modelProvider.test.ts +0 -138
  108. 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
- };