mirror of
https://gitcode.com/JianFeeeee/ModelRouter.git
synced 2026-11-07 09:47:23 +00:00
G-Star 合规要求下,把"模拟官方客户端、复刻私有协议、自动领取平台额度"这一类 能力整体移出仓库。这些实现依赖各平台未公开的端点、签名算法与官方 client id, 属于绕过客户端校验获取额度,风险高于普通协议适配。 移除(93 个文件): - 适配器:opencodezen(伪装 UA 取免费池)、trae、buddy、kimicode - 插件:channels.lua(12 个平台登录/领额度/签到)、quota.lua(厂商额度探针) - 随之删除的 78 个渠道/额度专用测试与 3 份渠道文档 同时修掉的既有问题: - **硬编码第三方 OAuth client_secret**(Google Cloud Code 的 GOCSPX-…,两处) 随 channels.lua 一起消失。 - `deploy.sh` 的 `sync_plugins` 整段删除:它仍按"内置插件是发行物"的旧前提 把插件复制/覆盖进 plugin_dir,与"插件属运维资产、网关不安装不覆盖"的契约 冲突。现在部署脚本只同步适配器与二进制/配置。 - 适配器清单去掉已移除项;e2e 配置改用显式 `auto:` 链(`models.priority` 早已 移除,该测试此前已失效)。 保留(公开协议):openai / anthropic / gemini / deepseek / github / groq / mistral / ollama / qwen38 / sensenova = 10 个适配器;插件示例 billing / usage。 验证:go build -tags luajit ./... OK;internal/lua 21.4s、provider、core 51s、 gateway 122.8s、e2e 9.0s 全绿。
74 lines
2.8 KiB
Bash
Executable File
74 lines
2.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# Upload release assets to a GitCode release.
|
||
#
|
||
# The endpoint shapes are asymmetric and both differ from the "obvious" guess:
|
||
#
|
||
# GET /releases/tags/{tag} → read a release
|
||
# GET /releases/{tag}/upload_url → get a presigned PUT (NO "tags/")
|
||
# PUT {presigned url} → upload, REPLAYING the headers verbatim
|
||
#
|
||
# Two mistakes cost real time on v1.9.5 before this script existed:
|
||
#
|
||
# 1. POSTing straight to /releases/{tag}/assets returns 404 — that endpoint
|
||
# does not exist. It reads as "authentication failed" if you only check
|
||
# the status code.
|
||
# 2. PUTting without the headers fails with an opaque storage error, not a
|
||
# permission one, so it looks like a size limit or a corrupt file.
|
||
#
|
||
# The x-obs-* headers are part of the signature: dropping any one of them turns
|
||
# the request into an unsigned one.
|
||
set -uo pipefail
|
||
|
||
TOKEN="$(tr -d '\n\r' < /tmp/gc_token)"
|
||
REPO="HeNanMU-EEA/ModelRouter"
|
||
TAG="${1:?usage: upload-release.sh <tag> <file>...}"
|
||
shift
|
||
|
||
# 仓库托管在 AtomGit(与 gitcode 同一后端)。API 基址可覆盖,便于换托管或
|
||
# 用私有部署;默认值保持合并前的 v5 路径即可工作。
|
||
API="${UPLOAD_API_BASE:-https://atomgit.com/api/v5}/repos/${REPO}"
|
||
|
||
for f in "$@"; do
|
||
name="$(basename "$f")"
|
||
size="$(stat -c%s "$f")"
|
||
printf ' %-46s %10s bytes ' "$name" "$size"
|
||
|
||
# 1) presigned upload location. The file name must be URL-encoded; the v1.9.4
|
||
# assets show "~" surviving in a stored name, so encoding is per-component.
|
||
enc="$(python3 -c 'import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))' "$name")"
|
||
resp="$(curl -sS -m 60 -H "Authorization: Bearer ${TOKEN}" \
|
||
"${API}/releases/${TAG}/upload_url?file_name=${enc}" 2>&1)"
|
||
url="$(printf '%s' "$resp" | python3 -c 'import json,sys
|
||
try:
|
||
d = json.load(sys.stdin)
|
||
print(d.get("url") or d.get("uploadUrl") or "")
|
||
except Exception:
|
||
print("")' 2>/dev/null)"
|
||
if [ -z "$url" ]; then
|
||
echo "FAIL 取得上传地址失败: ${resp:0:140}"
|
||
continue
|
||
fi
|
||
|
||
# 2) PUT with the headers replayed exactly as returned.
|
||
code="$(printf '%s' "$resp" | python3 -c 'import json,sys
|
||
try:
|
||
print(json.dumps(json.load(sys.stdin).get("headers") or {}))
|
||
except Exception:
|
||
print("{}")' 2>/dev/null | python3 -c '
|
||
import json, subprocess, sys
|
||
headers = json.load(sys.stdin)
|
||
args = ["curl", "-sS", "-o", "/dev/null", "-w", "%{http_code}", "-X", "PUT"]
|
||
for k, v in headers.items():
|
||
args += ["-H", f"{k}: {v}"]
|
||
args += ["--data-binary", "@" + sys.argv[1], sys.argv[2]]
|
||
print(subprocess.run(args, capture_output=True, text=True).stdout)
|
||
' "$f" "$url" 2>/dev/null)"
|
||
|
||
if [ "$code" = "200" ] || [ "$code" = "201" ] || [ "$code" = "204" ]; then
|
||
echo "OK HTTP=$code"
|
||
else
|
||
echo "FAIL HTTP=$code"
|
||
fi
|
||
sleep 1
|
||
done
|