fix(llm-tui): fix card layout overlap, handle HTTP 503 loading state, and auto-switch to status tab
This commit is contained in:
parent
ca74d9f321
commit
d3b0f9ba7a
1 changed files with 29 additions and 3 deletions
32
bin/llm-tui
32
bin/llm-tui
|
|
@ -220,6 +220,15 @@ def check_port_status(port: int) -> tuple[bool, str]:
|
|||
data = json.loads(response.read().decode())
|
||||
status = data.get("status", "unknown")
|
||||
return True, f"Online ({status})"
|
||||
except urllib.error.HTTPError as e:
|
||||
if e.code == 503:
|
||||
try:
|
||||
data = json.loads(e.read().decode())
|
||||
msg = data.get("error", {}).get("message", "Loading model")
|
||||
return True, f"Loading ({msg})"
|
||||
except Exception:
|
||||
return True, "Loading model..."
|
||||
return False, f"HTTP Error {e.code}"
|
||||
except Exception:
|
||||
return False, "Offline"
|
||||
|
||||
|
|
@ -246,6 +255,7 @@ class LLMConfigApp(App):
|
|||
border: solid #3b4252;
|
||||
padding: 1 2;
|
||||
margin-bottom: 1;
|
||||
height: auto;
|
||||
}
|
||||
.title {
|
||||
color: #88c0d0;
|
||||
|
|
@ -302,18 +312,21 @@ class LLMConfigApp(App):
|
|||
border-left: thick #88c0d0;
|
||||
padding: 1 2;
|
||||
margin-bottom: 1;
|
||||
height: auto;
|
||||
}
|
||||
#vram-meter {
|
||||
background: #232834;
|
||||
border: solid #4c566a;
|
||||
padding: 1;
|
||||
margin-top: 1;
|
||||
height: auto;
|
||||
}
|
||||
#status-card {
|
||||
background: #1e222b;
|
||||
border: solid #4c566a;
|
||||
padding: 1;
|
||||
margin-bottom: 1;
|
||||
height: auto;
|
||||
}
|
||||
Log {
|
||||
background: #0f1117;
|
||||
|
|
@ -339,6 +352,8 @@ class LLMConfigApp(App):
|
|||
_sync_lock: bool = False
|
||||
_last_selected_model: str = ""
|
||||
_last_selected_mmproj: str = ""
|
||||
_last_log_size: int = -1
|
||||
_last_log_name: str = ""
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
yield Header(show_clock=True)
|
||||
|
|
@ -672,7 +687,12 @@ class LLMConfigApp(App):
|
|||
lines = []
|
||||
for port, label in [(11434, "Planner / Solo"), (11435, "Worker 1"), (11436, "Worker 2")]:
|
||||
online, msg = check_port_status(port)
|
||||
badge = "[green]● ONLINE[/]" if online else "[yellow]○ OFFLINE[/]"
|
||||
if not online:
|
||||
badge = "[yellow]○ OFFLINE[/]"
|
||||
elif "loading" in msg.lower():
|
||||
badge = "[cyan]⏳ LOADING[/]"
|
||||
else:
|
||||
badge = "[green]● ONLINE[/]"
|
||||
lines.append(f"Port {port} ({label}): {badge} - {msg}")
|
||||
|
||||
card = self.query_one("#status-card", Static)
|
||||
|
|
@ -684,8 +704,13 @@ class LLMConfigApp(App):
|
|||
if logs:
|
||||
latest = logs[0]
|
||||
try:
|
||||
cur_size = latest.stat().st_size
|
||||
if cur_size == self._last_log_size and latest.name == self._last_log_name:
|
||||
return
|
||||
self._last_log_size = cur_size
|
||||
self._last_log_name = latest.name
|
||||
with open(latest, "r", errors="ignore") as f:
|
||||
f.seek(max(0, latest.stat().st_size - 8192))
|
||||
f.seek(max(0, cur_size - 16384))
|
||||
tail = f.read()
|
||||
log_widget.clear()
|
||||
log_widget.write(f"--- Streaming {latest.name} ---\n" + tail)
|
||||
|
|
@ -732,7 +757,8 @@ class LLMConfigApp(App):
|
|||
)
|
||||
|
||||
subprocess.Popen(cmd, env=env, cwd=str(SCRIPT_DIR), start_new_session=True)
|
||||
self.notify(f"Launching {preset} server. Check Status & Live Logs tab.", severity="information")
|
||||
self.notify(f"Launching {preset} server. Switching to Status & Logs...", severity="information")
|
||||
self.query_one(TabbedContent).active = "tab-status"
|
||||
self.action_refresh_status()
|
||||
|
||||
def action_stop(self) -> None:
|
||||
|
|
|
|||
Loading…
Reference in a new issue