diff --git a/apps/rowboat/app/actions/assistant-templates.actions.ts b/apps/rowboat/app/actions/assistant-templates.actions.ts index 29abde59..13fc55c7 100644 --- a/apps/rowboat/app/actions/assistant-templates.actions.ts +++ b/apps/rowboat/app/actions/assistant-templates.actions.ts @@ -5,6 +5,7 @@ import { authCheck } from "./auth.actions"; import { MongoDBAssistantTemplatesRepository } from '@/src/infrastructure/repositories/mongodb.assistant-templates.repository'; import { prebuiltTemplates } from '@/app/lib/prebuilt-cards'; import { USE_AUTH } from '@/app/lib/feature_flags'; +import { ensureLibraryTemplatesSeeded } from '@/app/lib/assistant_templates_seed'; const repo = new MongoDBAssistantTemplatesRepository(); @@ -40,7 +41,8 @@ const CreateTemplateSchema = z.object({ export async function listAssistantTemplates(request: z.infer) { const user = await authCheck(); - // No longer seeding all templates upfront - using lazy seeding instead + // Kick off best-effort library reconcile/seed on each UI fetch (non-blocking) + try { void ensureLibraryTemplatesSeeded(); } catch {} const params = ListTemplatesSchema.parse(request); diff --git a/apps/rowboat/app/lib/assistant_templates_seed.ts b/apps/rowboat/app/lib/assistant_templates_seed.ts index 862a2380..002e30a3 100644 --- a/apps/rowboat/app/lib/assistant_templates_seed.ts +++ b/apps/rowboat/app/lib/assistant_templates_seed.ts @@ -14,6 +14,7 @@ export async function ensureLibraryTemplatesSeeded(): Promise { console.log('[PrebuiltTemplates] Starting template seeding...'); const entries = Object.entries(prebuiltTemplates); + const currentPrebuiltKeys = new Set(entries.map(([key]) => key)); for (const [prebuiltKey, tpl] of entries) { // minimal guard; only ingest valid workflow-like objects if (!(tpl as any)?.agents || !Array.isArray((tpl as any).agents)) continue; @@ -51,6 +52,33 @@ export async function ensureLibraryTemplatesSeeded(): Promise { await collection.insertOne(doc as any); } + + // Simple reconcile: delete library templates that are no longer present in prebuilt files + try { + const cursor = collection.find({ + source: 'library', + authorName: 'Rowboat', + tags: { $in: ["__library__"] }, + }, { projection: { _id: 1, tags: 1, name: 1 } }); + + const toDeleteIds: any[] = []; + const removedNames: string[] = []; + for await (const doc of cursor as any) { + const prebuiltTag: string | undefined = (doc.tags || []).find((t: string) => t.startsWith('prebuilt:')); + const key = prebuiltTag ? prebuiltTag.replace('prebuilt:', '') : undefined; + if (!key || !currentPrebuiltKeys.has(key)) { + toDeleteIds.push(doc._id); + if (doc.name) removedNames.push(doc.name); + } + } + + if (toDeleteIds.length > 0) { + await collection.deleteMany({ _id: { $in: toDeleteIds } } as any); + console.log(`[PrebuiltTemplates] Reconciled by deleting ${toDeleteIds.length} removed templates:`, removedNames); + } + } catch (reconcileErr) { + console.error('[PrebuiltTemplates] Reconcile (delete missing) failed:', reconcileErr); + } } catch (err) { // best-effort seed; do not throw to avoid breaking requests console.error("ensureLibraryTemplatesSeeded error:", err);