import { Conversation } from '@/types/chat'; import { useMemo, useReducer } from 'react'; // Extracts property names from initial state of reducer to allow typesafe dispatch objects export type FieldNames = { [K in keyof T]: T[K] extends string ? K : K; }[keyof T]; // Returns the Action Type for the dispatch object to be used for typing in things like context export type ActionType = | { type: 'reset' } | { type?: 'change'; field: FieldNames; value: any }; // Returns a typed dispatch and state export const useCreateReducer = ({ initialState }: { initialState: T }) => { type Action = | { type: 'reset' } | { type?: 'change'; field: FieldNames; value: any }; const reducer = (state: T, action: Action) => { if (!action.type) return { ...state, [action.field]: action.value }; if (action.type === 'reset') return initialState; throw new Error(); }; const [state, dispatch] = useReducer(reducer, initialState); return useMemo(() => ({ state, dispatch }), [state, dispatch]); }; export const updateConversation = ( updatedConversation: Conversation, allConversations: Conversation[], ) => { const updatedConversations = allConversations.map((c) => { if (c.id === updatedConversation.id) { return updatedConversation; } return c; }); saveConversation(updatedConversation); saveConversations(updatedConversations); return { single: updatedConversation, all: updatedConversations, }; }; export const saveConversation = (conversation: Conversation) => { localStorage.setItem('selectedConversation', JSON.stringify(conversation)); }; export const saveConversations = (conversations: Conversation[]) => { localStorage.setItem('conversationHistory', JSON.stringify(conversations)); }; export function throttle any>( func: T, limit: number, ): T { let lastFunc: ReturnType; let lastRan: number; return ((...args) => { if (!lastRan) { func(...args); lastRan = Date.now(); } else { clearTimeout(lastFunc); lastFunc = setTimeout(() => { if (Date.now() - lastRan >= limit) { func(...args); lastRan = Date.now(); } }, limit - (Date.now() - lastRan)); } }) as T; } export const DEFAULT_SYSTEM_PROMPT = process.env.NEXT_PUBLIC_DEFAULT_SYSTEM_PROMPT || "Follow the user's instructions carefully. Respond using markdown."; export const DEFAULT_TEMPERATURE = parseFloat(process.env.NEXT_PUBLIC_DEFAULT_TEMPERATURE || "1");