#!/usr/bin/env python3 # -*- coding: utf-8 -*- """第三处修复: start.bat 把 "网关已起但有模块降级" 误报成 "没起来"。 现状: guanlan.py serve 的退出码 1 有**两种**含义 —— ① 网关 healthz 压根没起来; ② 网关起来了, 但有模块 [DOWN] (本机 Ollama 没跑 / 没拉模型时必然如此)。 start.bat 只看 errorlevel, 于是 ② 也走 "[X] Server did not start ... Not opening the browser", 用户看到的是 "服务没起", 实际网关在跑、6/7 页面都正常 —— 与原始报障里那条 "[X] Server did not start (reason above)" 同源。 修复: 退出码非 0 时先探一次 /healthz 区分两种情形; 真没起来才报 [X] 并停; 起来了但有降级则打 [!] 说明 (哪一类页面受影响), 浏览器照常打开。 保持 .bat 的 CRLF / 无 BOM 约定。 """ from __future__ import annotations import pathlib import shutil import sys ROOT = pathlib.Path(r"F:\temp\guanlan-rudong-v2_0.2.0") START = ROOT / "start.bat" OLD = ( '".venv\\Scripts\\python.exe" guanlan.py serve\n' 'if errorlevel 1 (\n' ' echo.\n' ' echo [X] Server did not start ^(reason above^). Not opening the browser -\n' ' echo a "site cannot be reached" page would look like a network problem.\n' ' echo See logs\\gateway.log\n' ' pause\n' ' exit /b 1\n' ')\n' 'start "" http://127.0.0.1:28084/\n' ) NEW = '''".venv\\Scripts\\python.exe" guanlan.py serve if errorlevel 1 ( rem serve exits 1 in two different cases: the gateway never came up, or the gateway is rem up with at least one degraded module, e.g. Ollama not running. Probe healthz to tell rem them apart, otherwise a working server gets reported as "did not start". ".venv\\Scripts\\python.exe" -c "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:28084/healthz',timeout=6).status==200 else 1)" 2>nul if errorlevel 1 ( echo. echo [X] Gateway did not come up ^(reason above^). Not opening the browser - echo a "site cannot be reached" page would look like a network problem. echo See logs\\gateway.log pause exit /b 1 ) echo. echo [!] Gateway is up, but at least one module is degraded ^(the [DOWN] lines above^). echo Usual cause: local Ollama is not running or has no models pulled, which only echo disables the Q^&A / local-review pages. Every other page works. echo Details: logs\\ for the degraded module. ) start "" http://127.0.0.1:28084/ ''' def main() -> int: raw = START.read_bytes() if raw.startswith(b"\xef\xbb\xbf"): print(" [X] start.bat 不该有 BOM") return 1 text = raw.decode("utf-8").replace("\r\n", "\n") # .bat 是 CRLF, 先归一化再匹配 if "Gateway did not come up" in text: print(" [=] start.bat 已修过, 跳过") return 0 if text.count(OLD) != 1: print(f" [X] start.bat 锚点命中 {text.count(OLD)} 次, 未改动") return 1 b = START.with_name(START.name + ".bak-healthz") if not b.exists(): shutil.copy2(START, b) print(f" 备份 start.bat -> {b.name}") out = text.replace(OLD, NEW).replace("\r\n", "\n").replace("\n", "\r\n") START.write_bytes(out.encode("utf-8")) # UTF-8 无 BOM + CRLF print(" [OK] start.bat 已修 (CRLF / 无 BOM 保持不变)") return 0 if __name__ == "__main__": sys.exit(main())