Files
Loki/frontend/src/App.tsx
T
MichaelandClaude Opus 4.8 cb2872c78a perf: fix model reload thrash and cut time-to-first-token
Ollama reloaded the chat model mid-message because plan/summary/router
calls sent divergent runner options (no num_ctx/num_batch) and omitted
keep_alive — the main cause of perceived slowness.

- share one keep-alive httpx.AsyncClient for all Ollama calls
- unify runner options (runner_options) + keep_alive on every model
  call, embeddings included
- drop the blocking LLM routing fallback (pure lexical heuristic)
- run RAG recall + plan + code-model pick in parallel inside the SSE
  stream, after the start event
- RAG cosine scoring off the event loop; cache /api/tags 30s and
  nvidia-smi 5s; frontend polls 2s->5s, warm poll backoff, dedup
  config fetch

feat: working session menu in TopBar (switch/create/rename/delete)
feat: workspace file deletion (DELETE /api/files + UI trash buttons)
docs: recommended Ollama env vars (KEEP_ALIVE, MAX_LOADED_MODELS...)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 13:58:18 +02:00

67 lines
2.2 KiB
TypeScript

import { useEffect, useState } from "react";
import { ActivityBar, type View } from "./components/ActivityBar";
import { TopBar } from "./components/TopBar";
import { LeftPanel } from "./panels/LeftPanel";
import { ChatPanel } from "./panels/ChatPanel";
import { PreviewPanel } from "./panels/PreviewPanel";
import { SettingsView } from "./panels/SettingsView";
import { FilesView, HistoryView, ToolsView } from "./panels/ActivityViews";
import { useStore } from "./store/useStore";
export default function App() {
const [view, setView] = useState<View>("chat");
const {
refreshStatus,
refreshSystemStats,
refreshModels,
refreshLoadedModels,
refreshSessions,
} = useStore();
// Au démarrage : statut Ollama + modèles + sessions. La config est chargée
// par setSelectedModel (via refreshModels) — pas de double fetch. Poll du
// statut, des stats système (5 s, apparié au cache GPU serveur) et des
// modèles chargés en VRAM (indicateur de préchargement).
useEffect(() => {
refreshStatus();
refreshSystemStats();
refreshModels();
refreshLoadedModels();
refreshSessions();
const statusId = setInterval(refreshStatus, 10000);
const statsId = setInterval(refreshSystemStats, 5000);
const loadedId = setInterval(refreshLoadedModels, 8000);
return () => {
clearInterval(statusId);
clearInterval(statsId);
clearInterval(loadedId);
};
}, [refreshStatus, refreshSystemStats, refreshModels, refreshLoadedModels, refreshSessions]);
return (
<div className="flex h-full flex-col bg-base text-ink">
<TopBar />
<div className="flex min-h-0 flex-1">
<ActivityBar active={view} onChange={setView} />
{view === "chat" && (
<>
<LeftPanel />
<ChatPanel />
<PreviewPanel />
</>
)}
{view === "history" && <HistoryView onOpen={() => setView("chat")} />}
{view === "files" && (
<>
<FilesView />
<PreviewPanel />
</>
)}
{view === "tools" && <ToolsView onSettings={() => setView("settings")} />}
{view === "settings" && <SettingsView />}
</div>
</div>
);
}