Add hub AI config tab with sync to instances and deploy secret bootstrap.

Wire bootstrap_deploy_secrets into setup_env.sh (one-time HUB_BRIDGE_TOKEN, FLASK_SECRET_KEY, HUB_SESSION_SECRET). Remove AI section from instance env UI; hub saves OPENAI settings to all four .env files. SSO unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-08 22:50:58 +08:00
parent 886f7740f2
commit 823aeda42a
17 changed files with 653 additions and 54 deletions
+39
View File
@@ -1692,6 +1692,45 @@ def api_admin_restart():
return result
class HubAiEnvBody(BaseModel):
values: dict[str, str] = Field(default_factory=dict)
restart: bool = True
@app.get("/api/settings/ai-env")
def api_get_ai_env(request: Request):
_require_hub_logged_in(request)
from hub_env_lib import get_hub_ai_env_payload
return {"ok": True, **get_hub_ai_env_payload()}
@app.post("/api/settings/ai-env")
def api_save_ai_env(request: Request, body: HubAiEnvBody):
_require_hub_logged_in(request)
from hub_env_lib import get_hub_ai_env_payload, restart_all_pm2, save_hub_ai_env
result = save_hub_ai_env(body.values or {})
if not result.get("ok"):
raise HTTPException(status_code=400, detail="; ".join(result.get("errors") or ["保存失败"]))
restart_result = None
if body.restart and result.get("restart_required"):
restart_result = restart_all_pm2()
if not restart_result.get("ok"):
raise HTTPException(
status_code=500,
detail="保存成功但 PM2 重启失败,请手动 restart",
)
payload = get_hub_ai_env_payload()
return {
"ok": True,
"changed": result.get("changed") or {},
"restart_required": bool(result.get("restart_required")),
"restart": restart_result,
"sync_status": payload.get("sync_status"),
}
async def _fetch_agent_status(client: httpx.AsyncClient, ex: dict) -> dict:
url = f"{ex['agent_url'].rstrip('/')}/status"
try: