protocol-proxy 2.2.0 → 2.3.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/converters/anthropic-to-gemini.js +253 -0
- package/lib/converters/gemini-to-anthropic.js +275 -0
- package/lib/converters/gemini-to-openai.js +238 -0
- package/lib/converters/openai-to-gemini.js +284 -0
- package/lib/detector.js +4 -0
- package/lib/proxy-server.js +44 -5
- package/lib/stats-store.js +11 -13
- package/package.json +2 -3
- package/public/app.js +24 -4
- package/public/index.html +9 -4
- package/public/style.css +44 -2
- package/server.js +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "protocol-proxy",
|
|
3
|
-
"version": "2.2
|
|
3
|
+
"version": "2.3.2",
|
|
4
4
|
"description": "OpenAI / Anthropic 协议转换透明代理",
|
|
5
5
|
"main": "server.js",
|
|
6
6
|
"bin": {
|
|
@@ -27,8 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"cors": "^2.8.5",
|
|
30
|
-
"express": "^4.19.2"
|
|
31
|
-
"puppeteer-core": "^24.43.0"
|
|
30
|
+
"express": "^4.19.2"
|
|
32
31
|
},
|
|
33
32
|
"devDependencies": {
|
|
34
33
|
"pkg": "^5.8.1"
|
package/public/app.js
CHANGED
|
@@ -211,6 +211,8 @@ function selectProvider(id) {
|
|
|
211
211
|
const models = provider?.models || [];
|
|
212
212
|
selectModel(models[0] || '');
|
|
213
213
|
updateModelAddState();
|
|
214
|
+
// 同步 API Key placeholder
|
|
215
|
+
document.getElementById('target-key').placeholder = provider?.apiKey ? '已设置(留空则不修改)' : 'sk-...';
|
|
214
216
|
// 同步 Azure 字段
|
|
215
217
|
document.getElementById('target-azure-deployment').value = provider?.azureDeployment || '';
|
|
216
218
|
document.getElementById('target-azure-version').value = provider?.azureApiVersion || '';
|
|
@@ -440,11 +442,16 @@ async function confirmImport() {
|
|
|
440
442
|
|
|
441
443
|
async function restartAllProxies() {
|
|
442
444
|
try {
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
445
|
+
// 先停掉所有运行中的代理(不管 ID 是否匹配新配置)
|
|
446
|
+
const statusRes = await fetch('/api/status');
|
|
447
|
+
const status = await statusRes.json();
|
|
448
|
+
const runningIds = (status.running || []).map(r => r.id);
|
|
449
|
+
for (const id of runningIds) {
|
|
450
|
+
await fetch(`/api/proxies/${id}/stop`, { method: 'POST' });
|
|
447
451
|
}
|
|
452
|
+
// 重新加载配置
|
|
453
|
+
await loadProxies();
|
|
454
|
+
// 按新配置启动所有代理
|
|
448
455
|
for (const p of proxies) {
|
|
449
456
|
await fetch(`/api/proxies/${p.id}/start`, { method: 'POST' });
|
|
450
457
|
}
|
|
@@ -466,6 +473,10 @@ async function loadStats() {
|
|
|
466
473
|
try {
|
|
467
474
|
const params = new URLSearchParams({ range: statsRange });
|
|
468
475
|
if (statsProxyId) params.set('proxyId', statsProxyId);
|
|
476
|
+
const startDate = document.getElementById('stats-start-date')?.value;
|
|
477
|
+
const endDate = document.getElementById('stats-end-date')?.value;
|
|
478
|
+
if (startDate) params.set('startDate', startDate);
|
|
479
|
+
if (endDate) params.set('endDate', endDate);
|
|
469
480
|
const res = await fetch('/api/stats?' + params);
|
|
470
481
|
const data = await res.json();
|
|
471
482
|
renderStatsSummary(data.summary);
|
|
@@ -577,9 +588,15 @@ function initStatsRangeBtns() {
|
|
|
577
588
|
document.querySelectorAll('.stats-range-btn').forEach(b => b.classList.remove('active'));
|
|
578
589
|
btn.classList.add('active');
|
|
579
590
|
statsRange = btn.dataset.range;
|
|
591
|
+
// 清空日期选择器,显示全部数据
|
|
592
|
+
document.getElementById('stats-start-date').value = '';
|
|
593
|
+
document.getElementById('stats-end-date').value = '';
|
|
580
594
|
loadStats();
|
|
581
595
|
});
|
|
582
596
|
});
|
|
597
|
+
// 日期选择器变化时自动加载
|
|
598
|
+
document.getElementById('stats-start-date').addEventListener('change', loadStats);
|
|
599
|
+
document.getElementById('stats-end-date').addEventListener('change', loadStats);
|
|
583
600
|
}
|
|
584
601
|
|
|
585
602
|
function generateToken() {
|
|
@@ -635,6 +652,9 @@ async function init() {
|
|
|
635
652
|
initSimpleDropdown('protocol-dropdown', (val) => {
|
|
636
653
|
document.getElementById('azure-fields').style.display = val === 'openai' ? '' : 'none';
|
|
637
654
|
});
|
|
655
|
+
// 初始状态:根据当前协议值决定 Azure 字段显示
|
|
656
|
+
const initProto = document.getElementById('target-protocol').value;
|
|
657
|
+
document.getElementById('azure-fields').style.display = initProto === 'openai' ? '' : 'none';
|
|
638
658
|
}
|
|
639
659
|
|
|
640
660
|
// ==================== 代理地址复制 ====================
|
package/public/index.html
CHANGED
|
@@ -42,6 +42,10 @@
|
|
|
42
42
|
<button class="btn btn-sm stats-range-btn active" data-range="daily">每日</button>
|
|
43
43
|
<button class="btn btn-sm stats-range-btn" data-range="monthly">每月</button>
|
|
44
44
|
<button class="btn btn-sm stats-range-btn" data-range="yearly">每年</button>
|
|
45
|
+
<span class="stats-date-sep">|</span>
|
|
46
|
+
<input type="date" id="stats-start-date" class="stats-date-input" placeholder="开始日期">
|
|
47
|
+
<span class="stats-date-sep">~</span>
|
|
48
|
+
<input type="date" id="stats-end-date" class="stats-date-input" placeholder="结束日期">
|
|
45
49
|
</div>
|
|
46
50
|
</div>
|
|
47
51
|
</div>
|
|
@@ -160,6 +164,7 @@
|
|
|
160
164
|
<div class="model-dropdown-options" id="protocol-dropdown-options">
|
|
161
165
|
<div class="model-option selected" data-value="openai"><span class="model-option-name">OpenAI</span></div>
|
|
162
166
|
<div class="model-option" data-value="anthropic"><span class="model-option-name">Anthropic</span></div>
|
|
167
|
+
<div class="model-option" data-value="gemini"><span class="model-option-name">Gemini</span></div>
|
|
163
168
|
</div>
|
|
164
169
|
</div>
|
|
165
170
|
</div>
|
|
@@ -190,12 +195,12 @@
|
|
|
190
195
|
</div>
|
|
191
196
|
<div class="form-row" id="azure-fields" style="display:none">
|
|
192
197
|
<div class="form-group">
|
|
193
|
-
<label>Azure Deployment
|
|
194
|
-
<input type="text" id="target-azure-deployment" placeholder="
|
|
198
|
+
<label>Azure Deployment <span style="color:#64748b;font-size:0.75rem">(仅 Azure 用户填写)</span></label>
|
|
199
|
+
<input type="text" id="target-azure-deployment" placeholder="仅 Azure 用户填写">
|
|
195
200
|
</div>
|
|
196
201
|
<div class="form-group">
|
|
197
|
-
<label>Azure API Version
|
|
198
|
-
<input type="text" id="target-azure-version" placeholder="
|
|
202
|
+
<label>Azure API Version <span style="color:#64748b;font-size:0.75rem">(仅 Azure 用户填写)</span></label>
|
|
203
|
+
<input type="text" id="target-azure-version" placeholder="仅 Azure 用户填写">
|
|
199
204
|
</div>
|
|
200
205
|
</div>
|
|
201
206
|
</div>
|
package/public/style.css
CHANGED
|
@@ -954,7 +954,8 @@ form {
|
|
|
954
954
|
.stats-controls {
|
|
955
955
|
display: flex;
|
|
956
956
|
gap: 12px;
|
|
957
|
-
|
|
957
|
+
flex-wrap: wrap;
|
|
958
|
+
justify-content: flex-end; align-items: center;
|
|
958
959
|
}
|
|
959
960
|
|
|
960
961
|
.stats-controls .model-dropdown {
|
|
@@ -970,6 +971,7 @@ form {
|
|
|
970
971
|
.stats-range-btns {
|
|
971
972
|
display: flex;
|
|
972
973
|
gap: 4px;
|
|
974
|
+
align-items: center;
|
|
973
975
|
background: rgba(6, 8, 15, 0.4);
|
|
974
976
|
border-radius: 10px;
|
|
975
977
|
padding: 3px;
|
|
@@ -995,7 +997,38 @@ form {
|
|
|
995
997
|
.stats-range-btn.active {
|
|
996
998
|
background: rgba(59, 130, 246, 0.2) !important;
|
|
997
999
|
color: #60a5fa !important;
|
|
998
|
-
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
.stats-date-range {
|
|
1003
|
+
display: flex;
|
|
1004
|
+
align-items: center;
|
|
1005
|
+
gap: 4px;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
.stats-date-input {
|
|
1009
|
+
background: rgba(15, 23, 42, 0.6);
|
|
1010
|
+
border: 1px solid rgba(51, 65, 85, 0.5);
|
|
1011
|
+
border-radius: 6px;
|
|
1012
|
+
color: #e2e8f0;
|
|
1013
|
+
padding: 6px 8px;
|
|
1014
|
+
font-size: 0.78rem;
|
|
1015
|
+
outline: none;
|
|
1016
|
+
transition: border-color 0.2s;
|
|
1017
|
+
width: 125px;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
.stats-date-input:focus {
|
|
1021
|
+
border-color: #3b82f6;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
.stats-date-input::-webkit-calendar-picker-indicator {
|
|
1025
|
+
filter: invert(0.7);
|
|
1026
|
+
cursor: pointer;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
.stats-date-sep {
|
|
1030
|
+
color: #475569;
|
|
1031
|
+
font-size: 0.85rem;
|
|
999
1032
|
}
|
|
1000
1033
|
|
|
1001
1034
|
.stats-summary {
|
|
@@ -1123,6 +1156,15 @@ form {
|
|
|
1123
1156
|
.stats-controls .model-dropdown {
|
|
1124
1157
|
width: 100%;
|
|
1125
1158
|
}
|
|
1159
|
+
|
|
1160
|
+
.stats-date-range {
|
|
1161
|
+
width: 100%;
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
.stats-date-input {
|
|
1165
|
+
flex: 1;
|
|
1166
|
+
min-width: 0;
|
|
1167
|
+
}
|
|
1126
1168
|
}
|
|
1127
1169
|
|
|
1128
1170
|
/* Responsive */
|
package/server.js
CHANGED
|
@@ -596,6 +596,8 @@ process.on('SIGINT', async () => {
|
|
|
596
596
|
removePid();
|
|
597
597
|
try {
|
|
598
598
|
const proxyManager = require('./lib/proxy-manager');
|
|
599
|
+
const statsStore = require('./lib/stats-store');
|
|
600
|
+
statsStore.flush();
|
|
599
601
|
await proxyManager.stopAll();
|
|
600
602
|
} catch (err) {
|
|
601
603
|
console.error('[Shutdown] stopAll error:', err.message);
|
|
@@ -607,6 +609,8 @@ process.on('SIGTERM', async () => {
|
|
|
607
609
|
removePid();
|
|
608
610
|
try {
|
|
609
611
|
const proxyManager = require('./lib/proxy-manager');
|
|
612
|
+
const statsStore = require('./lib/stats-store');
|
|
613
|
+
statsStore.flush();
|
|
610
614
|
await proxyManager.stopAll();
|
|
611
615
|
} catch (err) {
|
|
612
616
|
console.error('[Shutdown] stopAll error:', err.message);
|