diff --git a/package.json b/package.json
index 28fe37a..f57cf9e 100644
--- a/package.json
+++ b/package.json
@@ -5,6 +5,7 @@
"scripts": {
"playground:dev": "pnpm run --filter=playground dev",
"lint": "eslint --cache --cache-location ./node_modules/.cache/eslint .",
+ "lint:fix": "npm run lint -- --fix",
"build": "pnpm run -r build",
"test": "pnpm run -r test",
"typecheck": "pnpm run -r typecheck"
diff --git a/packages/bolt/app/components/header/Header.tsx b/packages/bolt/app/components/header/Header.tsx
index 2aa4d48..15cf4bf 100644
--- a/packages/bolt/app/components/header/Header.tsx
+++ b/packages/bolt/app/components/header/Header.tsx
@@ -3,6 +3,7 @@ import { ClientOnly } from 'remix-utils/client-only';
import { chatStore } from '~/lib/stores/chat';
import { classNames } from '~/utils/classNames';
import { HeaderActionButtons } from './HeaderActionButtons.client';
+import { ChatDescription } from '~/lib/persistence/ChatDescription.client';
export function Header() {
const chat = useStore(chatStore);
@@ -23,7 +24,9 @@ export function Header() {
-
+
+ {() => }
+
{chat.started && (
{() => (
diff --git a/packages/bolt/app/components/sidebar/Menu.client.tsx b/packages/bolt/app/components/sidebar/Menu.client.tsx
index 3438214..cfeeb3c 100644
--- a/packages/bolt/app/components/sidebar/Menu.client.tsx
+++ b/packages/bolt/app/components/sidebar/Menu.client.tsx
@@ -4,7 +4,7 @@ import { toast } from 'react-toastify';
import { Dialog, DialogButton, DialogDescription, DialogRoot, DialogTitle } from '~/components/ui/Dialog';
import { IconButton } from '~/components/ui/IconButton';
import { ThemeSwitch } from '~/components/ui/ThemeSwitch';
-import { db, deleteId, getAll, type ChatHistoryItem } from '~/lib/persistence';
+import { db, deleteById, getAll, chatId, type ChatHistoryItem } from '~/lib/persistence';
import { cubicEasingFn } from '~/utils/easings';
import { logger } from '~/utils/logger';
import { HistoryItem } from './HistoryItem';
@@ -52,8 +52,15 @@ export function Menu() {
event.preventDefault();
if (db) {
- deleteId(db, item.id)
- .then(() => loadEntries())
+ deleteById(db, item.id)
+ .then(() => {
+ loadEntries();
+
+ if (chatId.get() === item.id) {
+ // hard page navigation to clear the stores
+ window.location.pathname = '/';
+ }
+ })
.catch((error) => {
toast.error('Failed to delete conversation');
logger.error(error);
diff --git a/packages/bolt/app/lib/persistence/ChatDescription.client.tsx b/packages/bolt/app/lib/persistence/ChatDescription.client.tsx
new file mode 100644
index 0000000..9c7cbf2
--- /dev/null
+++ b/packages/bolt/app/lib/persistence/ChatDescription.client.tsx
@@ -0,0 +1,6 @@
+import { useStore } from '@nanostores/react';
+import { description } from './useChatHistory';
+
+export function ChatDescription() {
+ return useStore(description);
+}
diff --git a/packages/bolt/app/lib/persistence/db.ts b/packages/bolt/app/lib/persistence/db.ts
index 786ad91..7a952e3 100644
--- a/packages/bolt/app/lib/persistence/db.ts
+++ b/packages/bolt/app/lib/persistence/db.ts
@@ -92,7 +92,7 @@ export async function getMessagesById(db: IDBDatabase, id: string): Promise {
+export async function deleteById(db: IDBDatabase, id: string): Promise {
return new Promise((resolve, reject) => {
const transaction = db.transaction('chats', 'readwrite');
const store = transaction.objectStore('chats');
diff --git a/packages/bolt/app/lib/persistence/useChatHistory.ts b/packages/bolt/app/lib/persistence/useChatHistory.ts
index 3b5e181..9d6d324 100644
--- a/packages/bolt/app/lib/persistence/useChatHistory.ts
+++ b/packages/bolt/app/lib/persistence/useChatHistory.ts
@@ -1,6 +1,7 @@
import { useLoaderData, useNavigate } from '@remix-run/react';
+import { useState, useEffect } from 'react';
+import { atom } from 'nanostores';
import type { Message } from 'ai';
-import { useEffect, useState } from 'react';
import { toast } from 'react-toastify';
import { AnalyticsAction, sendAnalyticsEvent } from '~/lib/analytics';
import { workbenchStore } from '~/lib/stores/workbench';
@@ -18,16 +19,16 @@ const persistenceEnabled = !import.meta.env.VITE_DISABLE_PERSISTENCE;
export const db = persistenceEnabled ? await openDatabase() : undefined;
+export const chatId = atom(undefined);
+export const description = atom(undefined);
+
export function useChatHistory() {
const navigate = useNavigate();
const { id: mixedId } = useLoaderData<{ id?: string }>();
- const [chatId, setChatId] = useState(mixedId);
const [initialMessages, setInitialMessages] = useState([]);
const [ready, setReady] = useState(false);
- const [entryId, setEntryId] = useState();
const [urlId, setUrlId] = useState();
- const [description, setDescription] = useState();
useEffect(() => {
if (!db) {
@@ -40,14 +41,14 @@ export function useChatHistory() {
return;
}
- if (chatId) {
- getMessages(db, chatId)
+ if (mixedId) {
+ getMessages(db, mixedId)
.then((storedMessages) => {
if (storedMessages && storedMessages.messages.length > 0) {
setInitialMessages(storedMessages.messages);
setUrlId(storedMessages.urlId);
- setDescription(storedMessages.description);
- setChatId(storedMessages.id);
+ description.set(storedMessages.description);
+ chatId.set(storedMessages.id);
} else {
navigate(`/`, { replace: true });
}
@@ -61,7 +62,7 @@ export function useChatHistory() {
}, []);
return {
- ready: !chatId || ready,
+ ready: !mixedId || ready,
initialMessages,
storeMessageHistory: async (messages: Message[]) => {
if (!db || messages.length === 0) {
@@ -77,27 +78,21 @@ export function useChatHistory() {
setUrlId(urlId);
}
- if (!description && firstArtifact?.title) {
- setDescription(firstArtifact?.title);
+ if (!description.get() && firstArtifact?.title) {
+ description.set(firstArtifact?.title);
}
- if (initialMessages.length === 0) {
- if (!entryId) {
- const nextId = await getNextId(db);
+ if (initialMessages.length === 0 && !chatId.get()) {
+ const nextId = await getNextId(db);
- await setMessages(db, nextId, messages, urlId, description);
+ chatId.set(nextId);
- setEntryId(nextId);
-
- if (!urlId) {
- navigateChat(nextId);
- }
- } else {
- await setMessages(db, entryId, messages, urlId, description);
+ if (!urlId) {
+ navigateChat(nextId);
}
- } else {
- await setMessages(db, chatId as string, messages, urlId, description);
}
+
+ await setMessages(db, chatId.get() as string, messages, urlId, description.get());
},
};
}