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 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-04 17:38:52 +00:00
co-authored by Claude Opus 4.6
parent 1a76efce4a
commit dfce63de66
4 changed files with 42 additions and 51 deletions
+6 -7
View File
@@ -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}`)
@@ -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<string, {
/** Build a single conversation with all seed prompts as sequential messages. */
export function seedPromptsToConversation(): {
id: string
title: string
messages: { id: string; role: string; content: string; timestamp: number }[]
createdAt: number
updatedAt: number
}> {
const conversations: Record<string, any> = {}
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,
}
}
@@ -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
}
+16 -23
View File
@@ -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<number> {
let seedConversations: Map<string, Conversation>
try {
const { seedPromptsToConversations } = await import('@/__tests__/fixtures/seedPrompts')
const raw = seedPromptsToConversations()
seedConversations = new Map(Object.entries(raw)) as Map<string, Conversation>
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 {