feat: add code queue services and baidu netdisk

This commit is contained in:
Codex
2026-05-13 00:59:36 +00:00
parent ae462ed9ef
commit 6a04144d3f
63 changed files with 10983 additions and 1101 deletions
+8 -4
View File
@@ -18,9 +18,11 @@ Provider Gateway 是计算节点侧容器。它只主动连出到主 server 暴
## Deployment Method
当前主 server 公网 IP 是 `74.48.78.17``config.json` 中的 `network.publicHost` 必须保持为该地址;公网 frontend 入口是 `http://74.48.78.17:18081/`provider gateway 对外接入入口是 `ws://74.48.78.17:18082/ws/provider`provider ingress 健康检查是 `http://74.48.78.17:18082/health`。主 server 本机 provider 由根目录 `docker-compose.yml``provider-gateway` 服务启动,容器内使用 Docker 内网地址 `ws://backend-core:8081/ws/provider` 自接入;外部计算节点部署 provider-gateway 时必须改用公网 provider ingress URL,并复用 `config.json` / `.state/docker-compose.env` 中的 provider token、心跳间隔和重连参数
当前主 server 公网 IP 是 `74.48.78.17``config.json` 中的 `network.publicHost` 必须保持为该地址;公网 frontend 入口是 `http://74.48.78.17:18081/`provider gateway 对外接入入口是 `ws://74.48.78.17:18082/ws/provider`provider ingress 健康检查是 `http://74.48.78.17:18082/health`。主 server 本机 provider 由根目录 `docker-compose.yml``provider-gateway` 服务启动,容器内使用 Docker 内网地址 `ws://backend-core:8081/ws/provider` 自接入;外部计算节点部署 provider-gateway 时必须改用公网 provider ingress URL。
计算节点部署 provider-gateway 的最小方法是:准备可运行 `unidesk_provider-gateway` 镜像的 Docker 环境,为节点分配唯一 `PROVIDER_ID` 与可读 `PROVIDER_NAME`,设置 `PROVIDER_SERVER_URL=ws://74.48.78.17:18082/ws/provider``PROVIDER_TOKEN``PROVIDER_LABELS_JSON``HEARTBEAT_INTERVAL_MS``RECONNECT_BASE_MS` `RECONNECT_MAX_MS`,并挂载 `/var/run/docker.sock:/var/run/docker.sock` 作为 Docker 状态采集、任务执行和远程升级的唯一自动化通道。为了让 `资源监控` 能看到节点级进程占用,provider-gateway 容器还必须运行在宿主 PID namespaceCompose 写法是 `pid: "host"``docker run` 写法是 `--pid host`;缺少该配置时只能看到 provider 容器命名空间内的进程,不能视为完整节点资源监控。所有长期接入节点都必须配置 `PROVIDER_UPGRADE_*` 环境变量,把节点上的 UniDesk 仓库只读挂载到 `PROVIDER_UPGRADE_WORKSPACE_PATH`,并确保升级命令只重建 `provider-gateway` service,不影响 database、backend-core、frontend。provider-gateway 容器必须使用 Docker restart policy `always`Compose 写法是 `restart: always``docker run` 写法是 `--restart always`。provider-gateway 部署必须同时交付 Host SSH / WSL SSH 透传维护桥;WSL 节点应设置 `HOST_SSH_HOST=host.docker.internal``HOST_SSH_PORT=22``HOST_SSH_USER=<WSL 用户>``HOST_SSH_KEY=/run/host-ssh/id_ed25519``HOST_REMOTE_CWD=/home/<WSL 用户>`,并把只含维护私钥的宿主目录只读挂载到 `/run/host-ssh`
新增计算节点推荐使用两项配置的简化挂载流程:在目标节点的 UniDesk 仓库根目录运行 `bun scripts/cli.ts provider attach <PROVIDER_ID> --master-server http://74.48.78.17/ --up`;如果主 server 仍是默认地址,`--master-server` 可省略。该命令生成 `.state/provider-<ID>.env``provider-<ID>.yml`env 文件默认只保留 `UNIDESK_MASTER_SERVER` `PROVIDER_ID` 两项,Compose 固定 `restart: always``pid: "host"`、Docker socket、只读 `/workspace` 仓库挂载、日志目录和 `/run/host-ssh` 维护私钥目录。provider-gateway 会从 `UNIDESK_MASTER_SERVER=http://74.48.78.17/` 自动派生 `ws://74.48.78.17:18082/ws/provider`,并自动补齐 `PROVIDER_NAME`、默认 labels、心跳/重连参数、`DOCKER_SOCKET_PATH``MONITOR_DISK_PATH``PROVIDER_UPGRADE_*`、runner image 和日志路径;远程升级所需的宿主仓库路径会优先通过 Docker inspect 反查当前容器 `/workspace` 挂载源,避免手写 `/home/ubuntu/unidesk`Compose project、env file 或 runner image 时出错。显式环境变量仍可覆盖这些默认值;如果主 server 的 provider token 已改成非默认值,挂载时只额外传一次 `--provider-token <token>` 或在 env 文件中加入 `PROVIDER_TOKEN`
手写 Compose 仍必须满足同一部署约束:挂载 `/var/run/docker.sock:/var/run/docker.sock` 作为 Docker 状态采集、任务执行和远程升级的唯一自动化通道,并让 provider-gateway 容器运行在宿主 PID namespaceCompose 写法是 `pid: "host"``docker run` 写法是 `--pid host`。缺少该配置时只能看到 provider 容器命名空间内的进程,不能视为完整节点资源监控。provider-gateway 容器必须使用 Docker restart policy `always``unless-stopped`、空 restart policy、手动 `docker stop` 后期待 Docker daemon 重启自动拉起,都不符合长期接入要求。长期接入节点必须保留只读 `/workspace` 仓库挂载,使 `provider.upgrade mode=schedule` 能构建候选 gateway 且只重建 `provider-gateway` service,不影响 database、backend-core、frontend 或业务用户服务。provider-gateway 部署必须同时交付 Host SSH / WSL SSH 透传维护桥;WSL 节点默认把私钥目录挂载到 `/run/host-ssh` 后,gateway 会在发现 `/run/host-ssh/id_ed25519` 时自动使用 `host.docker.internal:22`、从仓库路径推断 WSL 用户与默认工作目录,必要时仍可用 `HOST_SSH_HOST``HOST_SSH_PORT``HOST_SSH_USER``HOST_SSH_KEY``HOST_REMOTE_CWD` 显式覆盖。
## Mandatory SSH Passthrough Bundle
@@ -36,12 +38,14 @@ WSL 计算节点和普通外部计算节点使用同一套 provider ingress 协
WSL 节点应优先使用 WSL 内部原生 Docker Engine 和 `/var/run/docker.sock`,让资源采样、Docker 状态和任务执行都反映 WSL 计算环境本身,而不是 Windows 或 Docker Desktop 的代理上下文。如果当前 Docker CLI 实际连接 Docker Desktop daemon,也可以先作为可用计算节点接入,但必须在 `PROVIDER_LABELS_JSON` 中显式标注 `dockerContext=docker-desktop` 或等价标签,避免在 frontend 中把 Docker Desktop 资源误判为 WSL 原生资源。UniDesk 仓库建议放在 WSL 原生文件系统,例如 `/home/ubuntu/unidesk`,再按需从 Windows 工作区同步源码;长期运行和升级挂载应使用 WSL 原生路径只读挂到容器内 `/workspace`,减少 `/mnt/c` 权限、性能和路径转换问题。
WSL provider 的最小环境文件应放在节点本地私有路径,例如 `/home/ubuntu/unidesk/.state/provider-<ID>.env`,并由 `docker run --env-file` 读取。`PROVIDER_LABELS_JSON` 在 Docker env-file 中可以写成单行 JSON;如果临时用 shell `source` 方式调试必须对整段 JSON 加引号,否则 shell 会按 `{}` 和逗号拆分导致 JSON 解析失败。WSL 节点建议至少包含这些 labels:`host``role=wsl-provider``wsl=true``distro``docker=true`;运行时 provider-gateway 会自动追加 `runtime``dockerSocketPresent` `gatewayUptimeSeconds``.state/provider-<ID>.env``logs/provider-<ID>/` 和容器日志属于节点本地运行态,必须保持在 `.gitignore` 覆盖范围内,不能提交 provider token、登录态或运行日志。
WSL provider 的最小环境文件应放在节点本地私有路径,例如 `/home/ubuntu/unidesk/.state/provider-<ID>.env`,并由生成的 `provider-<ID>.yml` `docker run --env-file` 读取。新挂载默认只写 `UNIDESK_MASTER_SERVER``PROVIDER_ID`;如果需要覆盖 labels`PROVIDER_LABELS_JSON` 在 Docker env-file 中可以写成单行 JSON临时用 shell `source` 调试必须对整段 JSON 加引号,否则 shell 会按 `{}` 和逗号拆分导致 JSON 解析失败。不写 labels 时 provider-gateway 会根据 Provider ID、Docker、WSL 内核和 `/etc/os-release` 自动生成 `host``role``docker``wsl``distro``attachMode=simple`,并在运行时追加 `runtime``dockerSocketPresent`、gateway 版本`gatewayUptimeSeconds``.state/provider-<ID>.env``provider-<ID>.yml``logs/provider-<ID>/` 和容器日志属于节点本地运行态,必须保持在 `.gitignore` 覆盖范围内,不能提交 provider token、登录态或运行日志。
长期运行推荐用 systemd 管理 provider-gateway 容器,而不是只在交互 shell 中运行 Bun 进程。systemd unit 的稳定形态是:`ExecStartPre=-docker rm -f unidesk-provider-gateway-<ID>` 清理同名旧容器,`ExecStart=docker run --restart always --pid host --name unidesk-provider-gateway-<ID> --env-file ... -v /var/run/docker.sock:/var/run/docker.sock -v /home/ubuntu/unidesk:/workspace:ro -v /home/ubuntu/unidesk/logs/provider-<ID>:/var/log/unidesk -v <ssh-key-dir>:/run/host-ssh:ro unidesk_provider-gateway:<id>``ExecStop=docker stop unidesk-provider-gateway-<ID>`,并设置 `Restart=always`。临时部署也必须使用 `docker run -d --restart always --pid host`,并保证容器名、env 文件、日志目录、SSH 私钥只读挂载和镜像 tag 都带上节点 ID,便于 frontend、Docker 状态、SSH 透传、进程资源表和本地排障互相对应。`provider.upgrade` 是长期接入节点的必备能力,provider-gateway 不提供 `PROVIDER_UPGRADE_ENABLED` 或等价禁用开关;如果节点缺少升级环境变量或 SSH 透传环境变量,必须修正节点部署,而不是在服务端接受只能预检、不能升级或不能维护透传的半成品状态。
WSL 本身会在没有前台进程时被 Windows 回收;如果该节点要作为长期在线算力,必须通过 Windows 启动项、计划任务或后台 `wsl.exe -d <distro> -u root -- bash -lc "systemctl start docker unidesk-provider-gateway-<ID>.service; exec sleep infinity"` 这类 keepalive 进程保持发行版运行。仅启用 WSL 内 systemd service 不等价于 Windows 层面的常驻守护。
Docker daemon 重启后的恢复验收必须看两个层级。第一层是 Docker 自身:`docker inspect --format '{{.HostConfig.RestartPolicy.Name}} {{.HostConfig.PidMode}} {{.State.Status}}' unidesk-provider-gateway-<ID>` 必须返回 `always host running`D601/D518 这类 Docker Desktop daemon 上还要记录 `docker info --format '{{.Name}} {{.LiveRestoreEnabled}}'`,当前 `LiveRestore=false` 意味着 daemon 重启会停止容器,恢复完全依赖 restart policy,因此不能把容器曾经是 running 当作已具备重启恢复能力。第二层是宿主/WSL 常驻:节点应有 systemd、Windows 计划任务、Docker Desktop 自启动或等价 keepalive 证明 Docker daemon 会随机器/WSL 启动;如果 `systemctl list-unit-files '*unidesk*'` 为空,必须在验收记录中明确该节点暂时只依赖 Docker Desktop daemon 自身,不能声称有 WSL 内 systemd watchdog。provider-gateway 新版本会在启动与 heartbeat 中自检当前容器 restart policy,发现不是 `always` 时通过 Docker socket 尝试 `docker update --restart always <self>` 并在 labels 中上报 `providerGatewayRestartPolicyOk``providerGatewayPidModeOk``providerGatewayRuntimeGuardOk`;这只是最后一道自愈,不能替代 Compose/systemd 的正确配置。
## WSL Network And Proxy Bootstrap
WSL 节点出网异常时,先把代理设置固化到目标 WSL 用户的 `~/.bashrc`,而不是只在当前 shell 临时 `export`。长期可复用的写法是在每次交互 shell 启动时从 `/etc/resolv.conf` 读取 Windows 宿主在 WSL NAT 中的 nameserver IP,再导出 `http_proxy``https_proxy``HTTP_PROXY``HTTPS_PROXY``all_proxy``ALL_PROXY` 指向 `http://<windows-host-ip>:7890` / `socks5://<windows-host-ip>:7890`,并保留 `no_proxy=localhost,127.0.0.1,::1,host.docker.internal`。不要把某次启动看到的宿主 IP 当成永远不变的常量;动态读取可以避免 WSL 网络重建后代理失效。
@@ -80,7 +84,7 @@ provider ingress 是唯一允许公网暴露的 provider 连接接口,当前
## User Service HTTP Proxy
`microservice.http` 是 provider-gateway 给 UniDesk 用户服务使用的私有后端访问能力。backend-core 通过真实 WebSocket dispatch 下发目标 service id、节点本机 `targetBaseUrl`、path、query、method、request body、timeout 和可选 JSON 数组裁剪参数;provider-gateway 支持 `GET``HEAD``POST``PUT``PATCH``DELETE`,但最终允许方法必须由每个用户服务的 `backend.allowedMethods` 显式配置。provider-gateway 只允许访问 `http://127.0.0.1``http://localhost``http://host.docker.internal` 这些节点本地地址;主 server 内置 Todo Note 与 Codex Queue 后端可分别使用 Compose 服务名 `http://todo-note:4211``http://codex-queue:4222`。该能力不打开 provider-gateway 入站端口,也不替代业务仓库自身 Dockerfile/docker-compose。
`microservice.http` 是 provider-gateway 给 UniDesk 用户服务使用的私有后端访问能力。backend-core 通过真实 WebSocket dispatch 下发目标 service id、节点本机 `targetBaseUrl`、path、query、method、request body、timeout 和可选 JSON 数组裁剪参数;provider-gateway 支持 `GET``HEAD``POST``PUT``PATCH``DELETE`,但最终允许方法必须由每个用户服务的 `backend.allowedMethods` 显式配置。provider-gateway 只允许访问 `http://127.0.0.1``http://localhost``http://host.docker.internal` 这些节点本地地址;主 server 内置 Todo Note 与 Code Queue 后端可分别使用 Compose 服务名 `http://todo-note:4211``http://code-queue:4222`。该能力不打开 provider-gateway 入站端口,也不替代业务仓库自身 Dockerfile/docker-compose。
超大 JSON 响应可以使用 `jsonArrayLimits` 在 provider-gateway 返回前裁剪指定数组,并在响应体中写入 `_unidesk.arrayLimits` 元数据,便于 UniDesk frontend 预览列表而不展示裸 JSON。长期应优先推动业务后端提供分页 API;裁剪只是 UniDesk 集成层的展示保护。