mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-11 17:26:57 +02:00
improve session activity and model display
This commit is contained in:
1 parent
a7290039f6
commit
f6793daed3
6 files changed
+65
-19
No files matched your search
+2
-1
@@ -3,13 +3,14 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=DM+Mono:wght@400;500&family=Press+Start+2P&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<title>Loki — Agent local</title>
|
||||
<title>Loki - Agent local</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
||||
<rect width="64" height="64" rx="10" fill="#18181b"/>
|
||||
<rect x="11" y="11" width="38" height="38" rx="7" fill="#ff5436" stroke="#ffffff" stroke-width="6"/>
|
||||
<rect x="25" y="25" width="12" height="12" fill="#ffffff"/>
|
||||
<path d="M18 54h38V16" fill="none" stroke="#ff5436" stroke-width="5" stroke-linecap="square"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 386 B |
@@ -20,12 +20,13 @@ export function ModelSelector() {
|
||||
<div className="relative" ref={ref}>
|
||||
<button
|
||||
onClick={() => setOpen((v) => !v)}
|
||||
className="flex h-[34px] items-center gap-2 border-[3px] border-white bg-accent px-3 text-white shadow-accent-soft"
|
||||
className="flex h-[34px] min-w-0 max-w-[260px] items-center gap-2 border-[3px] border-white bg-accent px-3 text-white shadow-accent-soft"
|
||||
title={selectedModel || undefined}
|
||||
style={{ borderRadius: 7 }}
|
||||
>
|
||||
<span className="h-2.5 w-2.5 border-2 border-line bg-white" />
|
||||
<span className="text-[14px] leading-none">{selectedModel || "—"}</span>
|
||||
<ChevronDown size={12} />
|
||||
<span className="min-w-0 truncate text-[14px] leading-none">{selectedModel || "—"}</span>
|
||||
<ChevronDown size={12} className="flex-none" />
|
||||
</button>
|
||||
|
||||
{open && (
|
||||
@@ -51,7 +52,9 @@ export function ModelSelector() {
|
||||
m.name === selectedModel ? "bg-accent" : "bg-card"
|
||||
}`}
|
||||
/>
|
||||
<span className="flex-1 text-xs text-ink-2">{m.name}</span>
|
||||
<span className="min-w-0 flex-1 truncate text-xs text-ink-2" title={m.name}>
|
||||
{m.name}
|
||||
</span>
|
||||
{m.size_go > 0 && (
|
||||
<span className="text-[10px] text-muted-2">{m.size_go} Go</span>
|
||||
)}
|
||||
|
||||
@@ -11,6 +11,7 @@ export function ChatPanel() {
|
||||
selectedModel,
|
||||
messages,
|
||||
streaming,
|
||||
streamingSessionId,
|
||||
streamContent,
|
||||
streamThinking,
|
||||
streamStatus,
|
||||
@@ -22,6 +23,7 @@ export function ChatPanel() {
|
||||
pendingShell,
|
||||
approveShell,
|
||||
rejectShell,
|
||||
sessions,
|
||||
} = useStore();
|
||||
|
||||
const activeTools = config
|
||||
@@ -49,7 +51,9 @@ export function ChatPanel() {
|
||||
}
|
||||
};
|
||||
|
||||
const empty = messages.length === 0 && !streaming;
|
||||
const showingStreaming = streaming && currentSessionId === streamingSessionId;
|
||||
const workingSession = sessions.find((s) => s.id === streamingSessionId);
|
||||
const empty = messages.length === 0 && !showingStreaming;
|
||||
|
||||
return (
|
||||
<div className="flex min-w-0 flex-1 flex-col bg-base">
|
||||
@@ -88,7 +92,7 @@ export function ChatPanel() {
|
||||
{messages.map((m) => (
|
||||
<Bubble key={m.id} msg={m} />
|
||||
))}
|
||||
{streaming && (
|
||||
{showingStreaming && (
|
||||
<Bubble
|
||||
msg={{
|
||||
id: "stream",
|
||||
@@ -105,7 +109,7 @@ export function ChatPanel() {
|
||||
thinking={streamThinking}
|
||||
/>
|
||||
)}
|
||||
{pendingShell && (
|
||||
{showingStreaming && pendingShell && (
|
||||
<ShellConfirm
|
||||
command={pendingShell}
|
||||
onApprove={approveShell}
|
||||
@@ -132,12 +136,23 @@ export function ChatPanel() {
|
||||
<button className="flex h-8 w-8 items-center justify-center border-2 border-line text-ink-2">
|
||||
<ClipIcon />
|
||||
</button>
|
||||
<div className="flex h-8 items-center gap-1.5 border-2 border-line px-2.5 text-[13px] text-ink-2">
|
||||
<div
|
||||
className="flex h-8 min-w-0 max-w-[220px] items-center gap-1.5 border-2 border-line px-2.5 text-[13px] text-ink-2"
|
||||
title={selectedModel || undefined}
|
||||
>
|
||||
<span className="h-2 w-2 border-2 border-line bg-accent" />
|
||||
{selectedModel || "—"}
|
||||
<span className="min-w-0 truncate">{selectedModel || "—"}</span>
|
||||
</div>
|
||||
<div className="flex-1" />
|
||||
<span className="text-[13px] text-muted-3">⏎ envoyer · ⇧⏎ ligne</span>
|
||||
{streaming && !showingStreaming ? (
|
||||
<span className="min-w-0 flex-1 truncate text-[13px] text-accent">
|
||||
Travail en cours : {workingSession?.title ?? "session ouverte"}
|
||||
</span>
|
||||
) : (
|
||||
<>
|
||||
<div className="flex-1" />
|
||||
<span className="text-[13px] text-muted-3">⏎ envoyer · ⇧⏎ ligne</span>
|
||||
</>
|
||||
)}
|
||||
<button
|
||||
onClick={submit}
|
||||
disabled={streaming || !draft.trim()}
|
||||
|
||||
@@ -8,6 +8,7 @@ export function LeftPanel() {
|
||||
const {
|
||||
sessions,
|
||||
currentSessionId,
|
||||
streamingSessionId,
|
||||
refreshSessions,
|
||||
refreshFiles,
|
||||
fileTree,
|
||||
@@ -43,6 +44,7 @@ export function LeftPanel() {
|
||||
)}
|
||||
{sessions.map((s) => {
|
||||
const active = s.id === currentSessionId;
|
||||
const working = s.id === streamingSessionId;
|
||||
return (
|
||||
<div
|
||||
key={s.id}
|
||||
@@ -60,6 +62,14 @@ export function LeftPanel() {
|
||||
>
|
||||
{s.title}
|
||||
</div>
|
||||
{working && (
|
||||
<span
|
||||
className="flex-none border-2 border-line bg-accent px-1.5 py-0.5 text-[10px] leading-none text-white"
|
||||
title="Session en cours de travail"
|
||||
>
|
||||
EN COURS
|
||||
</span>
|
||||
)}
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
|
||||
@@ -31,6 +31,7 @@ interface LokiState {
|
||||
currentSessionId: string | null;
|
||||
messages: Message[];
|
||||
streaming: boolean;
|
||||
streamingSessionId: string | null;
|
||||
streamContent: string; // réponse de l'agent en cours de frappe
|
||||
streamThinking: string; // raisonnement de l'agent en cours
|
||||
streamStatus: string;
|
||||
@@ -73,6 +74,7 @@ export const useStore = create<LokiState>((set, get) => ({
|
||||
currentSessionId: null,
|
||||
messages: [],
|
||||
streaming: false,
|
||||
streamingSessionId: null,
|
||||
streamContent: "",
|
||||
streamThinking: "",
|
||||
streamStatus: "",
|
||||
@@ -174,24 +176,26 @@ export const useStore = create<LokiState>((set, get) => ({
|
||||
|
||||
newSession: async () => {
|
||||
const s = await createSession(get().selectedModel || undefined);
|
||||
const streaming = get().streaming;
|
||||
set({
|
||||
currentSessionId: s.id,
|
||||
messages: [],
|
||||
streamContent: "",
|
||||
streamStatus: "",
|
||||
streamNotice: null,
|
||||
...(streaming
|
||||
? {}
|
||||
: { streamContent: "", streamStatus: "", streamNotice: null }),
|
||||
});
|
||||
await get().refreshSessions();
|
||||
},
|
||||
|
||||
openSession: async (id) => {
|
||||
const { messages } = await getSession(id);
|
||||
const streaming = get().streaming;
|
||||
set({
|
||||
currentSessionId: id,
|
||||
messages,
|
||||
streamContent: "",
|
||||
streamStatus: "",
|
||||
streamNotice: null,
|
||||
...(streaming
|
||||
? {}
|
||||
: { streamContent: "", streamStatus: "", streamNotice: null }),
|
||||
});
|
||||
},
|
||||
|
||||
@@ -251,6 +255,7 @@ export const useStore = create<LokiState>((set, get) => ({
|
||||
set({
|
||||
messages: [...get().messages, userMsg],
|
||||
streaming: true,
|
||||
streamingSessionId: sid,
|
||||
streamContent: "",
|
||||
streamThinking: "",
|
||||
streamStatus: "Connexion à Ollama…",
|
||||
@@ -292,6 +297,7 @@ export const useStore = create<LokiState>((set, get) => ({
|
||||
);
|
||||
set({
|
||||
streaming: false,
|
||||
streamingSessionId: null,
|
||||
streamContent: "",
|
||||
streamThinking: "",
|
||||
streamStatus: "",
|
||||
@@ -314,13 +320,18 @@ export const useStore = create<LokiState>((set, get) => ({
|
||||
};
|
||||
set({
|
||||
streaming: false,
|
||||
streamingSessionId: null,
|
||||
streamContent: "",
|
||||
streamThinking: "",
|
||||
streamStatus: "",
|
||||
streamNotice: null,
|
||||
streamTools: [],
|
||||
messages: [...get().messages, errMsg],
|
||||
messages:
|
||||
get().currentSessionId === sid
|
||||
? [...get().messages, errMsg]
|
||||
: get().messages,
|
||||
});
|
||||
void get().refreshSessions();
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user