| import useAppStore from '../store/appStore' |
| import { getProcessStatus, getTree, readFile } from '../api/projects' |
|
|
| |
| |
| |
| const DEFAULT_ENTRY = 'frontend/src/App.jsx' |
|
|
| export function useSession() { |
| const { |
| setSessions, setActiveSessionId, setMessages, |
| setProject, resetProject, |
| resetSessionTokens, resetInferenceStats, |
| setRuntime, resetRuntime, stopStream, clearPacing, |
| } = useAppStore() |
|
|
| async function loadSessions() { |
| const res = await fetch('/api/sessions') |
| const data = await res.json() |
| const sessions = Array.isArray(data) ? data : [] |
| setSessions(sessions) |
| return sessions |
| } |
|
|
| async function createSession(name = 'New Session', template) { |
| const body = { name } |
| if (template) body.template = template |
| const res = await fetch('/api/sessions', { |
| method: 'POST', |
| headers: { 'Content-Type': 'application/json' }, |
| body: JSON.stringify(body), |
| }) |
| const session = await res.json() |
| await loadSessions() |
| return session |
| } |
|
|
| async function openSession(id) { |
| |
| |
| |
| stopStream() |
| clearPacing() |
|
|
| const res = await fetch(`/api/sessions/${id}`) |
| const data = await res.json() |
| setActiveSessionId(data.id) |
| |
| |
| const messages = (data.messages || []).map((m) => { |
| if (m.role !== 'assistant' || !m.tool_calls_json) return m |
| try { |
| return { ...m, toolCalls: JSON.parse(m.tool_calls_json) } |
| } catch { |
| return m |
| } |
| }) |
| setMessages(messages) |
| resetSessionTokens() |
| resetInferenceStats() |
|
|
| |
| resetRuntime() |
|
|
| const projectId = data.project_id |
| if (!projectId) { |
| resetProject() |
| return |
| } |
|
|
| const tree = await getTree(projectId) |
|
|
| |
| |
| const fileEntries = tree.filter((e) => !e.is_dir) |
| const contents = await Promise.all( |
| fileEntries.map((e) => |
| readFile(projectId, e.path).then((c) => [e.path, c]).catch(() => null), |
| ), |
| ) |
| const files = Object.fromEntries(contents.filter(Boolean)) |
|
|
| |
| const activeFile = files[DEFAULT_ENTRY] != null |
| ? DEFAULT_ENTRY |
| : (fileEntries[0]?.path ?? null) |
|
|
| setProject({ id: projectId, tree, files, activeFile, dirty: {} }) |
|
|
| |
| try { |
| const processStatus = await getProcessStatus(projectId) |
| const { overall, frontend, backend } = processStatus |
| if (overall !== 'idle') { |
| setRuntime({ |
| status: overall, |
| frontendPort: frontend.port, |
| backendPort: backend.port, |
| frontendStatus: frontend.status, |
| backendStatus: backend.status, |
| }) |
| } |
| } catch { } |
| } |
|
|
| async function deleteSession(id) { |
| await fetch(`/api/sessions/${id}`, { method: 'DELETE' }) |
| const sessions = await loadSessions() |
| if (sessions.length > 0) { |
| await openSession(sessions[0].id) |
| } else { |
| setActiveSessionId(null) |
| setMessages([]) |
| resetProject() |
| } |
| } |
|
|
| async function renameSession(id, name) { |
| await fetch(`/api/sessions/${id}`, { |
| method: 'PATCH', |
| headers: { 'Content-Type': 'application/json' }, |
| body: JSON.stringify({ name }), |
| }) |
| await loadSessions() |
| } |
|
|
| return { loadSessions, createSession, openSession, deleteSession, renameSession } |
| } |
|
|