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:
co-authored by
Claude Opus 4.6
parent
1a76efce4a
commit
dfce63de66
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user