coding-proxy 0.2.4a2__py3-none-any.whl → 0.2.4a4__py3-none-any.whl
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.
- coding/proxy/config/config.default.yaml +1 -1
- coding/proxy/routing/executor.py +42 -10
- coding/proxy/server/dashboard.py +23 -9
- coding/proxy/server/request_normalizer.py +144 -0
- {coding_proxy-0.2.4a2.dist-info → coding_proxy-0.2.4a4.dist-info}/METADATA +3 -3
- {coding_proxy-0.2.4a2.dist-info → coding_proxy-0.2.4a4.dist-info}/RECORD +9 -9
- {coding_proxy-0.2.4a2.dist-info → coding_proxy-0.2.4a4.dist-info}/WHEEL +0 -0
- {coding_proxy-0.2.4a2.dist-info → coding_proxy-0.2.4a4.dist-info}/entry_points.txt +0 -0
- {coding_proxy-0.2.4a2.dist-info → coding_proxy-0.2.4a4.dist-info}/licenses/LICENSE +0 -0
coding/proxy/routing/executor.py
CHANGED
|
@@ -233,7 +233,7 @@ class _RouteExecutor:
|
|
|
233
233
|
"""为指定 tier 准备请求体,必要时应用 Anthropic 专属修复(Phase 2).
|
|
234
234
|
|
|
235
235
|
仅当 tier 为 Anthropic 时才执行以下处理:
|
|
236
|
-
1. tool_result
|
|
236
|
+
1. 跨供应商 tool_use/tool_result 配对强制修复(单遍自包含扫描)
|
|
237
237
|
2. 条件化 thinking block 剥离(仅跨供应商场景)
|
|
238
238
|
|
|
239
239
|
确保 Zhipu 等其他 vendor 不受影响。
|
|
@@ -241,30 +241,28 @@ class _RouteExecutor:
|
|
|
241
241
|
if tier.name != "anthropic":
|
|
242
242
|
return body
|
|
243
243
|
|
|
244
|
-
|
|
245
|
-
normalization
|
|
244
|
+
needs_tool_pairing = self._needs_tool_pairing_enforcement(
|
|
245
|
+
normalization, session_record
|
|
246
246
|
)
|
|
247
247
|
needs_thinking_strip = self._needs_thinking_strip(normalization, session_record)
|
|
248
248
|
|
|
249
|
-
if not
|
|
249
|
+
if not needs_tool_pairing and not needs_thinking_strip:
|
|
250
250
|
return body
|
|
251
251
|
|
|
252
252
|
from ..server.request_normalizer import (
|
|
253
|
-
|
|
253
|
+
enforce_anthropic_tool_pairing,
|
|
254
254
|
strip_thinking_blocks,
|
|
255
255
|
)
|
|
256
256
|
|
|
257
257
|
body_for_vendor = copy.deepcopy(body)
|
|
258
258
|
|
|
259
|
-
if
|
|
260
|
-
fixes =
|
|
259
|
+
if needs_tool_pairing:
|
|
260
|
+
fixes = enforce_anthropic_tool_pairing(
|
|
261
261
|
body_for_vendor.get("messages", []),
|
|
262
|
-
normalization.misplaced_tool_results,
|
|
263
|
-
normalization.misplaced_log_info,
|
|
264
262
|
)
|
|
265
263
|
if fixes:
|
|
266
264
|
logger.debug(
|
|
267
|
-
"Applied
|
|
265
|
+
"Applied tool pairing enforcement for tier %s: %s",
|
|
268
266
|
tier.name,
|
|
269
267
|
", ".join(fixes),
|
|
270
268
|
)
|
|
@@ -279,6 +277,40 @@ class _RouteExecutor:
|
|
|
279
277
|
|
|
280
278
|
return body_for_vendor
|
|
281
279
|
|
|
280
|
+
@staticmethod
|
|
281
|
+
def _needs_tool_pairing_enforcement(
|
|
282
|
+
normalization: Any, session_record: Any
|
|
283
|
+
) -> bool:
|
|
284
|
+
"""判断是否需要强制执行 Anthropic tool_use/tool_result 配对修复.
|
|
285
|
+
|
|
286
|
+
此方法扩展了原有 ``has_anthropic_fixes`` 的触发条件,覆盖以下场景:
|
|
287
|
+
|
|
288
|
+
1. 请求体中检测到跨供应商产物(如非标准 ID、misplaced tool_result)
|
|
289
|
+
2. Phase 1 检测到需要 Anthropic 修复(misplaced 或 ID 重写)
|
|
290
|
+
3. 会话历史中存在非 Anthropic 供应商记录(如 zhipu)
|
|
291
|
+
4. 无会话追踪能力时安全回退
|
|
292
|
+
|
|
293
|
+
条件 3 和 4 确保即使请求体本身无跨供应商产物(如 zhipu 使用标准
|
|
294
|
+
``toolu_*`` ID 时),只要会话曾经过非 Anthropic 供应商,仍会执行配对修复。
|
|
295
|
+
"""
|
|
296
|
+
# Signal 1: 当前请求体有跨供应商产物
|
|
297
|
+
if normalization is not None and normalization.has_cross_vendor_signals:
|
|
298
|
+
return True
|
|
299
|
+
# Signal 2: Phase 1 检测到需要 Anthropic 修复
|
|
300
|
+
if normalization is not None and normalization.has_anthropic_fixes:
|
|
301
|
+
return True
|
|
302
|
+
# Signal 3: 无会话追踪 → 安全回退
|
|
303
|
+
if session_record is None:
|
|
304
|
+
return True
|
|
305
|
+
# Signal 4: 会话历史中有非 Anthropic 供应商
|
|
306
|
+
if session_record.provider_state:
|
|
307
|
+
non_anthropic = {
|
|
308
|
+
v for v in session_record.provider_state if v != "anthropic"
|
|
309
|
+
}
|
|
310
|
+
if non_anthropic:
|
|
311
|
+
return True
|
|
312
|
+
return False
|
|
313
|
+
|
|
282
314
|
@staticmethod
|
|
283
315
|
def _needs_thinking_strip(normalization: Any, session_record: Any) -> bool:
|
|
284
316
|
"""判断是否需要剥离 thinking blocks(仅跨供应商场景).
|
coding/proxy/server/dashboard.py
CHANGED
|
@@ -911,8 +911,21 @@ function updateVendorStatus(status) {
|
|
|
911
911
|
}).join('');
|
|
912
912
|
}
|
|
913
913
|
|
|
914
|
+
// ── 按 tiers 顺序排序 vendor 列表 ─────────────────────────
|
|
915
|
+
function sortByTierOrder(vendors, tierOrder) {
|
|
916
|
+
if (!tierOrder || !tierOrder.length) return vendors.sort();
|
|
917
|
+
const orderMap = {};
|
|
918
|
+
tierOrder.forEach((name, i) => { orderMap[name] = i; });
|
|
919
|
+
const maxIdx = tierOrder.length;
|
|
920
|
+
return vendors.sort((a, b) => {
|
|
921
|
+
const ia = orderMap[a] ?? maxIdx;
|
|
922
|
+
const ib = orderMap[b] ?? maxIdx;
|
|
923
|
+
return ia !== ib ? ia - ib : a.localeCompare(b);
|
|
924
|
+
});
|
|
925
|
+
}
|
|
926
|
+
|
|
914
927
|
// ── 时序折线图(请求量,按 vendor)────────────────────────
|
|
915
|
-
function buildTimeline(rows) {
|
|
928
|
+
function buildTimeline(rows, tierOrder) {
|
|
916
929
|
const vendorDateMap = {};
|
|
917
930
|
const allDates = new Set();
|
|
918
931
|
for (const r of rows) {
|
|
@@ -923,7 +936,7 @@ function buildTimeline(rows) {
|
|
|
923
936
|
allDates.add(d);
|
|
924
937
|
}
|
|
925
938
|
const dates = [...allDates].sort();
|
|
926
|
-
const vendors = Object.keys(vendorDateMap)
|
|
939
|
+
const vendors = sortByTierOrder(Object.keys(vendorDateMap), tierOrder);
|
|
927
940
|
|
|
928
941
|
if (chartTimeline) chartTimeline.destroy();
|
|
929
942
|
const ctx = document.getElementById('chart-timeline').getContext('2d');
|
|
@@ -962,14 +975,14 @@ function buildTimeline(rows) {
|
|
|
962
975
|
}
|
|
963
976
|
|
|
964
977
|
// ── 供应商分布环形图 ──────────────────────────────────────
|
|
965
|
-
function buildVendorDist(rows) {
|
|
978
|
+
function buildVendorDist(rows, tierOrder) {
|
|
966
979
|
const vendorTotals = {};
|
|
967
980
|
for (const r of rows) {
|
|
968
981
|
const v = r.vendor;
|
|
969
982
|
if (!isValidLabel(v)) continue;
|
|
970
983
|
vendorTotals[v] = (vendorTotals[v] || 0) + (r.total_requests || 0);
|
|
971
984
|
}
|
|
972
|
-
const labels = Object.keys(vendorTotals)
|
|
985
|
+
const labels = sortByTierOrder(Object.keys(vendorTotals), tierOrder);
|
|
973
986
|
const data = labels.map(v => vendorTotals[v]);
|
|
974
987
|
|
|
975
988
|
if (chartVendorDist) chartVendorDist.destroy();
|
|
@@ -1027,7 +1040,7 @@ function buildVendorDist(rows) {
|
|
|
1027
1040
|
}
|
|
1028
1041
|
|
|
1029
1042
|
// ── Token 量趋势折线图(按 vendor)───────────────────────
|
|
1030
|
-
function buildTokenTimeline(rows) {
|
|
1043
|
+
function buildTokenTimeline(rows, tierOrder) {
|
|
1031
1044
|
const vendorDateMap = {};
|
|
1032
1045
|
const allDates = new Set();
|
|
1033
1046
|
for (const r of rows) {
|
|
@@ -1040,7 +1053,7 @@ function buildTokenTimeline(rows) {
|
|
|
1040
1053
|
allDates.add(d);
|
|
1041
1054
|
}
|
|
1042
1055
|
const dates = [...allDates].sort();
|
|
1043
|
-
const vendors = Object.keys(vendorDateMap)
|
|
1056
|
+
const vendors = sortByTierOrder(Object.keys(vendorDateMap), tierOrder);
|
|
1044
1057
|
|
|
1045
1058
|
if (chartTokenTimeline) chartTokenTimeline.destroy();
|
|
1046
1059
|
const ctx = document.getElementById('chart-token-timeline').getContext('2d');
|
|
@@ -1258,9 +1271,10 @@ async function refresh() {
|
|
|
1258
1271
|
updateChartTitles(days);
|
|
1259
1272
|
|
|
1260
1273
|
const rows = timeline.rows || [];
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1274
|
+
const tierOrder = (status.tiers || []).map(t => t.name);
|
|
1275
|
+
buildTimeline(rows, tierOrder);
|
|
1276
|
+
buildVendorDist(rows, tierOrder);
|
|
1277
|
+
buildTokenTimeline(rows, tierOrder);
|
|
1264
1278
|
buildModelTokenTimeline(rows);
|
|
1265
1279
|
|
|
1266
1280
|
document.getElementById('refresh-time').textContent = '上次刷新: ' + now();
|
|
@@ -487,6 +487,150 @@ def _repair_orphaned_tool_use(
|
|
|
487
487
|
return repaired
|
|
488
488
|
|
|
489
489
|
|
|
490
|
+
# ── Phase 2: 跨供应商 tool_use/tool_result 配对强制修复 ─────────
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
def enforce_anthropic_tool_pairing(
|
|
494
|
+
messages_list: list[dict[str, Any]],
|
|
495
|
+
) -> list[str]:
|
|
496
|
+
"""为跨供应商场景强制保证 Anthropic tool_use/tool_result 配对约束.
|
|
497
|
+
|
|
498
|
+
单次正向遍历所有消息,对每个 assistant 消息执行:
|
|
499
|
+
|
|
500
|
+
1. 剥离所有 tool_result 块(跨供应商产物,如 GLM-5 内联的 tool_result)
|
|
501
|
+
2. 收集所有 tool_use ID
|
|
502
|
+
3. 确保紧邻的下一条消息是 user 消息且包含所有必需的 tool_result
|
|
503
|
+
4. 将剥离的 tool_result 重定位到正确的 user 消息
|
|
504
|
+
5. 为仍缺失的 tool_result 合成 ``is_error=True`` 的占位块
|
|
505
|
+
|
|
506
|
+
此函数是一个**自包含的单遍处理**,不依赖 Phase 1 收集的 misplaced 信息,
|
|
507
|
+
通过直接扫描消息列表确保处理的完备性。替代此前多步串联管线
|
|
508
|
+
(剥离 → 重定位 → 孤儿修复)因步骤间隐式依赖导致的漏修问题。
|
|
509
|
+
|
|
510
|
+
仅在请求实际发送给 Anthropic tier 且检测到跨供应商信号时调用,
|
|
511
|
+
确保 Zhipu 等其他 vendor 不受影响。
|
|
512
|
+
|
|
513
|
+
Args:
|
|
514
|
+
messages_list: 消息列表(就地修改)。
|
|
515
|
+
|
|
516
|
+
Returns:
|
|
517
|
+
新增的 adaptation 标签列表。
|
|
518
|
+
"""
|
|
519
|
+
adaptations: list[str] = []
|
|
520
|
+
relocated_count = 0
|
|
521
|
+
synthesized_ids: list[str] = []
|
|
522
|
+
|
|
523
|
+
i = 0
|
|
524
|
+
while i < len(messages_list):
|
|
525
|
+
msg = messages_list[i]
|
|
526
|
+
if not isinstance(msg, dict) or msg.get("role") != "assistant":
|
|
527
|
+
i += 1
|
|
528
|
+
continue
|
|
529
|
+
|
|
530
|
+
content = msg.get("content")
|
|
531
|
+
if not isinstance(content, list):
|
|
532
|
+
i += 1
|
|
533
|
+
continue
|
|
534
|
+
|
|
535
|
+
# ── A. 从 assistant 消息中剥离所有 tool_result 块 ─────────
|
|
536
|
+
extracted_tool_results: dict[str, dict[str, Any]] = {} # tool_use_id → block
|
|
537
|
+
retained_content: list[Any] = []
|
|
538
|
+
for block in content:
|
|
539
|
+
if isinstance(block, dict) and block.get("type") == "tool_result":
|
|
540
|
+
tid = block.get("tool_use_id")
|
|
541
|
+
if tid:
|
|
542
|
+
extracted_tool_results[tid] = block
|
|
543
|
+
relocated_count += 1
|
|
544
|
+
# 无 tool_use_id 的 tool_result 直接丢弃(无效块)
|
|
545
|
+
else:
|
|
546
|
+
retained_content.append(block)
|
|
547
|
+
|
|
548
|
+
if extracted_tool_results:
|
|
549
|
+
msg["content"] = retained_content
|
|
550
|
+
|
|
551
|
+
# ── B. 收集所有 tool_use ID ───────────────────────────────
|
|
552
|
+
tool_use_ids: list[str] = [
|
|
553
|
+
b["id"]
|
|
554
|
+
for b in (
|
|
555
|
+
msg.get("content") if isinstance(msg.get("content"), list) else []
|
|
556
|
+
)
|
|
557
|
+
if isinstance(b, dict) and b.get("type") == "tool_use" and b.get("id")
|
|
558
|
+
]
|
|
559
|
+
if not tool_use_ids:
|
|
560
|
+
# 无 tool_use 块:若剥离后 content 为空,插入占位
|
|
561
|
+
current_content = msg.get("content")
|
|
562
|
+
if isinstance(current_content, list) and not current_content:
|
|
563
|
+
msg["content"] = [{"type": "text", "text": ""}]
|
|
564
|
+
i += 1
|
|
565
|
+
continue
|
|
566
|
+
|
|
567
|
+
# ── C. 确保 messages[i+1] 是 user 消息 ───────────────────
|
|
568
|
+
next_idx = i + 1
|
|
569
|
+
if (
|
|
570
|
+
next_idx < len(messages_list)
|
|
571
|
+
and isinstance(messages_list[next_idx], dict)
|
|
572
|
+
and messages_list[next_idx].get("role") == "user"
|
|
573
|
+
):
|
|
574
|
+
user_msg = messages_list[next_idx]
|
|
575
|
+
else:
|
|
576
|
+
# 插入合成 user 消息
|
|
577
|
+
user_msg: dict[str, Any] = {"role": "user", "content": []}
|
|
578
|
+
messages_list.insert(next_idx, user_msg)
|
|
579
|
+
|
|
580
|
+
# ── D. 确保 user_msg.content 是 list ─────────────────────
|
|
581
|
+
user_content = user_msg.get("content")
|
|
582
|
+
if isinstance(user_content, str):
|
|
583
|
+
user_msg["content"] = [{"type": "text", "text": user_content}]
|
|
584
|
+
elif not isinstance(user_content, list):
|
|
585
|
+
user_msg["content"] = []
|
|
586
|
+
|
|
587
|
+
# ── E. 收集 user 消息中已有的 tool_result IDs ─────────────
|
|
588
|
+
existing_result_ids: set[str] = {
|
|
589
|
+
b["tool_use_id"]
|
|
590
|
+
for b in user_msg["content"]
|
|
591
|
+
if isinstance(b, dict)
|
|
592
|
+
and b.get("type") == "tool_result"
|
|
593
|
+
and b.get("tool_use_id")
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
# ── F. 为每个 tool_use_id 确保 tool_result 存在 ──────────
|
|
597
|
+
for uid in tool_use_ids:
|
|
598
|
+
if uid in existing_result_ids:
|
|
599
|
+
continue # 已有匹配的 tool_result
|
|
600
|
+
|
|
601
|
+
if uid in extracted_tool_results:
|
|
602
|
+
# 从 assistant 剥离的 tool_result 重定位到 user
|
|
603
|
+
user_msg["content"].append(extracted_tool_results[uid])
|
|
604
|
+
else:
|
|
605
|
+
# 完全缺失:合成 is_error=True 占位块
|
|
606
|
+
user_msg["content"].append(
|
|
607
|
+
{
|
|
608
|
+
"type": "tool_result",
|
|
609
|
+
"tool_use_id": uid,
|
|
610
|
+
"content": "",
|
|
611
|
+
"is_error": True,
|
|
612
|
+
}
|
|
613
|
+
)
|
|
614
|
+
synthesized_ids.append(uid)
|
|
615
|
+
|
|
616
|
+
i += 1
|
|
617
|
+
|
|
618
|
+
# ── 构建 adaptation 标签与日志 ────────────────────────────
|
|
619
|
+
if relocated_count:
|
|
620
|
+
adaptations.append("misplaced_tool_result_relocated")
|
|
621
|
+
if synthesized_ids:
|
|
622
|
+
adaptations.append("orphaned_tool_use_repaired")
|
|
623
|
+
logger.warning(
|
|
624
|
+
"Vendor degradation adaptation: synthesized %d tool_result block(s) "
|
|
625
|
+
"for orphaned tool_use to satisfy Anthropic pairing constraint. "
|
|
626
|
+
"Affected tool_use_ids: %s",
|
|
627
|
+
len(synthesized_ids),
|
|
628
|
+
", ".join(synthesized_ids),
|
|
629
|
+
)
|
|
630
|
+
|
|
631
|
+
return adaptations
|
|
632
|
+
|
|
633
|
+
|
|
490
634
|
# ── Phase 2: Thinking block 剥离 ──────────────────────────────
|
|
491
635
|
|
|
492
636
|
# 需要从 assistant messages 中剥离的 thinking block 类型
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: coding-proxy
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4a4
|
|
4
4
|
Summary: A High-Availability, Transparent, and Smart Multi-Vendor Proxy for Claude Code. Support Claude Plans, GitHub Copilot, Google Antigravity, ZAI/GLM, MiniMax, Qwen, Xiaomi, Kimi, Doubao...
|
|
5
5
|
Project-URL: Source Code, https://github.com/ThreeFish-AI/coding-proxy
|
|
6
6
|
Project-URL: User Guide, https://github.com/ThreeFish-AI/coding-proxy/blob/master/docs/user-guide.md
|
|
@@ -145,7 +145,7 @@ graph RL
|
|
|
145
145
|
|
|
146
146
|
subgraph CodingProxy["⚡ coding-proxy"]
|
|
147
147
|
direction RL
|
|
148
|
-
|
|
148
|
+
|
|
149
149
|
Router["RequestRouter<br/><code>routing/router.py</code>"]:::router
|
|
150
150
|
|
|
151
151
|
Router -->NTier
|
|
@@ -178,7 +178,7 @@ graph RL
|
|
|
178
178
|
Tier2 -. "🆘 Safety Net Downgrade" .-> TierN
|
|
179
179
|
end
|
|
180
180
|
|
|
181
|
-
end
|
|
181
|
+
end
|
|
182
182
|
|
|
183
183
|
Client -->|"POST /v1/messages"| CodingProxy
|
|
184
184
|
```
|
|
@@ -17,7 +17,7 @@ coding/proxy/compat/canonical.py,sha256=-zcuEwZ402xeH3C545RmuYRkT2HDuvFloyFydDv8
|
|
|
17
17
|
coding/proxy/compat/session_store.py,sha256=B9IFjjQJnHMg1244m__jG9gnqGWi26-JyEtwopEri6Q,5244
|
|
18
18
|
coding/proxy/config/__init__.py,sha256=hzgU5noJGecjj13UY38cC_p6jpWO3GO7okSW-A2XkJ0,127
|
|
19
19
|
coding/proxy/config/auth_schema.py,sha256=LYrJQU_fgW-6AoQdjXt4-MgPJjXjv9HrghlCcZwotnA,696
|
|
20
|
-
coding/proxy/config/config.default.yaml,sha256=
|
|
20
|
+
coding/proxy/config/config.default.yaml,sha256=Q7pfvyVfm63sBGsw5OWyBHILi4vp_ANcRQAfU_q-T9g,16579
|
|
21
21
|
coding/proxy/config/loader.py,sha256=1J_RBJgjuC8RwB2mwewLMS7vy9WEhUqttZG2igeDm-w,8984
|
|
22
22
|
coding/proxy/config/resiliency.py,sha256=GnzY-LoyfFqXFM1l6xEru418v-cKlv97-HM0noGPdks,1308
|
|
23
23
|
coding/proxy/config/routing.py,sha256=aJMhfCRyoZIvemM3Q2_KV9rpWxUsFnoY0ZdCr4TwSs8,11765
|
|
@@ -44,7 +44,7 @@ coding/proxy/model/vendor.py,sha256=Yg4AYN7tgjHaGWRGEccCs3AdO8vBc-KxIelnqRowpyo,
|
|
|
44
44
|
coding/proxy/routing/__init__.py,sha256=2Tpc6MQ5Oy_w-YlEWQVDSgcSgiHp3OwKOABIjj5kfHA,1595
|
|
45
45
|
coding/proxy/routing/circuit_breaker.py,sha256=hOyoY_RWB5dTVbipyuiWfAelnva3cZRLbXrSmSn8KTs,8096
|
|
46
46
|
coding/proxy/routing/error_classifier.py,sha256=oDxp69sCb-pdfe1hWce29A9tsN3jAbhqfl2fRECBtCo,3747
|
|
47
|
-
coding/proxy/routing/executor.py,sha256=
|
|
47
|
+
coding/proxy/routing/executor.py,sha256=PNOv9fK5ZGGNx3wVLWmPBtM48R88Iu3xLZ2oXgDlx6M,35533
|
|
48
48
|
coding/proxy/routing/model_mapper.py,sha256=b72CGRdusLAwoq7p8-8TWAv9-Zv8BozssiZC8XnNTx4,3574
|
|
49
49
|
coding/proxy/routing/quota_guard.py,sha256=uoQSr2siv6aIBVylvXG_PsfdpY_i4QJxc-WHz4MGDa4,7791
|
|
50
50
|
coding/proxy/routing/rate_limit.py,sha256=i2cCqtbmXrP6wjRUTWXLP4DdYwVj0C4o59QdYGkPQj0,5122
|
|
@@ -56,9 +56,9 @@ coding/proxy/routing/usage_parser.py,sha256=j4G0ArFduQ2D4Yeuad94DVlwdc-JvSh7SJLV
|
|
|
56
56
|
coding/proxy/routing/usage_recorder.py,sha256=pObOrX2yIITTiyojl1fJcqO0yWWpbP4KqsJvFdmlt04,6273
|
|
57
57
|
coding/proxy/server/__init__.py,sha256=KeH7mEu36v9v27m3VgeSxSeFz9sLTJrxS_EVATJ7Vks,20
|
|
58
58
|
coding/proxy/server/app.py,sha256=kRGgb772dZu8200LPnn7Nt0IU5oagcbBf_Vc5ynxxzE,5599
|
|
59
|
-
coding/proxy/server/dashboard.py,sha256=
|
|
59
|
+
coding/proxy/server/dashboard.py,sha256=sCGuqBFqCrwB6zoyYXDdIfadZphHHhKJ9A9GjiHSHQU,55210
|
|
60
60
|
coding/proxy/server/factory.py,sha256=w8VFvxoogw9K9sO8MlT6bIP7xM7mR6sCohrZle9y_Gg,9985
|
|
61
|
-
coding/proxy/server/request_normalizer.py,sha256=
|
|
61
|
+
coding/proxy/server/request_normalizer.py,sha256=QqevMqHFFwkggo7MEVAX4YmOFNtnwuH4SkpBO11YiZs,27778
|
|
62
62
|
coding/proxy/server/responses.py,sha256=i0ugnLRNOdRYGHEWxkwsxR35ChmdMQsSaD8AjRluTn4,2167
|
|
63
63
|
coding/proxy/server/routes.py,sha256=_N_-GPEgK5YEmlkuuM0dvB-nOyL_OMXI12cOiQWAGPY,13845
|
|
64
64
|
coding/proxy/streaming/__init__.py,sha256=0al5TC-zJt8Bz0CibTmd8WPza-Cs-qcuZWvT2fKPqHI,23
|
|
@@ -80,8 +80,8 @@ coding/proxy/vendors/native_anthropic.py,sha256=SxtM71PDci0gqLqiwCrFnT410SnSoD7F
|
|
|
80
80
|
coding/proxy/vendors/token_manager.py,sha256=s10t4Com0jNnKGkPyJ_HpG5SjHrCEJvfArEOAaPKA_k,4189
|
|
81
81
|
coding/proxy/vendors/xiaomi.py,sha256=E-GcmJBZh7GOtDFonxZmlf0hKRhrlrXzL0IxHFRYcRo,860
|
|
82
82
|
coding/proxy/vendors/zhipu.py,sha256=3j_rqNFu1CX-B5ugtrL6Y1OeWSy9yiqsVa9Bi1ssaAA,1062
|
|
83
|
-
coding_proxy-0.2.
|
|
84
|
-
coding_proxy-0.2.
|
|
85
|
-
coding_proxy-0.2.
|
|
86
|
-
coding_proxy-0.2.
|
|
87
|
-
coding_proxy-0.2.
|
|
83
|
+
coding_proxy-0.2.4a4.dist-info/METADATA,sha256=Fk2VSfWJkycIPJ-qy72DxJWdb2sqy0Wn6udazeKrV7o,10880
|
|
84
|
+
coding_proxy-0.2.4a4.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
85
|
+
coding_proxy-0.2.4a4.dist-info/entry_points.txt,sha256=moIVzt5ho0Wk9B47LOo2SEAbhzuDDHWi-EfM30U0XBg,54
|
|
86
|
+
coding_proxy-0.2.4a4.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
87
|
+
coding_proxy-0.2.4a4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|