Skip to content

Commit c90252a

Browse files
vbomfimCopilot
andcommitted
Add delete persona from sidebar
Hover over a persona to reveal ✕ button. Confirms before deleting. Removes persona, all conversations, and all memories from IndexedDB. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent dcc8a0c commit c90252a

3 files changed

Lines changed: 53 additions & 11 deletions

File tree

src/components/Sidebar.svelte

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,29 @@
22
import { personaStore } from '../stores/persona.svelte';
33
import { sceneStore } from '../stores/scene.svelte';
44
import { chatStore } from '../stores/chat.svelte';
5-
import { getLatestConversationForPersona } from '../lib/conversation/store';
6-
import { getMemoriesForPersona } from '../lib/memory/store';
5+
import { getLatestConversationForPersona, deleteConversationsForPersona } from '../lib/conversation/store';
6+
import { getMemoriesForPersona, deleteMemoriesForPersona } from '../lib/memory/store';
77
import { llmEngine } from '../lib/llm/engine.svelte';
88
import { buildSystemPrompt } from '../lib/llm/prompts';
99
import { summarizeAndStoreConversation } from '../lib/memory/episodic';
1010
import { saveConversation } from '../lib/conversation/store';
11+
import { deletePersona } from '../lib/persona/store';
1112
import type { Persona } from '../lib/persona/schema';
1213
1314
let isResuming = $state(false);
1415
16+
async function removePersona(e: Event, persona: Persona) {
17+
e.stopPropagation();
18+
if (!confirm(`Forget ${persona.identity.name}? This removes all conversations and memories.`)) return;
19+
20+
try {
21+
await deletePersona(persona.id);
22+
await deleteConversationsForPersona(persona.id);
23+
await deleteMemoriesForPersona(persona.id);
24+
personaStore.all = personaStore.all.filter(p => p.id !== persona.id);
25+
} catch { /* silent */ }
26+
}
27+
1528
async function resumePersona(persona: Persona) {
1629
if (isResuming) return;
1730
isResuming = true;
@@ -112,15 +125,24 @@
112125

113126
<div class="flex-1 overflow-y-auto">
114127
{#each inactivePersonas as persona}
115-
<button
116-
onclick={() => resumePersona(persona)}
117-
disabled={isResuming || chatStore.isGenerating}
118-
class="w-full text-left px-3 py-3 hover:bg-gray-700/50 transition-colors border-b border-gray-800 disabled:opacity-50 cursor-pointer"
119-
>
120-
<p class="text-sm font-medium text-gray-200 truncate">{persona.identity.name}</p>
121-
<p class="text-xs text-gray-500 truncate">{persona.background.profession}</p>
122-
<p class="text-xs text-gray-600 truncate">📍 {persona.background.currentLocation}</p>
123-
</button>
128+
<div class="flex items-center border-b border-gray-800 hover:bg-gray-700/50 transition-colors group">
129+
<button
130+
onclick={() => resumePersona(persona)}
131+
disabled={isResuming || chatStore.isGenerating}
132+
class="flex-1 text-left px-3 py-3 disabled:opacity-50 cursor-pointer"
133+
>
134+
<p class="text-sm font-medium text-gray-200 truncate">{persona.identity.name}</p>
135+
<p class="text-xs text-gray-500 truncate">{persona.background.profession}</p>
136+
<p class="text-xs text-gray-600 truncate">📍 {persona.background.currentLocation}</p>
137+
</button>
138+
<button
139+
onclick={(e) => removePersona(e, persona)}
140+
class="px-2 py-1 text-gray-600 hover:text-red-400 opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer"
141+
title="Forget {persona.identity.name}"
142+
>
143+
144+
</button>
145+
</div>
124146
{/each}
125147
</div>
126148
</div>

src/lib/conversation/store.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,13 @@ export async function getAllConversations(): Promise<StoredConversation[]> {
4545
const db = await getDB();
4646
return db.getAll('conversations');
4747
}
48+
49+
export async function deleteConversationsForPersona(personaId: string): Promise<void> {
50+
const conversations = await getConversationsForPersona(personaId);
51+
const db = await getDB();
52+
const tx = db.transaction('conversations', 'readwrite');
53+
for (const conv of conversations) {
54+
await tx.store.delete(conv.id);
55+
}
56+
await tx.done;
57+
}

src/lib/memory/store.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,13 @@ export async function getMemoriesForPersona(personaId: string): Promise<StoredMe
1313
const index = tx.store.index('by-persona');
1414
return index.getAll(personaId);
1515
}
16+
17+
export async function deleteMemoriesForPersona(personaId: string): Promise<void> {
18+
const memories = await getMemoriesForPersona(personaId);
19+
const db = await getDB();
20+
const tx = db.transaction('memories', 'readwrite');
21+
for (const mem of memories) {
22+
await tx.store.delete(mem.id);
23+
}
24+
await tx.done;
25+
}

0 commit comments

Comments
 (0)