refactoring and clean up of chat cliet

This commit is contained in:
Storme-bit
2026-04-07 03:27:04 -07:00
parent 107ee5755e
commit 541e664da1
6 changed files with 43 additions and 30 deletions

View File

@@ -5,7 +5,7 @@ import InfoPanel from './components/InfoPanel';
import { useSession } from './hooks/useSession'; import { useSession } from './hooks/useSession';
import { useChat } from './hooks/useChat'; import { useChat } from './hooks/useChat';
const DEFAULT_MODEL = 'companion:latest'; import { DEFAULT_MODEL } from './config/constants';
export default function App() { export default function App() {
const [leftOpen, setLeftOpen] = useState(true); const [leftOpen, setLeftOpen] = useState(true);

View File

@@ -1,14 +1,16 @@
import { API_DEFAULTS } from "../config/constants";
const BASE_URL = import.meta.env.VITE_ORCHESTRATION_URL ?? ''; const BASE_URL = import.meta.env.VITE_ORCHESTRATION_URL ?? '';
// ── Sessions ──────────────────────────────────────────────── // ── Sessions ────────────────────────────────────────────────
export async function fetchSessions(limit = 20, offset = 0) { export async function fetchSessions(limit = API_DEFAULTS.SESSIONS_LIMIT, offset = API_DEFAULTS.OFFSET) {
const res = await fetch(`${BASE_URL}/sessions?limit=${limit}&offset=${offset}`); const res = await fetch(`${BASE_URL}/sessions?limit=${limit}&offset=${offset}`);
if (!res.ok) throw new Error(`Failed to fetch sessions: ${res.status}`); if (!res.ok) throw new Error(`Failed to fetch sessions: ${res.status}`);
return res.json(); return res.json();
} }
export async function fetchSessionHistory(sessionId, limit = 50, offset = 0) { export async function fetchSessionHistory(sessionId, limit = API_DEFAULTS.HISTORY_LIMIT, offset = API_DEFAULTS.OFFSET) {
const res = await fetch(`${BASE_URL}/sessions/${sessionId}/history?limit=${limit}&offset=${offset}`); const res = await fetch(`${BASE_URL}/sessions/${sessionId}/history?limit=${limit}&offset=${offset}`);
if (!res.ok) throw new Error(`Failed to fetch history: ${res.status}`); if (!res.ok) throw new Error(`Failed to fetch history: ${res.status}`);
return res.json(); return res.json();

View File

@@ -1,11 +1,5 @@
import React from 'react'; import React from 'react';
import { MODELS } from '../config/constants';
const MODELS = [
{ value: 'companion:latest', label: 'Companion' },
{ value: 'mistral-nemo:latest', label: 'Mistral Nemo' },
{ value: 'coder:latest', label: 'Coder' },
{ value: 'qwen2.5-coder:14b', label: 'Qwen 2.5 Coder 14B' },
];
export default function InfoPanel({ isOpen, onToggle, activeSession, lastModel, lastTokenCount, selectedModel, onModelChange }) { export default function InfoPanel({ isOpen, onToggle, activeSession, lastModel, lastTokenCount, selectedModel, onModelChange }) {

View File

@@ -0,0 +1,14 @@
export const MODELS = [
{ value: 'companion:latest', label: 'Companion' },
{ value: 'mistral-nemo:latest', label: 'Mistral Nemo' },
{ value: 'coder:latest', label: 'Coder' },
{ value: 'qwen2.5-coder:14b', label: 'Qwen 2.5 Coder 14B' },
];
export const DEFAULT_MODEL = MODELS[0].value;
export const API_DEFAULTS = {
SESSIONS_LIMIT: 20,
HISTORY_LIMIT: 50,
OFFSET: 0,
}

View File

@@ -9,18 +9,27 @@ export function useSession() {
const [loadingHistory, setLoadingHistory] = useState(false); const [loadingHistory, setLoadingHistory] = useState(false);
const [error, setError] = useState(null); const [error, setError] = useState(null);
// Load session list on mount
useEffect(() => {
loadSessions();
}, []);
async function loadSessions() { // Called by useChat after a message completes — keeps session list fresh
const refreshSessions = useCallback(async () => {
try { try {
const data = await fetchSessions(); const data = await fetchSessions();
setSessions(data); setSessions(data);
} catch (err) { } catch {
setError(err.message); // non-critical — sidebar just won't update
} }
}, []);
// Load session list on mount
useEffect(() => {
refreshSessions();
}, [refreshSessions]);
function episodesToMessages(episodes) {
return [...episodes].reverse().flatMap(ep => [
{ id: `${ep.id}-user`, role: 'user', text: ep.user_message },
{ id: `${ep.id}-ai`, role: 'assistant', text: ep.ai_response },
]);
} }
// Switch to an existing session and load its history // Switch to an existing session and load its history
@@ -32,10 +41,7 @@ export function useSession() {
try { try {
const data = await fetchSessionHistory(session.external_id); const data = await fetchSessionHistory(session.external_id);
// History comes back newest-first — reverse for display // History comes back newest-first — reverse for display
const history = data.episodes.reverse().map(ep => ([ const history = episodesToMessages(data.episodes);
{ id: `${ep.id}-user`, role: 'user', text: ep.user_message },
{ id: `${ep.id}-ai`, role: 'assistant', text: ep.ai_response },
])).flat();
setMessages(history); setMessages(history);
} catch (err) { } catch (err) {
@@ -58,15 +64,7 @@ export function useSession() {
setMessages([]); setMessages([]);
}, []); }, []);
// Called by useChat after a message completes — keeps session list fresh
const refreshSessions = useCallback(async () => {
try {
const data = await fetchSessions();
setSessions(data);
} catch {
// non-critical — sidebar just won't update
}
}, []);
// Append a message to the current thread (used by useChat) // Append a message to the current thread (used by useChat)
const appendMessage = useCallback((message) => { const appendMessage = useCallback((message) => {

View File

@@ -23,4 +23,9 @@ html, body, #root {
background: var(--bg-base); background: var(--bg-base);
color: var(--text-primary); color: var(--text-primary);
font-size: 15px; font-size: 15px;
}
@keyframes blink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
} }