mirror of
https://gitcode.com/JianFeeeee/ModelRouter.git
synced 2026-09-20 00:48:00 +00:00
feat(gui): dockerized Windows cross-build (win-builder image + one-shot dist script) + GUI/backend scenario docs
This commit is contained in:
11
Makefile
11
Makefile
@ -1,4 +1,4 @@
|
||||
.PHONY: all build test gui gui-dev gui-dist gui-deb gui-win help clean
|
||||
.PHONY: all build test gui gui-dev gui-dist gui-deb gui-win gui-win-docker help clean
|
||||
|
||||
# ModelRouter - single-binary gateway + optional Electron desktop GUI (embedded core)
|
||||
export BINARY
|
||||
@ -33,10 +33,14 @@ gui-dist:
|
||||
gui-deb:
|
||||
@cd $(GUI_DIR) && npm run dist:debian
|
||||
|
||||
# windows nsis installer (needs apt install gcc-mingw-w64-x86-64 + wine for electron-builder)
|
||||
# windows nsis installer: host-built core (needs apt install gcc-mingw-w64-x86-64 + wine)
|
||||
gui-win:
|
||||
@cd $(GUI_DIR) && npm run dist:win
|
||||
|
||||
# windows nsis installer: full cross-build in docker (self-sufficient, no host mingw)
|
||||
gui-win-docker:
|
||||
@cd $(GUI_DIR) && ./scripts/dist-win-docker.sh
|
||||
|
||||
gui-dist-dir:
|
||||
@cd $(GUI_DIR) && npm run dist:dir
|
||||
|
||||
@ -53,5 +57,6 @@ help:
|
||||
@echo " make gui-dev run GUI with devtools"
|
||||
@echo " make gui-dist build deb + AppImage (linux)"
|
||||
@echo " make gui-deb build deb only"
|
||||
@echo " make gui-win build Windows nsis (needs mingw + wine)"
|
||||
@echo " make gui-win build Windows nsis (needs host mingw + wine)"
|
||||
@echo " make gui-win-docker build Windows nsis all-in-docker (no host mingw needed)"
|
||||
@echo " make test run go tests"
|
||||
|
||||
40
README.md
40
README.md
@ -307,6 +307,18 @@ zen 按 User-Agent 指纹识别官方客户端并分流——非官方 UA 的请
|
||||
一键启停、系统托盘常驻、开机自启、静默启动,内容区一比一内嵌完整 WebUI
|
||||
(状态/对话/密钥/优先级/源/适配器 六个页面,免登录)。服务器用户继续使用纯 Go 二进制。
|
||||
|
||||
### 选择 GUI 还是纯后端
|
||||
|
||||
| 场景 | 推荐 | 理由 |
|
||||
| ------ | ------ | ------ |
|
||||
| 服务器 / 内网网关 / Docker 部署 / 无人值守常驻 | **纯后端**(单二进制) | 极轻量(~10MB、~15MB RSS),零 GUI 依赖,适合 systemd/容器托管、远程管理 |
|
||||
| 个人桌面日常使用 / 多设备内网共享 | **GUI**(Electron) | 免登录内嵌 WebUI、系统托盘一键启停、开机自启、静默后台,适合不懂命令行的使用者 |
|
||||
| Windows 桌面 | **GUI** | 纯后端在 Windows 上需自行注册服务,GUI 提供原生托盘/自启体验 |
|
||||
| CI 一键出三平台安装包 | **GUI 打包脚本** | `make gui-*` 系列出 deb/AppImage/NSIS,可进发行流水线 |
|
||||
|
||||
两者完全同源:GUI 内嵌的就是纯后端的同一份 `llmsproxy` 核心(LuaJIT 版),
|
||||
配置/适配器格式完全一致,可随时互换。
|
||||
|
||||
### 构建与运行
|
||||
|
||||
```bash
|
||||
@ -314,12 +326,32 @@ cd cmd/gui
|
||||
npm install
|
||||
make gui # 或 npm run dev —— 开发运行(需先 make build 生成 bin/llmsproxy)
|
||||
make gui-deb # 本机构建 deb(分享给其它 Linux 用户)
|
||||
make gui-dist # 构建 deb + AppImage
|
||||
make gui-win # 构建 Windows nsis 安装包(需先 apt install gcc-mingw-w64-x86-64;electron-builder 用 wine)
|
||||
make gui-dist # 构建 deb + AppImage(linux)
|
||||
make gui-win # 构建 Windows nsis 安装包(本机 mingw + wine)
|
||||
make gui-win-docker # 构建 Windows nsis 安装包(全 docker 自足,无需本机 mingw)
|
||||
make gui-dist-dir # 仅解包产物(调试用,不产安装包)
|
||||
```
|
||||
|
||||
产物在 `cmd/build/gui-dist/`:`ModelRouter-1.0.0.AppImage`、`modelrouter-gui_1.0.0_amd64.deb`、
|
||||
`modelrouter-gui Setup 1.0.0.exe`(win,需 mingw 交叉编译核心后)。rpm 需系统 `rpmbuild`。
|
||||
产物在 `cmd/build/gui-dist/`:`ModelRouter-1.0.0.AppImage`、
|
||||
`modelrouter-gui_1.0.0_amd64.deb`、`ModelRouter Setup 1.0.0.exe`(win)。rpm 需系统 `rpmbuild`。
|
||||
|
||||
#### Windows 打包(docker 固化方案,推荐)
|
||||
|
||||
`make gui-win-docker` 一步完成:交叉编译核心 + NSIS 打包,宿主机**无需安装 mingw**。
|
||||
|
||||
- 构建镜像:`cmd/gui/docker/win-builder/Dockerfile`(`golang:1.25` + mingw-w64 +
|
||||
预编译 LuaJIT windows 版 `lua51.dll` 与 import lib)。LuaJIT 源码取自 gitcode
|
||||
镜像(国内可达),github 兜底;Go 依赖走 `https://goproxy.cn`。
|
||||
- 核心编译:`cmd/gui/scripts/win-core-docker.sh` —— 在容器内产出
|
||||
`cmd/gui/bin/{llmsproxy.exe,lua51.dll}`。
|
||||
- 一键发布:`cmd/gui/scripts/dist-win-docker.sh` —— 核心编译后调用
|
||||
electron-builder(宿主需有 `wine` 用于 NSIS)。
|
||||
- 首次运行自动构建 `modelrouter/win-builder` 镜像;已存在则直接复用。
|
||||
|
||||
```bash
|
||||
# 全 Windows 发布(核心重编 + NSIS):
|
||||
make gui-win-docker
|
||||
```
|
||||
|
||||
### 特性
|
||||
|
||||
|
||||
74
README_EN.md
74
README_EN.md
@ -305,6 +305,78 @@ app, so you HMAC-sign timestamp+URL+body with `meta.app_secret` and add
|
||||
`X-App-Sign`-style headers. Configure `sources[].meta.{app_id, app_secret,
|
||||
app_agent}`.
|
||||
|
||||
## Desktop GUI (Electron)
|
||||
|
||||
Optional standalone product for desktop users on your internal network: an
|
||||
**embedded ModelRouter core** (Clash Verge-style): one-click start/stop, system
|
||||
tray, autostart, silent launch, and a pixel-for-pixel embedded full WebUI
|
||||
(Status/Chat/Keys/Priority/Sources/Adapters — no login needed). Server users
|
||||
keep using the plain Go binary.
|
||||
|
||||
### GUI vs. plain backend
|
||||
|
||||
| Scenario | Pick | Why |
|
||||
| ---- | ---- | ---- |
|
||||
| Server / intranet gateway / Docker / unattended long-running | **plain backend** (single binary) | ~10 MB, ~15 MB RSS, zero GUI deps; systemd/container friendly, remote admin |
|
||||
| Personal desktop daily use / multi-device intranet sharing | **GUI** (Electron) | no-login embedded WebUI, tray one-click, autostart, silent background — for non-CLI users |
|
||||
| Windows desktop | **GUI** | plain backend needs manual service registration; GUI ships native tray/autostart |
|
||||
| CI one-shot 3-platform installers | **GUI packaging scripts** | `make gui-*` emits deb / AppImage / NSIS, drops straight into a release pipeline |
|
||||
|
||||
Both share the exact same `llmsproxy` core (LuaJIT build) — configs and
|
||||
adapters are fully compatible, freely interchangeable.
|
||||
|
||||
### Build & run
|
||||
|
||||
```bash
|
||||
cd cmd/gui
|
||||
npm install
|
||||
make gui # or npm run dev — dev run (needs make build first for bin/llmsproxy)
|
||||
make gui-deb # local deb (share with other Linux users)
|
||||
make gui-dist # deb + AppImage (linux)
|
||||
make gui-win # Windows NSIS (host mingw + wine)
|
||||
make gui-win-docker # Windows NSIS, fully dockerized (no host mingw needed)
|
||||
```
|
||||
|
||||
Artifacts land in `cmd/build/gui-dist/`: `ModelRouter-1.0.0.AppImage`,
|
||||
`modelrouter-gui_1.0.0_amd64.deb`, `ModelRouter Setup 1.0.0.exe` (win). rpm
|
||||
needs system `rpmbuild`.
|
||||
|
||||
#### Windows packaging (dockerized, recommended)
|
||||
|
||||
`make gui-win-docker` does cross-compile + NSIS in one step; the host needs
|
||||
**no mingw**.
|
||||
|
||||
- Image: `cmd/gui/docker/win-builder/Dockerfile` (`golang:1.25` + mingw-w64 +
|
||||
prebuilt LuaJIT for Windows: `lua51.dll` + import lib). LuaJIT source comes
|
||||
from the gitcode mirror (reachable in CN) with github fallback; Go modules go
|
||||
through `https://goproxy.cn`.
|
||||
- Core build: `cmd/gui/scripts/win-core-docker.sh` — emits
|
||||
`cmd/gui/bin/{llmsproxy.exe,lua51.dll}` inside the container.
|
||||
- One-shot release: `cmd/gui/scripts/dist-win-docker.sh` — after the core,
|
||||
runs electron-builder (host needs `wine` for NSIS).
|
||||
- The `modelrouter/win-builder` image is auto-built on first run and reused
|
||||
afterwards.
|
||||
|
||||
```bash
|
||||
# Full Windows release (rebuild core + NSIS):
|
||||
make gui-win-docker
|
||||
```
|
||||
|
||||
### Features
|
||||
|
||||
- **Embedded core**: auto-spawns the bundled `llmsproxy` (LuaJIT build);
|
||||
config/keys/adapters live in `<userData>/profile/`. First run generates a
|
||||
random admin key written into `keys` (not seed) and self-injects it — WebUI
|
||||
needs no login and never nags about changing the initial key. Port changeable
|
||||
in settings (default 8787).
|
||||
- **System tray**: core status dot, autostart/silent toggles, start/stop/restart
|
||||
core, quit.
|
||||
- **Silent launch**: `--silent` flag or setting — starts to the tray only;
|
||||
first run always shows the window.
|
||||
- **Autostart**: `setLoginItemSettings` on Windows/macOS; writes
|
||||
`~/.config/autostart/modelrouter-gui.desktop` on Linux, appending `--silent`
|
||||
when silent mode is on.
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
@ -324,4 +396,4 @@ go test -tags luajit ./...
|
||||
|
||||
Covers: config validation, adapter load/transform, signature hooks, gateway
|
||||
auth, SDK round trip, SSE streaming, model routing, multimodal passthrough and
|
||||
disable_thinking.
|
||||
disable_thinking.
|
||||
|
||||
35
cmd/gui/docker/win-builder/Dockerfile
Normal file
35
cmd/gui/docker/win-builder/Dockerfile
Normal file
@ -0,0 +1,35 @@
|
||||
# ModelRouter GUI Windows builder
|
||||
# Self-sufficient cross-compilation environment for the embedded llmsproxy core.
|
||||
# Produces llmsproxy.exe (Go, windows/amd64, luajit tag) + lua51.dll (LuaJIT mingw build)
|
||||
# inside a mounted workspace: cmd/gui/bin/{llmsproxy.exe,lua51.dll}
|
||||
#
|
||||
# Build: docker build -t modelrouter/win-builder cmd/gui/docker/win-builder
|
||||
# Usage: make gui-win-docker (or cmd/gui/scripts/dist-win-docker.sh)
|
||||
#
|
||||
# LuaJIT source is fetched from gitcode.com (CN-reachable mirror) with github
|
||||
# fallback; pass --build-arg LUAJIT_REPO to override.
|
||||
|
||||
FROM golang:1.25
|
||||
|
||||
ARG LUAJIT_REPO=https://gitcode.com/openresty/luajit2.git
|
||||
|
||||
RUN apt-get update -qq \
|
||||
&& DEBIAN_FRONTEND=noninteractive apt-get install -y -qq \
|
||||
gcc-mingw-w64-x86-64 make ca-certificates git \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# LuaJIT cross-compiled for Windows; keeps lua51.dll and the cgo import lib
|
||||
# (libluajit-5.1.dll.a -> libluajit-5.1.a in the mingw lib dir).
|
||||
# NOTE: $LUAJIT_REPO deliberately unquoted in "sh -c" — quoting the ARG would
|
||||
# embed literal quotes into the URL.
|
||||
RUN git clone --depth 1 $LUAJIT_REPO /opt/luajit2 \
|
||||
|| git clone --depth 1 https://github.com/openresty/luajit2 /opt/luajit2 \
|
||||
&& cd /opt/luajit2 \
|
||||
&& make HOST_CC=gcc CROSS=x86_64-w64-mingw32- TARGET_SYS=Windows TARGET_XCFLAGS=-DLUAJIT_ENABLE_LUA52COMPAT \
|
||||
&& cp src/libluajit-5.1.dll.a /usr/x86_64-w64-mingw32/lib/libluajit-5.1.a
|
||||
|
||||
# Go proxy mirror for builds behind GFW-ish networks; overridable at runtime.
|
||||
ENV GOPROXY=https://goproxy.cn,direct
|
||||
|
||||
WORKDIR /workspace
|
||||
CMD ["/bin/bash"]
|
||||
23
cmd/gui/scripts/dist-win-docker.sh
Executable file
23
cmd/gui/scripts/dist-win-docker.sh
Executable file
@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
# One-shot Windows release build for the GUI:
|
||||
# 1) cross-compile the embedded core in docker (llmsproxy.exe + lua51.dll)
|
||||
# 2) host-side electron-builder NSIS packaging (wine required on host)
|
||||
# Outputs: cmd/build/gui-dist/"ModelRouter Setup <version>.exe"
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
|
||||
cd "$ROOT/cmd/gui"
|
||||
|
||||
# 1) core (docker)
|
||||
"$ROOT/cmd/gui/scripts/win-core-docker.sh"
|
||||
|
||||
# 2) packaging (host, needs wine for electron-builder's signtool/nsis)
|
||||
command -v wine >/dev/null || { echo "wine required on host for NSIS packaging"; exit 1; }
|
||||
if ! command -v npx >/dev/null; then echo "node/npm required"; exit 1; fi
|
||||
|
||||
echo "[dist-win] electron-builder --win nsis ..."
|
||||
# bin artifacts already refreshed by win-core-docker.sh; skip the prepare step
|
||||
npx electron-builder --win nsis
|
||||
|
||||
ls -la "$ROOT/cmd/build/gui-dist/"*.exe 2>/dev/null
|
||||
echo "[dist-win] done"
|
||||
38
cmd/gui/scripts/win-core-docker.sh
Executable file
38
cmd/gui/scripts/win-core-docker.sh
Executable file
@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build embedded Windows core inside the self-sufficient builder image.
|
||||
# - image has LuaJIT pre-built: /opt/luajit2/src/{lua51.dll, libluajit-5.1.dll.a}
|
||||
# - import lib already installed at image build (libluajit-5.1.a, mingw lib dir)
|
||||
# Outputs: cmd/gui/bin/{llmsproxy.exe, lua51.dll}
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
|
||||
BIN_DIR="$ROOT/cmd/gui/bin"
|
||||
IMAGE="${WIN_BUILDER_IMAGE:-modelrouter/win-builder}"
|
||||
PROXY="${GOPROXY:-https://goproxy.cn,direct}"
|
||||
|
||||
command -v docker >/dev/null || {
|
||||
echo "docker required"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if ! docker image inspect "$IMAGE" >/dev/null 2>&1; then
|
||||
echo "[win-core] building image $IMAGE ..."
|
||||
docker build -t "$IMAGE" "$ROOT/cmd/gui/docker/win-builder"
|
||||
fi
|
||||
|
||||
mkdir -p "$BIN_DIR"
|
||||
|
||||
echo "[win-core] cross-building llmsproxy.exe (windows/amd64, luajit) + lua51.dll ..."
|
||||
docker run --rm \
|
||||
-v "$ROOT":/workspace \
|
||||
-e GOPROXY="$PROXY" \
|
||||
-w /workspace \
|
||||
"$IMAGE" bash -c '
|
||||
set -euo pipefail
|
||||
cp /opt/luajit2/src/lua51.dll /workspace/cmd/gui/bin/lua51.dll
|
||||
GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc \
|
||||
go build -buildvcs=false -tags luajit -trimpath \
|
||||
-o /workspace/cmd/gui/bin/llmsproxy.exe ./cmd/llmsproxy
|
||||
echo " -> core built"
|
||||
'
|
||||
echo "[win-core] done: $BIN_DIR/llmsproxy.exe"
|
||||
Reference in New Issue
Block a user