mirror of
https://github.com/Alishahryar1/free-claude-code.git
synced 2026-06-02 06:13:46 +02:00
Improve admin UI setup flow
This commit is contained in:
+2
-1
@@ -995,6 +995,7 @@ def write_managed_env(updates: Mapping[str, Any]) -> dict[str, Any]:
|
||||
return validation | {"applied": False, "pending_fields": []}
|
||||
|
||||
target_values = _target_values_with_updates(updates)
|
||||
pending_fields = changed_pending_fields(updates)
|
||||
path = managed_env_path()
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
temp_path = path.with_suffix(path.suffix + ".tmp")
|
||||
@@ -1006,7 +1007,7 @@ def write_managed_env(updates: Mapping[str, Any]) -> dict[str, Any]:
|
||||
"errors": [],
|
||||
"env_preview": render_env_file(target_values, mask_secrets=True),
|
||||
"path": str(path),
|
||||
"pending_fields": changed_pending_fields(updates),
|
||||
"pending_fields": pending_fields,
|
||||
}
|
||||
|
||||
|
||||
|
||||
+45
-2
@@ -2,16 +2,18 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import inspect
|
||||
import ipaddress
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from urllib.parse import urlsplit
|
||||
|
||||
import httpx
|
||||
from fastapi import APIRouter, HTTPException, Request
|
||||
from fastapi import APIRouter, BackgroundTasks, HTTPException, Request
|
||||
from fastapi.responses import FileResponse
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from config.settings import Settings
|
||||
from config.settings import get_settings as get_cached_settings
|
||||
from providers.registry import ProviderRegistry
|
||||
|
||||
@@ -22,6 +24,7 @@ from .admin_config import (
|
||||
validate_updates,
|
||||
write_managed_env,
|
||||
)
|
||||
from .admin_urls import local_admin_url
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@@ -104,13 +107,25 @@ async def validate_admin_config(payload: AdminConfigPayload, request: Request):
|
||||
|
||||
|
||||
@router.post("/admin/api/config/apply")
|
||||
async def apply_admin_config(payload: AdminConfigPayload, request: Request):
|
||||
async def apply_admin_config(
|
||||
payload: AdminConfigPayload,
|
||||
request: Request,
|
||||
background_tasks: BackgroundTasks,
|
||||
):
|
||||
require_loopback_admin(request)
|
||||
result = write_managed_env(_filtered_values(payload.values))
|
||||
if not result["applied"]:
|
||||
return result
|
||||
|
||||
get_cached_settings.cache_clear()
|
||||
restart = _restart_metadata(result["pending_fields"], request)
|
||||
result["restart"] = restart
|
||||
if restart["required"] and restart["automatic"]:
|
||||
callback = request.app.state.admin_restart_callback
|
||||
background_tasks.add_task(_invoke_admin_restart_callback, callback)
|
||||
request.app.state.admin_pending_fields = []
|
||||
return result
|
||||
|
||||
old_registry = getattr(request.app.state, "provider_registry", None)
|
||||
if isinstance(old_registry, ProviderRegistry):
|
||||
await old_registry.cleanup()
|
||||
@@ -200,6 +215,34 @@ def _filtered_values(values: dict[str, Any]) -> dict[str, Any]:
|
||||
return {key: value for key, value in values.items() if key in FIELD_BY_KEY}
|
||||
|
||||
|
||||
async def _invoke_admin_restart_callback(callback: Any) -> None:
|
||||
result = callback()
|
||||
if inspect.isawaitable(result):
|
||||
await result
|
||||
|
||||
|
||||
def _restart_metadata(fields: list[str], request: Request) -> dict[str, Any]:
|
||||
callback = getattr(request.app.state, "admin_restart_callback", None)
|
||||
automatic = bool(fields and callable(callback))
|
||||
return {
|
||||
"required": bool(fields),
|
||||
"automatic": automatic,
|
||||
"admin_url": _next_admin_url() if automatic else None,
|
||||
"fields": fields,
|
||||
}
|
||||
|
||||
|
||||
def _next_admin_url() -> str:
|
||||
fields = {
|
||||
field["key"]: field["value"] for field in load_config_response()["fields"]
|
||||
}
|
||||
settings = Settings.model_construct(
|
||||
host=fields.get("HOST") or "0.0.0.0",
|
||||
port=int(fields.get("PORT") or 8082),
|
||||
)
|
||||
return local_admin_url(settings)
|
||||
|
||||
|
||||
def _local_provider_url(provider_id: str, values: dict[str, str]) -> str:
|
||||
if provider_id == "lmstudio":
|
||||
return values.get("LM_STUDIO_BASE_URL", "")
|
||||
|
||||
@@ -339,11 +339,20 @@ async function apply() {
|
||||
showValidationResult(result);
|
||||
return;
|
||||
}
|
||||
const pending = result.pending_fields || [];
|
||||
const restart = result.restart || {};
|
||||
if (restart.required && restart.automatic) {
|
||||
showMessage("Applied. Restarting server...", "ok");
|
||||
byId("applyButton").disabled = true;
|
||||
setTimeout(() => {
|
||||
window.location.href = restart.admin_url || "/admin";
|
||||
}, 1600);
|
||||
return;
|
||||
}
|
||||
const pending = restart.required ? restart.fields || [] : result.pending_fields || [];
|
||||
await load();
|
||||
showMessage(
|
||||
pending.length
|
||||
? `Applied. Pending manual runtime action: ${pending.join(", ")}`
|
||||
? `Applied. Restart fcc-server to use: ${pending.join(", ")}`
|
||||
: "Applied",
|
||||
"ok",
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user