feat: add chat assistant with role-aware prompt and vision support
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
'use client';
|
||||
|
||||
import { create } from 'zustand';
|
||||
import { persist, createJSONStorage } from 'zustand/middleware';
|
||||
|
||||
export interface MessageAttachment {
|
||||
name: string;
|
||||
type: string;
|
||||
dataUrl: string;
|
||||
size: number;
|
||||
}
|
||||
|
||||
export interface Message {
|
||||
id: string;
|
||||
role: 'user' | 'assistant';
|
||||
content: string;
|
||||
attachments?: MessageAttachment[];
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
export interface ChatSession {
|
||||
id: string;
|
||||
title: string;
|
||||
messages: Message[];
|
||||
createdAt: number;
|
||||
}
|
||||
|
||||
interface ChatState {
|
||||
sessions: ChatSession[];
|
||||
activeSessionId: string | null;
|
||||
addMessage: (sessionId: string, message: Omit<Message, 'id' | 'timestamp'>) => void;
|
||||
createSession: (title: string) => string;
|
||||
setActiveSession: (id: string | null) => void;
|
||||
deleteSession: (id: string) => void;
|
||||
renameSession: (id: string, title: string) => void;
|
||||
clearAll: () => void;
|
||||
}
|
||||
|
||||
function randomId() {
|
||||
if (typeof crypto !== 'undefined' && 'randomUUID' in crypto) {
|
||||
return crypto.randomUUID();
|
||||
}
|
||||
return Math.random().toString(36).slice(2, 11);
|
||||
}
|
||||
|
||||
export const useChatStore = create<ChatState>()(
|
||||
persist(
|
||||
(set) => ({
|
||||
sessions: [],
|
||||
activeSessionId: null,
|
||||
createSession: (title) => {
|
||||
const id = randomId();
|
||||
const trimmed = (title || 'Neue Reparatur').slice(0, 60);
|
||||
set((state) => ({
|
||||
sessions: [
|
||||
{ id, title: trimmed, messages: [], createdAt: Date.now() },
|
||||
...state.sessions,
|
||||
],
|
||||
activeSessionId: id,
|
||||
}));
|
||||
return id;
|
||||
},
|
||||
setActiveSession: (id) => set({ activeSessionId: id }),
|
||||
addMessage: (sessionId, msg) => {
|
||||
set((state) => ({
|
||||
sessions: state.sessions.map((s) =>
|
||||
s.id === sessionId
|
||||
? {
|
||||
...s,
|
||||
messages: [
|
||||
...s.messages,
|
||||
{ ...msg, id: randomId(), timestamp: Date.now() },
|
||||
],
|
||||
}
|
||||
: s
|
||||
),
|
||||
}));
|
||||
},
|
||||
deleteSession: (id) =>
|
||||
set((state) => ({
|
||||
sessions: state.sessions.filter((s) => s.id !== id),
|
||||
activeSessionId: state.activeSessionId === id ? null : state.activeSessionId,
|
||||
})),
|
||||
renameSession: (id, title) =>
|
||||
set((state) => ({
|
||||
sessions: state.sessions.map((s) =>
|
||||
s.id === id ? { ...s, title: title.slice(0, 60) } : s
|
||||
),
|
||||
})),
|
||||
clearAll: () => set({ sessions: [], activeSessionId: null }),
|
||||
}),
|
||||
{
|
||||
name: 'patchpilot:chat',
|
||||
storage: createJSONStorage(() => localStorage),
|
||||
version: 2,
|
||||
}
|
||||
)
|
||||
);
|
||||
Reference in New Issue
Block a user