From dfce63de664aac9a8fe328454098d140efc15896 Mon Sep 17 00:00:00 2001 From: Dorian Date: Wed, 4 Mar 2026 17:38:52 +0000 Subject: [PATCH] refactor(app): consolidate seeds into single conversation All 15 seed prompts now load as one conversation ("Content Showcase") instead of 15 separate ones. /seed collapses chat to show PromptIndex so users can quickly pick any prompt to see its content surface. Co-Authored-By: Claude Opus 4.6 --- packages/app/scripts/generate-seed-chats.ts | 13 +++---- .../app/src/__tests__/fixtures/seedPrompts.ts | 31 ++++++++------- .../app/src/components/chat/ChatWindow.vue | 10 ++--- packages/app/src/stores/chat.ts | 39 ++++++++----------- 4 files changed, 42 insertions(+), 51 deletions(-) diff --git a/packages/app/scripts/generate-seed-chats.ts b/packages/app/scripts/generate-seed-chats.ts index 0f4c98d6..1b4d5e55 100644 --- a/packages/app/scripts/generate-seed-chats.ts +++ b/packages/app/scripts/generate-seed-chats.ts @@ -1,8 +1,8 @@ /** * Generate .dev/chats.json from the seed prompt index. - * Run: npx tsx packages/app/scripts/generate-seed-chats.ts + * Run: pnpm -C packages/app exec tsx scripts/generate-seed-chats.ts */ -import { seedPromptsToConversations } from '../src/__tests__/fixtures/seedPrompts' +import { seedPromptsToConversation } from '../src/__tests__/fixtures/seedPrompts' import { writeFileSync, mkdirSync, existsSync } from 'fs' import { resolve, dirname } from 'path' @@ -10,12 +10,11 @@ const outPath = resolve(dirname(new URL(import.meta.url).pathname), '../.dev/cha const dir = dirname(outPath) if (!existsSync(dir)) mkdirSync(dir, { recursive: true }) -const conversations = seedPromptsToConversations() -const ids = Object.keys(conversations) +const conv = seedPromptsToConversation() const data = { - conversations, - activeConversationId: ids[0] ?? null, + conversations: { [conv.id]: conv }, + activeConversationId: conv.id, } writeFileSync(outPath, JSON.stringify(data, null, 2), 'utf-8') -console.log(`Wrote ${ids.length} seed conversations to ${outPath}`) +console.log(`Wrote seed conversation (${conv.messages.length / 2} prompts) to ${outPath}`) diff --git a/packages/app/src/__tests__/fixtures/seedPrompts.ts b/packages/app/src/__tests__/fixtures/seedPrompts.ts index 70816e24..34f1c98e 100644 --- a/packages/app/src/__tests__/fixtures/seedPrompts.ts +++ b/packages/app/src/__tests__/fixtures/seedPrompts.ts @@ -438,30 +438,31 @@ One of each is all you need to start.`, /** * Convert seed prompts to the .dev/chats.json conversation format. */ -export function seedPromptsToConversations(): Record { - const conversations: Record = {} - const baseTime = 1772488800000 // Stable base timestamp +} { + const baseTime = 1772488800000 + const messages: { id: string; role: string; content: string; timestamp: number }[] = [] for (let i = 0; i < seedPrompts.length; i++) { const seed = seedPrompts[i] const ts = baseTime + i * 60000 - conversations[seed.id] = { - id: seed.id, - title: seed.userQuery.slice(0, 60), - messages: [ - { id: `${seed.id}-q`, role: 'user', content: seed.userQuery, timestamp: ts }, - { id: `${seed.id}-a`, role: 'assistant', content: seed.assistantResponse, timestamp: ts + 3000 }, - ], - createdAt: ts, - updatedAt: ts + 3000, - } + messages.push( + { id: `${seed.id}-q`, role: 'user', content: seed.userQuery, timestamp: ts }, + { id: `${seed.id}-a`, role: 'assistant', content: seed.assistantResponse, timestamp: ts + 3000 }, + ) } - return conversations + return { + id: 'seed-all', + title: 'Content Showcase', + messages, + createdAt: baseTime, + updatedAt: baseTime + seedPrompts.length * 60000, + } } diff --git a/packages/app/src/components/chat/ChatWindow.vue b/packages/app/src/components/chat/ChatWindow.vue index 5129c97c..2997c504 100644 --- a/packages/app/src/components/chat/ChatWindow.vue +++ b/packages/app/src/components/chat/ChatWindow.vue @@ -332,12 +332,10 @@ async function handleSend(text: string, images: ImageAttachment[] = []) { if (trimmed === '/seed') { await chatStore.loadSeedChats() - // Switch to first seed conversation and open history - const firstSeed = chatStore.conversationList.find(c => c.id.startsWith('seed-')) - if (firstSeed) { - chatStore.setActiveConversation(firstSeed.id) - } - chatStore.showHistory = true + // loadSeedChats already switches to the seed conversation + // Collapse chat so user sees PromptIndex for quick picking + chatStore.chatCollapsed = true + chatStore.showHistory = false return } diff --git a/packages/app/src/stores/chat.ts b/packages/app/src/stores/chat.ts index 29bbbb23..1273c9ca 100644 --- a/packages/app/src/stores/chat.ts +++ b/packages/app/src/stores/chat.ts @@ -393,34 +393,27 @@ export const useChatStore = defineStore('chat', () => { return siblings } - /** Load seed conversations from fixture index */ + /** Load all seed prompts as a single conversation */ async function loadSeedChats(): Promise { - let seedConversations: Map try { - const { seedPromptsToConversations } = await import('@/__tests__/fixtures/seedPrompts') - const raw = seedPromptsToConversations() - seedConversations = new Map(Object.entries(raw)) as Map + const { seedPromptsToConversation } = await import('@/__tests__/fixtures/seedPrompts') + const conv = seedPromptsToConversation() as Conversation + + if (conversations.value.has(conv.id)) { + // Already loaded — just switch to it + activeConversationId.value = conv.id + return 0 + } + + const merged = new Map(conversations.value) + merged.set(conv.id, conv) + conversations.value = merged + activeConversationId.value = conv.id + immediateIDBSave(conv) + return conv.messages.length / 2 // number of prompt/response pairs } catch { return 0 } - - // Build a new Map to guarantee Vue reactivity triggers - const merged = new Map(conversations.value) - let added = 0 - for (const [id, conv] of seedConversations) { - if (!merged.has(id)) { - merged.set(id, conv) - immediateIDBSave(conv) - added++ - } - } - if (added > 0) { - conversations.value = merged - if (!activeConversationId.value) { - activeConversationId.value = [...seedConversations.keys()][0] ?? null - } - } - return added } return {