bingocode 1.0.18 → 1.0.20
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/bin/claude +1 -1
- package/package.json +1 -1
- package/src/cli/ProviderPanel.tsx +47 -9
- package/src/entrypoints/init.ts +9 -1
- package/src/manager/CliMenuManager.tsx +84 -8
- package/src/server/__tests__/conversation-service.test.ts +7 -7
- package/src/server/__tests__/haha-oauth-service.test.ts +1 -1
- package/src/server/__tests__/providers-real.test.ts +15 -15
- package/src/server/api/computer-use.ts +2 -2
- package/src/server/api/providers.ts +6 -2
- package/src/server/cli/listProviders.ts +1 -1
- package/src/server/cli/providerManager.ts +68 -19
- package/src/server/cli/providersMenu.tsx +74 -44
- package/src/server/config/providers.yaml +207 -207
- package/src/server/proxy/handler.ts +30 -47
- package/src/server/proxy/streaming/anthropicStreamLabeler.ts +56 -0
- package/src/server/services/conversationService.ts +5 -5
- package/src/server/services/hahaOAuthService.ts +1 -1
- package/src/server/services/providerManager.ts +1 -1
- package/src/server/services/providerService.ts +32 -14
- package/src/server/types/provider.ts +1 -0
- package/src/utils/computerUse/wrapper.tsx +2 -2
- package/src/utils/config.ts +11 -5
- package/src/utils/managedEnv.ts +23 -15
- package/src/utils/preflightChecks.tsx +3 -3
- package/src/utils/proxy.ts +13 -1
|
@@ -30,8 +30,9 @@ const FIXED_APIFMT = 'openai_chat';
|
|
|
30
30
|
|
|
31
31
|
const ProvidersMenu: React.FC = () => {
|
|
32
32
|
const { exit } = useApp();
|
|
33
|
+
const [modelOptions, setModelOptions] = useState<string[]>([]);
|
|
33
34
|
const [modelSelectIdx, setModelSelectIdx] = useState(0);
|
|
34
|
-
const [addStep, setAddStep] = useState(0); // 0
|
|
35
|
+
const [addStep, setAddStep] = useState(0); // 0:输入key并加载模型, 1:选模型
|
|
35
36
|
const [inputKey, setInputKey] = useState('');
|
|
36
37
|
const [addError, setAddError] = useState('');
|
|
37
38
|
const [mode, setMode] = useState<UiMode>('list');
|
|
@@ -44,6 +45,9 @@ const ProvidersMenu: React.FC = () => {
|
|
|
44
45
|
const [msg, setMsg] = useState<string>('');
|
|
45
46
|
const [detail, setDetail] = useState<SavedProvider | null>(null);
|
|
46
47
|
const [presets, setPresets] = useState<any[]>([]);
|
|
48
|
+
// 临时存储当前正在配置的 Provider 草案
|
|
49
|
+
const [pendingProvider, setPendingProvider] = useState<CreateProviderInput | null>(null);
|
|
50
|
+
|
|
47
51
|
useEffect(() => { ProviderManager.listPresets().then(setPresets).catch(()=>setPresets([])); }, []);
|
|
48
52
|
|
|
49
53
|
const refresh = async () => {
|
|
@@ -54,7 +58,14 @@ const ProvidersMenu: React.FC = () => {
|
|
|
54
58
|
};
|
|
55
59
|
useEffect(() => { refresh(); }, []);
|
|
56
60
|
useEffect(() => {
|
|
57
|
-
if (mode !== 'add') {
|
|
61
|
+
if (mode !== 'add') {
|
|
62
|
+
setAddStep(0);
|
|
63
|
+
setInputKey('');
|
|
64
|
+
setAddError('');
|
|
65
|
+
setModelSelectIdx(0);
|
|
66
|
+
setModelOptions([]);
|
|
67
|
+
setPendingProvider(null);
|
|
68
|
+
}
|
|
58
69
|
}, [mode]);
|
|
59
70
|
|
|
60
71
|
// 主界面 LIST 模式
|
|
@@ -96,33 +107,55 @@ const ProvidersMenu: React.FC = () => {
|
|
|
96
107
|
setMode('list'); setAddError(''); setInputKey(''); setAddStep(0);
|
|
97
108
|
return;
|
|
98
109
|
}
|
|
99
|
-
// 步骤
|
|
100
|
-
if (addStep === 0) {
|
|
101
|
-
if (key.downArrow) setModelSelectIdx(idx => Math.min(
|
|
110
|
+
// 步骤1: 选模型
|
|
111
|
+
if (addStep === 1 && modelOptions.length > 0) {
|
|
112
|
+
if (key.downArrow) setModelSelectIdx(idx => Math.min(modelOptions.length - 1, idx + 1));
|
|
102
113
|
else if (key.upArrow) setModelSelectIdx(idx => Math.max(0, idx - 1));
|
|
103
|
-
else if (key.return) {
|
|
114
|
+
else if (key.return) {
|
|
115
|
+
completeAdd(modelOptions[modelSelectIdx]);
|
|
116
|
+
}
|
|
104
117
|
}
|
|
105
118
|
});
|
|
106
119
|
|
|
107
|
-
//
|
|
108
|
-
const
|
|
109
|
-
const selectedModel = MODEL_OPTIONS[modelSelectIdx];
|
|
110
|
-
const presetId = selectedModel.replace(/[^a-zA-Z0-9]/g, '') + '-preset';
|
|
111
|
-
const name = `${selectedModel} Provider`;
|
|
120
|
+
// 获取模型并进入下一步
|
|
121
|
+
const fetchModelsStep = async (keyInput: string) => {
|
|
112
122
|
if (!keyInput.trim()) { setAddError('API Key 不能为空'); return; }
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
123
|
+
setAddError('正在获取模型列表...');
|
|
124
|
+
try {
|
|
125
|
+
// 如果没有 pendingProvider,手动创建一个(比如 Custom 模式)
|
|
126
|
+
const draft = pendingProvider || {
|
|
127
|
+
presetId: 'custom-' + Date.now(),
|
|
128
|
+
name: 'Custom Provider',
|
|
129
|
+
baseUrl: FIXED_BASEURL,
|
|
130
|
+
apiFormat: FIXED_APIFMT,
|
|
131
|
+
apiKey: keyInput.trim(),
|
|
132
|
+
models: { main: '', haiku: '', sonnet: '', opus: '' }
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const models = await ProviderManager.fetchModels(draft, keyInput.trim());
|
|
136
|
+
if (models.length === 0) {
|
|
137
|
+
setAddError('未获取到可用模型,请检查 API Key 或网络连通性。');
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
setModelOptions(models);
|
|
141
|
+
setPendingProvider({ ...draft, apiKey: keyInput.trim() });
|
|
142
|
+
setAddStep(1);
|
|
143
|
+
setAddError('');
|
|
144
|
+
} catch (e: any) {
|
|
145
|
+
setAddError('获取模型失败: ' + (e.message || '未知错误'));
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const completeAdd = async (selectedModel: string) => {
|
|
150
|
+
if (!pendingProvider) return;
|
|
151
|
+
const name = pendingProvider.name || `${selectedModel} Provider`;
|
|
152
|
+
|
|
119
153
|
await ProviderManager.addProvider({
|
|
120
|
-
|
|
121
|
-
|
|
154
|
+
...pendingProvider,
|
|
155
|
+
name,
|
|
122
156
|
models: { main: selectedModel, haiku: '', sonnet: '', opus: '' }
|
|
123
157
|
});
|
|
124
|
-
|
|
125
|
-
delete (global as any).__PM_APIFMT_OVERRIDE__;
|
|
158
|
+
|
|
126
159
|
setMode('list');
|
|
127
160
|
setAddStep(0);
|
|
128
161
|
setInputKey('');
|
|
@@ -153,25 +186,25 @@ const ProvidersMenu: React.FC = () => {
|
|
|
153
186
|
{/* 新增 */}
|
|
154
187
|
{mode === 'add' && (
|
|
155
188
|
<Box flexDirection="column">
|
|
156
|
-
<Text>选择模型与输入API Key:</Text>
|
|
157
189
|
{addStep === 0
|
|
158
190
|
? <>
|
|
159
|
-
|
|
160
|
-
<Text key={m} color={idx === modelSelectIdx ? 'yellow' : undefined}>
|
|
161
|
-
{idx === modelSelectIdx ? '> ' : ' '}{m}
|
|
162
|
-
</Text>
|
|
163
|
-
))}
|
|
164
|
-
<Text color="gray">↑↓选择,回车下一步,q返回</Text>
|
|
165
|
-
</>
|
|
166
|
-
: <>
|
|
167
|
-
<Text>已选模型:{MODEL_OPTIONS[modelSelectIdx]}</Text>
|
|
191
|
+
<Text>请输入 API Key (将自动拉取可用模型):</Text>
|
|
168
192
|
<TextInput
|
|
169
193
|
value={inputKey}
|
|
170
194
|
onChange={setInputKey}
|
|
171
|
-
onSubmit={
|
|
195
|
+
onSubmit={fetchModelsStep}
|
|
172
196
|
placeholder="请输入API Key"
|
|
173
197
|
/>
|
|
174
|
-
<Text color="gray"
|
|
198
|
+
<Text color="gray">输入后回车继续,q返回</Text>
|
|
199
|
+
</>
|
|
200
|
+
: <>
|
|
201
|
+
<Text>获取成功!请选择主模型:</Text>
|
|
202
|
+
{modelOptions.map((m, idx) => (
|
|
203
|
+
<Text key={m} color={idx === modelSelectIdx ? 'yellow' : undefined}>
|
|
204
|
+
{idx === modelSelectIdx ? '> ' : ' '}{m}
|
|
205
|
+
</Text>
|
|
206
|
+
))}
|
|
207
|
+
<Text color="gray">↑↓选择,回车保存,q返回</Text>
|
|
175
208
|
</>
|
|
176
209
|
}
|
|
177
210
|
{addError && <Text color="red">{addError}</Text>}
|
|
@@ -259,17 +292,14 @@ const ProvidersMenu: React.FC = () => {
|
|
|
259
292
|
<SelectInput
|
|
260
293
|
items={presets.map((p: any) => ({ label: `${p.name || p.id} ${p.baseUrl || ''}`, value: p.id }))}
|
|
261
294
|
onSelect={async it => {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
(global as any).__PM_APIFMT_OVERRIDE__ = presetFmt;
|
|
271
|
-
setMode('add');
|
|
272
|
-
setAddStep(1); // 直接跳到 Key 输入
|
|
295
|
+
try {
|
|
296
|
+
const draft = await ProviderManager.applyPreset(it.value);
|
|
297
|
+
setPendingProvider(draft);
|
|
298
|
+
setMode('add');
|
|
299
|
+
setAddStep(0); // 去输入 Key
|
|
300
|
+
} catch (e: any) {
|
|
301
|
+
setMsg('预设加载失败: ' + e.message);
|
|
302
|
+
}
|
|
273
303
|
}}
|
|
274
304
|
/>
|
|
275
305
|
<Text color="gray">回车选择预设,q 返回</Text>
|
|
@@ -1,207 +1,207 @@
|
|
|
1
|
-
version: 2
|
|
2
|
-
|
|
3
|
-
# Provider 预设配置
|
|
4
|
-
# fields 数组声明新增时需填写的字段
|
|
5
|
-
# key: 'name' | 'apiKey' | 'baseUrl' 直接映射到顶层字段,其余存入 extra.<key>
|
|
6
|
-
# secret: true 时前端使用密码掩码显示
|
|
7
|
-
#
|
|
8
|
-
# modelsUrl: 相对于 baseUrl 的模型列表路径,空字符串表示不支持动态拉取
|
|
9
|
-
# modelsAuthStyle: bearer → Authorization: Bearer <apiKey>
|
|
10
|
-
# x-api-key → x-api-key: <apiKey> + anthropic-version header
|
|
11
|
-
# modelsDataPath: 响应 JSON 中模型数组的字段名(几乎总是 'data')
|
|
12
|
-
|
|
13
|
-
presets:
|
|
14
|
-
- id: official
|
|
15
|
-
name: Claude Official
|
|
16
|
-
baseUrl: ''
|
|
17
|
-
apiFormat: anthropic
|
|
18
|
-
needsApiKey: false
|
|
19
|
-
websiteUrl: https://www.anthropic.com/claude-code
|
|
20
|
-
modelsUrl: /v1/models
|
|
21
|
-
modelsAuthStyle: x-api-key
|
|
22
|
-
modelsDataPath: data
|
|
23
|
-
fields:
|
|
24
|
-
- key: name
|
|
25
|
-
label: Provider 昵称
|
|
26
|
-
required: true
|
|
27
|
-
secret: false
|
|
28
|
-
placeholder: 'e.g. Claude Official'
|
|
29
|
-
|
|
30
|
-
- id: openai
|
|
31
|
-
name: OpenAI
|
|
32
|
-
baseUrl: https://api.openai.com/v1
|
|
33
|
-
apiFormat: openai_chat
|
|
34
|
-
needsApiKey: true
|
|
35
|
-
websiteUrl: https://platform.openai.com
|
|
36
|
-
modelsUrl: /v1/models
|
|
37
|
-
modelsAuthStyle: bearer
|
|
38
|
-
modelsDataPath: data
|
|
39
|
-
fields:
|
|
40
|
-
- key: name
|
|
41
|
-
label: Provider 昵称
|
|
42
|
-
required: true
|
|
43
|
-
secret: false
|
|
44
|
-
placeholder: 'e.g. My OpenAI'
|
|
45
|
-
- key: apiKey
|
|
46
|
-
label: API Key
|
|
47
|
-
required: true
|
|
48
|
-
secret: true
|
|
49
|
-
placeholder: 'sk-...'
|
|
50
|
-
- key: baseUrl
|
|
51
|
-
label: Base URL (Optional)
|
|
52
|
-
required: false
|
|
53
|
-
secret: false
|
|
54
|
-
default: https://api.openai.com/v1
|
|
55
|
-
placeholder: 'https://api.openai.com/v1'
|
|
56
|
-
|
|
57
|
-
- id: gemini
|
|
58
|
-
name: Google Gemini
|
|
59
|
-
baseUrl: https://generativelanguage.googleapis.com/v1beta/openai
|
|
60
|
-
apiFormat: openai_chat
|
|
61
|
-
needsApiKey: true
|
|
62
|
-
websiteUrl: https://aistudio.google.com
|
|
63
|
-
modelsUrl: /v1/models
|
|
64
|
-
modelsAuthStyle: bearer
|
|
65
|
-
modelsDataPath: data
|
|
66
|
-
fields:
|
|
67
|
-
- key: name
|
|
68
|
-
label: Provider 昵称
|
|
69
|
-
required: true
|
|
70
|
-
secret: false
|
|
71
|
-
placeholder: 'e.g. My Gemini'
|
|
72
|
-
- key: apiKey
|
|
73
|
-
label: API Key
|
|
74
|
-
required: true
|
|
75
|
-
secret: true
|
|
76
|
-
placeholder: 'Gemini API Key'
|
|
77
|
-
|
|
78
|
-
- id: mistral
|
|
79
|
-
name: Mistral AI
|
|
80
|
-
baseUrl: https://api.mistral.ai/v1
|
|
81
|
-
apiFormat: openai_chat
|
|
82
|
-
needsApiKey: true
|
|
83
|
-
websiteUrl: https://console.mistral.ai
|
|
84
|
-
modelsUrl: /v1/models
|
|
85
|
-
modelsAuthStyle: bearer
|
|
86
|
-
modelsDataPath: data
|
|
87
|
-
fields:
|
|
88
|
-
- key: name
|
|
89
|
-
label: Provider 昵称
|
|
90
|
-
required: true
|
|
91
|
-
secret: false
|
|
92
|
-
placeholder: 'e.g. My Mistral'
|
|
93
|
-
- key: apiKey
|
|
94
|
-
label: API Key
|
|
95
|
-
required: true
|
|
96
|
-
secret: true
|
|
97
|
-
placeholder: 'Mistral API Key'
|
|
98
|
-
|
|
99
|
-
- id: deepseek
|
|
100
|
-
name: DeepSeek
|
|
101
|
-
baseUrl: https://api.deepseek.com
|
|
102
|
-
apiFormat:
|
|
103
|
-
needsApiKey: true
|
|
104
|
-
websiteUrl: https://platform.deepseek.com
|
|
105
|
-
modelsUrl: /v1/models
|
|
106
|
-
modelsAuthStyle: bearer
|
|
107
|
-
modelsDataPath: data
|
|
108
|
-
fields:
|
|
109
|
-
- key: name
|
|
110
|
-
label: Provider 昵称
|
|
111
|
-
required: true
|
|
112
|
-
secret: false
|
|
113
|
-
placeholder: 'e.g. My DeepSeek'
|
|
114
|
-
- key: apiKey
|
|
115
|
-
label: API Key
|
|
116
|
-
required: true
|
|
117
|
-
secret: true
|
|
118
|
-
placeholder: 'sk-...'
|
|
119
|
-
|
|
120
|
-
- id: zhipuglm
|
|
121
|
-
name: Zhipu GLM
|
|
122
|
-
baseUrl: https://open.bigmodel.cn/api/
|
|
123
|
-
apiFormat:
|
|
124
|
-
needsApiKey: true
|
|
125
|
-
websiteUrl: https://open.bigmodel.cn
|
|
126
|
-
modelsUrl: /
|
|
127
|
-
modelsAuthStyle: bearer
|
|
128
|
-
modelsDataPath: data
|
|
129
|
-
fields:
|
|
130
|
-
- key: name
|
|
131
|
-
label: Provider 昵称
|
|
132
|
-
required: true
|
|
133
|
-
secret: false
|
|
134
|
-
placeholder: 'e.g. My GLM'
|
|
135
|
-
- key: apiKey
|
|
136
|
-
label: API Key
|
|
137
|
-
required: true
|
|
138
|
-
secret: true
|
|
139
|
-
placeholder: '智谱 API Key'
|
|
140
|
-
|
|
141
|
-
- id: kimi
|
|
142
|
-
name: Kimi
|
|
143
|
-
baseUrl: https://api.moonshot.cn/
|
|
144
|
-
apiFormat:
|
|
145
|
-
needsApiKey: true
|
|
146
|
-
websiteUrl: https://platform.moonshot.cn
|
|
147
|
-
modelsUrl: /
|
|
148
|
-
modelsAuthStyle: bearer
|
|
149
|
-
modelsDataPath: data
|
|
150
|
-
fields:
|
|
151
|
-
- key: name
|
|
152
|
-
label: Provider 昵称
|
|
153
|
-
required: true
|
|
154
|
-
secret: false
|
|
155
|
-
placeholder: 'e.g. My Kimi'
|
|
156
|
-
- key: apiKey
|
|
157
|
-
label: API Key
|
|
158
|
-
required: true
|
|
159
|
-
secret: true
|
|
160
|
-
placeholder: 'Moonshot API Key'
|
|
161
|
-
|
|
162
|
-
- id: minimax
|
|
163
|
-
name: MiniMax
|
|
164
|
-
baseUrl: https://api.minimaxi.com/
|
|
165
|
-
apiFormat:
|
|
166
|
-
needsApiKey: true
|
|
167
|
-
websiteUrl: https://platform.minimaxi.com
|
|
168
|
-
modelsUrl: /
|
|
169
|
-
modelsAuthStyle: bearer
|
|
170
|
-
modelsDataPath: data
|
|
171
|
-
fields:
|
|
172
|
-
- key: name
|
|
173
|
-
label: Provider 昵称
|
|
174
|
-
required: true
|
|
175
|
-
secret: false
|
|
176
|
-
placeholder: 'e.g. My MiniMax'
|
|
177
|
-
- key: apiKey
|
|
178
|
-
label: API Key
|
|
179
|
-
required: true
|
|
180
|
-
secret: true
|
|
181
|
-
placeholder: 'MiniMax API Key'
|
|
182
|
-
|
|
183
|
-
- id: custom
|
|
184
|
-
name: Custom
|
|
185
|
-
baseUrl: ''
|
|
186
|
-
apiFormat: openai_chat
|
|
187
|
-
needsApiKey: true
|
|
188
|
-
websiteUrl: ''
|
|
189
|
-
modelsUrl: /v1/models
|
|
190
|
-
modelsAuthStyle: bearer
|
|
191
|
-
modelsDataPath: data
|
|
192
|
-
fields:
|
|
193
|
-
- key: name
|
|
194
|
-
label: Provider 昵称
|
|
195
|
-
required: true
|
|
196
|
-
secret: false
|
|
197
|
-
placeholder: 'e.g. My Custom Provider'
|
|
198
|
-
- key: baseUrl
|
|
199
|
-
label: Base URL
|
|
200
|
-
required: true
|
|
201
|
-
secret: false
|
|
202
|
-
placeholder: 'https://your-api-endpoint.com/v1'
|
|
203
|
-
- key: apiKey
|
|
204
|
-
label: API Key
|
|
205
|
-
required: false
|
|
206
|
-
secret: true
|
|
207
|
-
placeholder: '(可选)API Key'
|
|
1
|
+
version: 2
|
|
2
|
+
|
|
3
|
+
# Provider 预设配置
|
|
4
|
+
# fields 数组声明新增时需填写的字段
|
|
5
|
+
# key: 'name' | 'apiKey' | 'baseUrl' 直接映射到顶层字段,其余存入 extra.<key>
|
|
6
|
+
# secret: true 时前端使用密码掩码显示
|
|
7
|
+
#
|
|
8
|
+
# modelsUrl: 相对于 baseUrl 的模型列表路径,空字符串表示不支持动态拉取
|
|
9
|
+
# modelsAuthStyle: bearer → Authorization: Bearer <apiKey>
|
|
10
|
+
# x-api-key → x-api-key: <apiKey> + anthropic-version header
|
|
11
|
+
# modelsDataPath: 响应 JSON 中模型数组的字段名(几乎总是 'data')
|
|
12
|
+
|
|
13
|
+
presets:
|
|
14
|
+
- id: official
|
|
15
|
+
name: Claude Official
|
|
16
|
+
baseUrl: ''
|
|
17
|
+
apiFormat: anthropic
|
|
18
|
+
needsApiKey: false
|
|
19
|
+
websiteUrl: https://www.anthropic.com/claude-code
|
|
20
|
+
modelsUrl: /v1/models
|
|
21
|
+
modelsAuthStyle: x-api-key
|
|
22
|
+
modelsDataPath: data
|
|
23
|
+
fields:
|
|
24
|
+
- key: name
|
|
25
|
+
label: Provider 昵称
|
|
26
|
+
required: true
|
|
27
|
+
secret: false
|
|
28
|
+
placeholder: 'e.g. Claude Official'
|
|
29
|
+
|
|
30
|
+
- id: openai
|
|
31
|
+
name: OpenAI
|
|
32
|
+
baseUrl: https://api.openai.com/v1
|
|
33
|
+
apiFormat: openai_chat
|
|
34
|
+
needsApiKey: true
|
|
35
|
+
websiteUrl: https://platform.openai.com
|
|
36
|
+
modelsUrl: /v1/models
|
|
37
|
+
modelsAuthStyle: bearer
|
|
38
|
+
modelsDataPath: data
|
|
39
|
+
fields:
|
|
40
|
+
- key: name
|
|
41
|
+
label: Provider 昵称
|
|
42
|
+
required: true
|
|
43
|
+
secret: false
|
|
44
|
+
placeholder: 'e.g. My OpenAI'
|
|
45
|
+
- key: apiKey
|
|
46
|
+
label: API Key
|
|
47
|
+
required: true
|
|
48
|
+
secret: true
|
|
49
|
+
placeholder: 'sk-...'
|
|
50
|
+
- key: baseUrl
|
|
51
|
+
label: Base URL (Optional)
|
|
52
|
+
required: false
|
|
53
|
+
secret: false
|
|
54
|
+
default: https://api.openai.com/v1
|
|
55
|
+
placeholder: 'https://api.openai.com/v1'
|
|
56
|
+
|
|
57
|
+
- id: gemini
|
|
58
|
+
name: Google Gemini
|
|
59
|
+
baseUrl: https://generativelanguage.googleapis.com/v1beta/openai
|
|
60
|
+
apiFormat: openai_chat
|
|
61
|
+
needsApiKey: true
|
|
62
|
+
websiteUrl: https://aistudio.google.com
|
|
63
|
+
modelsUrl: /v1/models
|
|
64
|
+
modelsAuthStyle: bearer
|
|
65
|
+
modelsDataPath: data
|
|
66
|
+
fields:
|
|
67
|
+
- key: name
|
|
68
|
+
label: Provider 昵称
|
|
69
|
+
required: true
|
|
70
|
+
secret: false
|
|
71
|
+
placeholder: 'e.g. My Gemini'
|
|
72
|
+
- key: apiKey
|
|
73
|
+
label: API Key
|
|
74
|
+
required: true
|
|
75
|
+
secret: true
|
|
76
|
+
placeholder: 'Gemini API Key'
|
|
77
|
+
|
|
78
|
+
- id: mistral
|
|
79
|
+
name: Mistral AI
|
|
80
|
+
baseUrl: https://api.mistral.ai/v1
|
|
81
|
+
apiFormat: openai_chat
|
|
82
|
+
needsApiKey: true
|
|
83
|
+
websiteUrl: https://console.mistral.ai
|
|
84
|
+
modelsUrl: /v1/models
|
|
85
|
+
modelsAuthStyle: bearer
|
|
86
|
+
modelsDataPath: data
|
|
87
|
+
fields:
|
|
88
|
+
- key: name
|
|
89
|
+
label: Provider 昵称
|
|
90
|
+
required: true
|
|
91
|
+
secret: false
|
|
92
|
+
placeholder: 'e.g. My Mistral'
|
|
93
|
+
- key: apiKey
|
|
94
|
+
label: API Key
|
|
95
|
+
required: true
|
|
96
|
+
secret: true
|
|
97
|
+
placeholder: 'Mistral API Key'
|
|
98
|
+
|
|
99
|
+
- id: deepseek
|
|
100
|
+
name: DeepSeek
|
|
101
|
+
baseUrl: https://api.deepseek.com
|
|
102
|
+
apiFormat: openai_chat
|
|
103
|
+
needsApiKey: true
|
|
104
|
+
websiteUrl: https://platform.deepseek.com
|
|
105
|
+
modelsUrl: /v1/models
|
|
106
|
+
modelsAuthStyle: bearer
|
|
107
|
+
modelsDataPath: data
|
|
108
|
+
fields:
|
|
109
|
+
- key: name
|
|
110
|
+
label: Provider 昵称
|
|
111
|
+
required: true
|
|
112
|
+
secret: false
|
|
113
|
+
placeholder: 'e.g. My DeepSeek'
|
|
114
|
+
- key: apiKey
|
|
115
|
+
label: API Key
|
|
116
|
+
required: true
|
|
117
|
+
secret: true
|
|
118
|
+
placeholder: 'sk-...'
|
|
119
|
+
|
|
120
|
+
- id: zhipuglm
|
|
121
|
+
name: Zhipu GLM
|
|
122
|
+
baseUrl: https://open.bigmodel.cn/api/paas/v4
|
|
123
|
+
apiFormat: openai_chat
|
|
124
|
+
needsApiKey: true
|
|
125
|
+
websiteUrl: https://open.bigmodel.cn
|
|
126
|
+
modelsUrl: /models
|
|
127
|
+
modelsAuthStyle: bearer
|
|
128
|
+
modelsDataPath: data
|
|
129
|
+
fields:
|
|
130
|
+
- key: name
|
|
131
|
+
label: Provider 昵称
|
|
132
|
+
required: true
|
|
133
|
+
secret: false
|
|
134
|
+
placeholder: 'e.g. My GLM'
|
|
135
|
+
- key: apiKey
|
|
136
|
+
label: API Key
|
|
137
|
+
required: true
|
|
138
|
+
secret: true
|
|
139
|
+
placeholder: '智谱 API Key'
|
|
140
|
+
|
|
141
|
+
- id: kimi
|
|
142
|
+
name: Kimi
|
|
143
|
+
baseUrl: https://api.moonshot.cn/v1
|
|
144
|
+
apiFormat: openai_chat
|
|
145
|
+
needsApiKey: true
|
|
146
|
+
websiteUrl: https://platform.moonshot.cn
|
|
147
|
+
modelsUrl: /models
|
|
148
|
+
modelsAuthStyle: bearer
|
|
149
|
+
modelsDataPath: data
|
|
150
|
+
fields:
|
|
151
|
+
- key: name
|
|
152
|
+
label: Provider 昵称
|
|
153
|
+
required: true
|
|
154
|
+
secret: false
|
|
155
|
+
placeholder: 'e.g. My Kimi'
|
|
156
|
+
- key: apiKey
|
|
157
|
+
label: API Key
|
|
158
|
+
required: true
|
|
159
|
+
secret: true
|
|
160
|
+
placeholder: 'Moonshot API Key'
|
|
161
|
+
|
|
162
|
+
- id: minimax
|
|
163
|
+
name: MiniMax
|
|
164
|
+
baseUrl: https://api.minimaxi.com/v1
|
|
165
|
+
apiFormat: openai_chat
|
|
166
|
+
needsApiKey: true
|
|
167
|
+
websiteUrl: https://platform.minimaxi.com
|
|
168
|
+
modelsUrl: /models
|
|
169
|
+
modelsAuthStyle: bearer
|
|
170
|
+
modelsDataPath: data
|
|
171
|
+
fields:
|
|
172
|
+
- key: name
|
|
173
|
+
label: Provider 昵称
|
|
174
|
+
required: true
|
|
175
|
+
secret: false
|
|
176
|
+
placeholder: 'e.g. My MiniMax'
|
|
177
|
+
- key: apiKey
|
|
178
|
+
label: API Key
|
|
179
|
+
required: true
|
|
180
|
+
secret: true
|
|
181
|
+
placeholder: 'MiniMax API Key'
|
|
182
|
+
|
|
183
|
+
- id: custom
|
|
184
|
+
name: Custom
|
|
185
|
+
baseUrl: ''
|
|
186
|
+
apiFormat: openai_chat
|
|
187
|
+
needsApiKey: true
|
|
188
|
+
websiteUrl: ''
|
|
189
|
+
modelsUrl: /v1/models
|
|
190
|
+
modelsAuthStyle: bearer
|
|
191
|
+
modelsDataPath: data
|
|
192
|
+
fields:
|
|
193
|
+
- key: name
|
|
194
|
+
label: Provider 昵称
|
|
195
|
+
required: true
|
|
196
|
+
secret: false
|
|
197
|
+
placeholder: 'e.g. My Custom Provider'
|
|
198
|
+
- key: baseUrl
|
|
199
|
+
label: Base URL
|
|
200
|
+
required: true
|
|
201
|
+
secret: false
|
|
202
|
+
placeholder: 'https://your-api-endpoint.com/v1'
|
|
203
|
+
- key: apiKey
|
|
204
|
+
label: API Key
|
|
205
|
+
required: false
|
|
206
|
+
secret: true
|
|
207
|
+
placeholder: '(可选)API Key'
|