Files
muzick/frontend/src/store/useVibeStore.ts
T

57 lines
2.1 KiB
TypeScript

import { create } from 'zustand';
import type { Track, VibeSession } from '../types';
import type { VibePlanItem } from '../services/vibeService';
// The durable plan is authoritative. `buffer` is only its currently
// uncommitted, hydrated preview; it may be replaced at any feedback boundary.
interface VibeState {
activeSessionId: string | null;
seedTrackId: string | null;
planVersion: number | null;
/** Durable cursor for the track currently in Vibe playback. */
currentPlanItem: VibePlanItem | null;
centerTrack: Track | null;
buffer: Track[];
initialBatchStatus: 'idle' | 'loading' | 'exhausted' | 'failed';
setActiveSession: (session: VibeSession | null) => void;
setSeedTrackId: (seedTrackId: string | null) => void;
setCenterTrack: (track: Track | null) => void;
/** Returns false when a response belongs to an older plan revision. */
setPlan: (planVersion: number | null, preview: Track[]) => boolean;
setCurrentPlanItem: (item: VibePlanItem | null) => void;
setInitialBatchStatus: (status: VibeState['initialBatchStatus']) => void;
reset: () => void;
}
const initialState = {
activeSessionId: null as string | null,
seedTrackId: null as string | null,
planVersion: null as number | null,
currentPlanItem: null as VibePlanItem | null,
centerTrack: null as Track | null,
buffer: [] as Track[],
initialBatchStatus: 'idle' as const,
};
export const useVibeStore = create<VibeState>((set, get) => ({
...initialState,
setActiveSession: (session) => set(
session
? { activeSessionId: session.sessionId, seedTrackId: session.seedTrackId }
: { activeSessionId: null, seedTrackId: null },
),
setSeedTrackId: (seedTrackId) => set({ seedTrackId }),
setCenterTrack: (centerTrack) => set({ centerTrack }),
setPlan: (planVersion, buffer) => {
const current = get().planVersion;
if (planVersion === null || (current !== null && planVersion < current)) return false;
set({ planVersion, buffer });
return true;
},
setCurrentPlanItem: (currentPlanItem) => set({ currentPlanItem }),
setInitialBatchStatus: (initialBatchStatus) => set({ initialBatchStatus }),
reset: () => set({ ...initialState }),
}));