protocol-proxy 2.0.1 → 2.0.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.
- package/lib/config-store.js +47 -1
- package/package.json +1 -1
- package/public/app.js +4 -1
- package/public/index.html +1 -0
- package/server.js +6 -1
package/lib/config-store.js
CHANGED
|
@@ -21,6 +21,50 @@ migrateOldConfig();
|
|
|
21
21
|
|
|
22
22
|
let configCache = null;
|
|
23
23
|
|
|
24
|
+
// 迁移旧格式:target → providerId
|
|
25
|
+
function migrateTargetToProvider(config) {
|
|
26
|
+
if (!Array.isArray(config.proxies)) return config;
|
|
27
|
+
let changed = false;
|
|
28
|
+
|
|
29
|
+
for (const proxy of config.proxies) {
|
|
30
|
+
if (!proxy.target) continue;
|
|
31
|
+
|
|
32
|
+
// 有 target 但没有 providerId → 从 target 创建供应商
|
|
33
|
+
if (!proxy.providerId) {
|
|
34
|
+
const t = proxy.target;
|
|
35
|
+
const provider = {
|
|
36
|
+
id: 'provider-' + Date.now(),
|
|
37
|
+
name: t.providerName || t.providerUrl,
|
|
38
|
+
url: t.providerUrl,
|
|
39
|
+
protocol: t.protocol || 'openai',
|
|
40
|
+
apiKey: t.apiKey || '',
|
|
41
|
+
models: Array.isArray(t.models) ? t.models : [],
|
|
42
|
+
};
|
|
43
|
+
config.providers = config.providers || [];
|
|
44
|
+
config.providers.push(provider);
|
|
45
|
+
proxy.providerId = provider.id;
|
|
46
|
+
proxy.defaultModel = t.defaultModel || '';
|
|
47
|
+
delete proxy.target;
|
|
48
|
+
changed = true;
|
|
49
|
+
} else {
|
|
50
|
+
// 有 target 也有 providerId → 迁移 apiKey 到供应商,删除 target
|
|
51
|
+
const provider = (config.providers || []).find(p => p.id === proxy.providerId);
|
|
52
|
+
if (provider && proxy.target.apiKey && !provider.apiKey) {
|
|
53
|
+
provider.apiKey = proxy.target.apiKey;
|
|
54
|
+
changed = true;
|
|
55
|
+
}
|
|
56
|
+
delete proxy.target;
|
|
57
|
+
changed = true;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (changed) {
|
|
62
|
+
configCache = config;
|
|
63
|
+
saveConfig(config);
|
|
64
|
+
}
|
|
65
|
+
return config;
|
|
66
|
+
}
|
|
67
|
+
|
|
24
68
|
function normalizeModels(models) {
|
|
25
69
|
if (!Array.isArray(models)) return [];
|
|
26
70
|
return Array.from(new Set(
|
|
@@ -58,7 +102,9 @@ function loadConfig() {
|
|
|
58
102
|
return configCache;
|
|
59
103
|
}
|
|
60
104
|
const raw = fs.readFileSync(CONFIG_PATH, 'utf-8');
|
|
61
|
-
|
|
105
|
+
let config = normalizeConfig(JSON.parse(raw));
|
|
106
|
+
config = migrateTargetToProvider(config);
|
|
107
|
+
configCache = config;
|
|
62
108
|
return configCache;
|
|
63
109
|
} catch (err) {
|
|
64
110
|
console.error('加载配置失败:', err.message);
|
package/package.json
CHANGED
package/public/app.js
CHANGED
|
@@ -40,6 +40,7 @@ function initProviderDropdown() {
|
|
|
40
40
|
const dropdown = document.getElementById('provider-dropdown');
|
|
41
41
|
const addNameInput = document.getElementById('provider-add-name');
|
|
42
42
|
const addUrlInput = document.getElementById('provider-add-url');
|
|
43
|
+
const addKeyInput = document.getElementById('provider-add-key');
|
|
43
44
|
const addBtn = document.getElementById('provider-add-btn');
|
|
44
45
|
|
|
45
46
|
trigger.addEventListener('click', (e) => {
|
|
@@ -48,6 +49,7 @@ function initProviderDropdown() {
|
|
|
48
49
|
if (dropdown.classList.contains('open')) {
|
|
49
50
|
addNameInput.value = '';
|
|
50
51
|
addUrlInput.value = '';
|
|
52
|
+
addKeyInput.value = '';
|
|
51
53
|
renderProviderOptions();
|
|
52
54
|
addNameInput.focus();
|
|
53
55
|
}
|
|
@@ -62,6 +64,7 @@ function initProviderDropdown() {
|
|
|
62
64
|
addBtn.addEventListener('click', async () => {
|
|
63
65
|
const name = addNameInput.value.trim();
|
|
64
66
|
const url = addUrlInput.value.trim();
|
|
67
|
+
const apiKey = addKeyInput.value.trim();
|
|
65
68
|
if (!name || !url) {
|
|
66
69
|
showToast('请填写供应商名称和地址', true);
|
|
67
70
|
return;
|
|
@@ -70,7 +73,7 @@ function initProviderDropdown() {
|
|
|
70
73
|
const res = await fetch('/api/providers', {
|
|
71
74
|
method: 'POST',
|
|
72
75
|
headers: { 'Content-Type': 'application/json' },
|
|
73
|
-
body: JSON.stringify({ name, url }),
|
|
76
|
+
body: JSON.stringify({ name, url, apiKey }),
|
|
74
77
|
});
|
|
75
78
|
if (!res.ok) {
|
|
76
79
|
const err = await res.json();
|
package/public/index.html
CHANGED
|
@@ -85,6 +85,7 @@
|
|
|
85
85
|
<div class="model-add-section">
|
|
86
86
|
<input type="text" class="model-add-input" id="provider-add-name" placeholder="供应商名称">
|
|
87
87
|
<input type="url" class="model-add-input" id="provider-add-url" placeholder="https://api.example.com">
|
|
88
|
+
<input type="password" class="model-add-input" id="provider-add-key" placeholder="API Key">
|
|
88
89
|
<button type="button" class="btn btn-primary btn-sm" id="provider-add-btn">添加</button>
|
|
89
90
|
</div>
|
|
90
91
|
</div>
|
package/server.js
CHANGED
|
@@ -235,7 +235,12 @@ async function init() {
|
|
|
235
235
|
const proxies = configStore.getProxies().map(p => {
|
|
236
236
|
const provider = configStore.getProviderById(p.providerId);
|
|
237
237
|
return {
|
|
238
|
-
|
|
238
|
+
id: p.id,
|
|
239
|
+
name: p.name,
|
|
240
|
+
port: p.port,
|
|
241
|
+
requireAuth: p.requireAuth,
|
|
242
|
+
authToken: p.authToken,
|
|
243
|
+
providerId: p.providerId,
|
|
239
244
|
providerName: provider?.name || '',
|
|
240
245
|
providerUrl: provider?.url || '',
|
|
241
246
|
protocol: provider?.protocol || '',
|