Improve model status indicators and tune timeouts
Green/red emoji circles replace Unicode symbols for at-a-glance model readiness. Increase connect timeouts (10→30s) for cold model loading, warm timeout (120→300s) for large models, and pull timeout (600→1800s) to match route-level limit. Show error toast on SSE reconnection failure instead of silently recovering. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -49,7 +49,7 @@ onMounted(async () => {
|
|||||||
:key="m.name"
|
:key="m.name"
|
||||||
:value="m.name"
|
:value="m.name"
|
||||||
>
|
>
|
||||||
{{ isHot(m.name) ? "\u2B24 " : "\u25CB " }}{{ m.name }}
|
{{ isHot(m.name) ? "🟢 " : "🔴 " }}{{ m.name }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -239,6 +239,10 @@ export const useChatStore = defineStore("chat", () => {
|
|||||||
|
|
||||||
// Recovery fallback: re-fetch conversation from DB
|
// Recovery fallback: re-fetch conversation from DB
|
||||||
if (!gotDone && currentConversation.value?.id === convId) {
|
if (!gotDone && currentConversation.value?.id === convId) {
|
||||||
|
useToastStore().show(
|
||||||
|
"Connection lost — response may be incomplete",
|
||||||
|
"error",
|
||||||
|
);
|
||||||
try {
|
try {
|
||||||
await fetchConversation(convId);
|
await fetchConversation(convId);
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
@@ -269,7 +269,7 @@ async def warm_model_route():
|
|||||||
|
|
||||||
async def _warm():
|
async def _warm():
|
||||||
try:
|
try:
|
||||||
async with httpx.AsyncClient(timeout=120.0) as client:
|
async with httpx.AsyncClient(timeout=300.0) as client:
|
||||||
await client.post(
|
await client.post(
|
||||||
f"{Config.OLLAMA_URL}/api/generate",
|
f"{Config.OLLAMA_URL}/api/generate",
|
||||||
json={"model": model, "prompt": "", "keep_alive": "30m"},
|
json={"model": model, "prompt": "", "keep_alive": "30m"},
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ async def ensure_model(model: str) -> None:
|
|||||||
|
|
||||||
logger.info("Pulling model '%s' from Ollama...", model)
|
logger.info("Pulling model '%s' from Ollama...", model)
|
||||||
try:
|
try:
|
||||||
async with httpx.AsyncClient(timeout=600.0) as client:
|
async with httpx.AsyncClient(timeout=1800.0) as client:
|
||||||
async with client.stream(
|
async with client.stream(
|
||||||
"POST",
|
"POST",
|
||||||
f"{Config.OLLAMA_URL}/api/pull",
|
f"{Config.OLLAMA_URL}/api/pull",
|
||||||
@@ -80,7 +80,7 @@ async def stream_chat(
|
|||||||
payload: dict = {"model": model, "messages": messages, "stream": True}
|
payload: dict = {"model": model, "messages": messages, "stream": True}
|
||||||
if options:
|
if options:
|
||||||
payload["options"] = options
|
payload["options"] = options
|
||||||
async with httpx.AsyncClient(timeout=httpx.Timeout(1800.0, connect=10.0, read=300.0)) as client:
|
async with httpx.AsyncClient(timeout=httpx.Timeout(1800.0, connect=30.0, read=300.0)) as client:
|
||||||
async with client.stream(
|
async with client.stream(
|
||||||
"POST",
|
"POST",
|
||||||
f"{Config.OLLAMA_URL}/api/chat",
|
f"{Config.OLLAMA_URL}/api/chat",
|
||||||
@@ -100,7 +100,7 @@ async def stream_chat(
|
|||||||
|
|
||||||
async def generate_completion(messages: list[dict], model: str) -> str:
|
async def generate_completion(messages: list[dict], model: str) -> str:
|
||||||
"""Non-streaming chat completion, returns full response text."""
|
"""Non-streaming chat completion, returns full response text."""
|
||||||
async with httpx.AsyncClient(timeout=httpx.Timeout(1800.0, connect=10.0, read=300.0)) as client:
|
async with httpx.AsyncClient(timeout=httpx.Timeout(1800.0, connect=30.0, read=300.0)) as client:
|
||||||
resp = await client.post(
|
resp = await client.post(
|
||||||
f"{Config.OLLAMA_URL}/api/chat",
|
f"{Config.OLLAMA_URL}/api/chat",
|
||||||
json={"model": model, "messages": messages, "stream": False},
|
json={"model": model, "messages": messages, "stream": False},
|
||||||
|
|||||||
+4
-2
@@ -12,7 +12,7 @@
|
|||||||
> Include file-level details in the commit body when the change is non-trivial.
|
> Include file-level details in the commit body when the change is non-trivial.
|
||||||
|
|
||||||
## Last Updated
|
## Last Updated
|
||||||
2026-02-14 — Phase 6.0: Model selection, dashboard chat input, model warming
|
2026-02-14 — Phase 6.1: Model status colors, timeout tuning, SSE error feedback
|
||||||
|
|
||||||
## Project Overview
|
## Project Overview
|
||||||
Fabled Assistant is a self-hosted note-taking and task-tracking application with
|
Fabled Assistant is a self-hosted note-taking and task-tracking application with
|
||||||
@@ -527,8 +527,10 @@ When adding a new migration, follow these conventions:
|
|||||||
- Per-conversation model selection via ModelSelector dropdown in chat header (persisted via PATCH)
|
- Per-conversation model selection via ModelSelector dropdown in chat header (persisted via PATCH)
|
||||||
- Dashboard inline chat input: model selector + note picker + textarea; creates conversation and navigates
|
- Dashboard inline chat input: model selector + note picker + textarea; creates conversation and navigates
|
||||||
- Model warming: default model pre-loaded into Ollama on dashboard mount via fire-and-forget POST
|
- Model warming: default model pre-loaded into Ollama on dashboard mount via fire-and-forget POST
|
||||||
- Hot/cold model indicators: `/api/chat/ps` proxies Ollama `/api/ps`; ModelSelector shows filled/empty circles
|
- Hot/cold model indicators: `/api/chat/ps` proxies Ollama `/api/ps`; ModelSelector shows green/red emoji circles
|
||||||
- Ollama configured with `OLLAMA_MAX_LOADED_MODELS=2` and `OLLAMA_KEEP_ALIVE=30m`
|
- Ollama configured with `OLLAMA_MAX_LOADED_MODELS=2` and `OLLAMA_KEEP_ALIVE=30m`
|
||||||
|
- Timeout tuning: connect timeout 30s (cold model loading), warm timeout 300s, pull timeout 1800s
|
||||||
|
- SSE reconnection failure shows error toast instead of silently recovering
|
||||||
|
|
||||||
### Authentication & User Management
|
### Authentication & User Management
|
||||||
- Session cookie auth with bcrypt, first-user-is-admin, orphaned data claiming
|
- Session cookie auth with bcrypt, first-user-is-admin, orphaned data claiming
|
||||||
|
|||||||
Reference in New Issue
Block a user