godcrm/backend/database/migrations/015-labs-ai-templates-seed.js
GOD CRM Release f89e074dd1
Some checks failed
CI / Lint / Typecheck / Test / Build (push) Has been cancelled
CI / PostgreSQL Integration Tests (push) Has been cancelled
GOD CRM — public scrubbed snapshot
Governed substrate for autonomous agents: scoped identity (passports),
audited actions, MCP workspace. Infra IPs and secrets redacted for public release.
2026-08-10 04:01:45 +03:00

375 lines
No EOL
14 KiB
JavaScript

// 🟢 GREEN Phase: Migration for Labs AI Templates Seed Data
// Migration 015: Seed labs_ai_templates with MindWorkflow AI Agents
// Migrated from: /home/dev2/workspace/mindworkflow-download/app/src/data/aiCatalog.ts
import dotenv from 'dotenv';
// Load environment variables BEFORE importing connection
dotenv.config();
/**
* Run migration to seed Labs AI Templates
* @param {import('better-sqlite3').Database|import('pg').Pool} db - Database instance
*/
export async function runMigration(db) {
console.log('📦 Running Migration 015: Labs AI Templates Seed...');
// Import after dotenv is loaded
const { isPostgres } = await import('../connection.js');
if (isPostgres()) {
// PostgreSQL version
await runPostgresMigration(db);
} else {
// SQLite version
await runSQLiteMigration(db);
}
console.log('✅ Migration 015 completed successfully!');
}
/**
* PostgreSQL migration
*/
async function runPostgresMigration(db) {
// ========================================
// SEED: labs_ai_templates with MindWorkflow agents
// ========================================
const templates = [
{
mindworkflow_id: 'planner_llm',
name: 'Strategic Planner',
category: 'text_to_text',
description: 'Long-form reasoning model for planning multi-step creative pipelines.',
system_prompt: 'You are a senior creative strategist. Respond with numbered steps, each containing a goal, reasoning, and deliverable.',
user_prompt_example: 'Draft a 5 step plan for launching a snack food brand on social media.',
inputs: JSON.stringify([
{ name: 'brief', description: 'Primary project description or goal statement' },
{ name: 'constraints', description: 'Hard limits such as budget or timeline', requirement: 'Optional but recommended' }
]),
settings: JSON.stringify({
model: 'gpt-4.1-mini',
temperature: '0.4',
top_p: '0.9'
}),
routing_config: JSON.stringify({
outputs: [{ id: 'text', type: 'text', enabled: true }],
maxLength: '8k tokens'
})
},
{
mindworkflow_id: 'tone_refiner',
name: 'Tone Refiner',
category: 'text_to_text',
description: 'Refines supplied copy to match a target brand voice.',
system_prompt: 'You are a copy editor tasked with adjusting tone without changing intent.',
user_prompt_example: 'Rewrite this paragraph to sound energetic and Gen-Z friendly.',
inputs: JSON.stringify([
{ name: 'draft', description: 'Original text to rephrase' },
{ name: 'tone', description: 'Voice guidelines or adjectives' }
]),
settings: JSON.stringify({
model: 'claude-3.5',
temperature: '0.3'
}),
routing_config: JSON.stringify({
outputs: [{ id: 'text', type: 'text', enabled: true }],
maxLength: '4k tokens'
})
},
{
mindworkflow_id: 'midjourney_adapter',
name: 'Visual Ideation Adapter',
category: 'text_to_image',
description: 'Prepares prompts and references for image generation pipelines.',
system_prompt: 'Combine user prompt and structured references into a single Midjourney-style command. List modifiers last.',
user_prompt_example: 'Concept art of a neon-lit street vendor in rainy Tokyo.',
inputs: JSON.stringify([
{ name: 'reference_image', description: 'Primary inspiration image URL', requirement: 'JPEG/PNG up to 2 MB' },
{ name: 'character_sheet', description: 'Character reference board', requirement: 'Optional' },
{ name: 'style', description: 'Target art direction keywords' }
]),
settings: JSON.stringify({
model: 'mj-v6-raw',
resolution: '1024x1024',
seed: 'auto'
}),
routing_config: JSON.stringify({
outputs: [{ id: 'image', type: 'image', enabled: true }],
maxLength: 'N/A'
})
},
{
mindworkflow_id: 'caption_model',
name: 'Scene Captioning',
category: 'image_to_text',
description: 'Generates descriptive captions for storyboard frames.',
system_prompt: 'Return vivid but production-ready descriptions mentioning characters, lighting, and props.',
user_prompt_example: 'Describe the uploaded storyboard frame in two sentences.',
inputs: JSON.stringify([
{ name: 'frame', description: 'Story frame image', requirement: 'PNG up to 5 MB' }
]),
settings: JSON.stringify({
model: 'gpt-4o-mini-vision',
temperature: '0.2'
}),
routing_config: JSON.stringify({
outputs: [{ id: 'text', type: 'text', enabled: true }],
maxLength: '1k tokens'
})
},
{
mindworkflow_id: 'voiceover_tts',
name: 'Narration Voice',
category: 'text_to_voice',
description: 'Produces natural voiceover tracks from scripts.',
system_prompt: 'Render the line with studio quality, subtle pacing, and no background music.',
user_prompt_example: 'Generate a calm, confident narration for the supplied script.',
inputs: JSON.stringify([
{ name: 'script', description: 'Narration script markdown' },
{ name: 'voice_reference', description: 'Optional timbre reference clip', requirement: 'MP3/WAV up to 30s' }
]),
settings: JSON.stringify({
model: 'elevenlabs-pro',
sample_rate: '48kHz',
language: 'en-US'
}),
routing_config: JSON.stringify({
outputs: [{ id: 'audio', type: 'voice', enabled: true }],
maxLength: '1.5k tokens'
})
},
{
mindworkflow_id: 'speech_to_text',
name: 'Interview Transcriber',
category: 'voice_to_text',
description: 'High accuracy transcription tuned for production interviews.',
system_prompt: 'Return JSON with segments, timestamps, and speaker labels suitable for editing timelines.',
user_prompt_example: 'Transcribe the conversation and highlight key soundbites.',
inputs: JSON.stringify([
{ name: 'recording', description: 'Interview audio', requirement: 'MP3/WAV up to 60 minutes' },
{ name: 'speaker_map', description: 'List of speaker names in order of appearance', requirement: 'Optional' }
]),
settings: JSON.stringify({
model: 'whisper-large-v3',
diarization: 'enabled'
}),
routing_config: JSON.stringify({
outputs: [{ id: 'text', type: 'text', enabled: true }],
maxLength: '60 minutes audio'
})
}
];
for (const template of templates) {
try {
await db.query(`
INSERT INTO labs_ai_templates (
mindworkflow_id, name, category, description,
system_prompt, user_prompt_example, inputs,
settings, routing_config, created_at
) VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb, $8::jsonb, $9::jsonb, NOW())
ON CONFLICT (mindworkflow_id) DO UPDATE SET
name = EXCLUDED.name,
category = EXCLUDED.category,
description = EXCLUDED.description,
system_prompt = EXCLUDED.system_prompt,
user_prompt_example = EXCLUDED.user_prompt_example,
inputs = EXCLUDED.inputs,
settings = EXCLUDED.settings,
routing_config = EXCLUDED.routing_config
`, [
template.mindworkflow_id,
template.name,
template.category,
template.description,
template.system_prompt,
template.user_prompt_example,
template.inputs,
template.settings,
template.routing_config
]);
console.log(` ✅ Seeded AI template: ${template.name} (${template.mindworkflow_id})`);
} catch (error) {
console.error(` ❌ Failed to seed template ${template.mindworkflow_id}:`, error.message);
}
}
}
/**
* SQLite migration
*/
async function runSQLiteMigration(db) {
// ========================================
// SEED: labs_ai_templates with MindWorkflow agents
// ========================================
const templates = [
{
mindworkflow_id: 'planner_llm',
name: 'Strategic Planner',
category: 'text_to_text',
description: 'Long-form reasoning model for planning multi-step creative pipelines.',
system_prompt: 'You are a senior creative strategist. Respond with numbered steps, each containing a goal, reasoning, and deliverable.',
user_prompt_example: 'Draft a 5 step plan for launching a snack food brand on social media.',
inputs: JSON.stringify([
{ name: 'brief', description: 'Primary project description or goal statement' },
{ name: 'constraints', description: 'Hard limits such as budget or timeline', requirement: 'Optional but recommended' }
]),
settings: JSON.stringify({
model: 'gpt-4.1-mini',
temperature: '0.4',
top_p: '0.9'
}),
routing_config: JSON.stringify({
outputs: [{ id: 'text', type: 'text', enabled: true }],
maxLength: '8k tokens'
})
},
{
mindworkflow_id: 'tone_refiner',
name: 'Tone Refiner',
category: 'text_to_text',
description: 'Refines supplied copy to match a target brand voice.',
system_prompt: 'You are a copy editor tasked with adjusting tone without changing intent.',
user_prompt_example: 'Rewrite this paragraph to sound energetic and Gen-Z friendly.',
inputs: JSON.stringify([
{ name: 'draft', description: 'Original text to rephrase' },
{ name: 'tone', description: 'Voice guidelines or adjectives' }
]),
settings: JSON.stringify({
model: 'claude-3.5',
temperature: '0.3'
}),
routing_config: JSON.stringify({
outputs: [{ id: 'text', type: 'text', enabled: true }],
maxLength: '4k tokens'
})
},
{
mindworkflow_id: 'midjourney_adapter',
name: 'Visual Ideation Adapter',
category: 'text_to_image',
description: 'Prepares prompts and references for image generation pipelines.',
system_prompt: 'Combine user prompt and structured references into a single Midjourney-style command. List modifiers last.',
user_prompt_example: 'Concept art of a neon-lit street vendor in rainy Tokyo.',
inputs: JSON.stringify([
{ name: 'reference_image', description: 'Primary inspiration image URL', requirement: 'JPEG/PNG up to 2 MB' },
{ name: 'character_sheet', description: 'Character reference board', requirement: 'Optional' },
{ name: 'style', description: 'Target art direction keywords' }
]),
settings: JSON.stringify({
model: 'mj-v6-raw',
resolution: '1024x1024',
seed: 'auto'
}),
routing_config: JSON.stringify({
outputs: [{ id: 'image', type: 'image', enabled: true }],
maxLength: 'N/A'
})
},
{
mindworkflow_id: 'caption_model',
name: 'Scene Captioning',
category: 'image_to_text',
description: 'Generates descriptive captions for storyboard frames.',
system_prompt: 'Return vivid but production-ready descriptions mentioning characters, lighting, and props.',
user_prompt_example: 'Describe the uploaded storyboard frame in two sentences.',
inputs: JSON.stringify([
{ name: 'frame', description: 'Story frame image', requirement: 'PNG up to 5 MB' }
]),
settings: JSON.stringify({
model: 'gpt-4o-mini-vision',
temperature: '0.2'
}),
routing_config: JSON.stringify({
outputs: [{ id: 'text', type: 'text', enabled: true }],
maxLength: '1k tokens'
})
},
{
mindworkflow_id: 'voiceover_tts',
name: 'Narration Voice',
category: 'text_to_voice',
description: 'Produces natural voiceover tracks from scripts.',
system_prompt: 'Render the line with studio quality, subtle pacing, and no background music.',
user_prompt_example: 'Generate a calm, confident narration for the supplied script.',
inputs: JSON.stringify([
{ name: 'script', description: 'Narration script markdown' },
{ name: 'voice_reference', description: 'Optional timbre reference clip', requirement: 'MP3/WAV up to 30s' }
]),
settings: JSON.stringify({
model: 'elevenlabs-pro',
sample_rate: '48kHz',
language: 'en-US'
}),
routing_config: JSON.stringify({
outputs: [{ id: 'audio', type: 'voice', enabled: true }],
maxLength: '1.5k tokens'
})
},
{
mindworkflow_id: 'speech_to_text',
name: 'Interview Transcriber',
category: 'voice_to_text',
description: 'High accuracy transcription tuned for production interviews.',
system_prompt: 'Return JSON with segments, timestamps, and speaker labels suitable for editing timelines.',
user_prompt_example: 'Transcribe the conversation and highlight key soundbites.',
inputs: JSON.stringify([
{ name: 'recording', description: 'Interview audio', requirement: 'MP3/WAV up to 60 minutes' },
{ name: 'speaker_map', description: 'List of speaker names in order of appearance', requirement: 'Optional' }
]),
settings: JSON.stringify({
model: 'whisper-large-v3',
diarization: 'enabled'
}),
routing_config: JSON.stringify({
outputs: [{ id: 'text', type: 'text', enabled: true }],
maxLength: '60 minutes audio'
})
}
];
for (const template of templates) {
try {
// SQLite doesn't support ON CONFLICT with complex updates, so we'll use INSERT OR REPLACE
const stmt = db.prepare(`
INSERT OR REPLACE INTO labs_ai_templates (
mindworkflow_id, name, category, description,
system_prompt, user_prompt_example, inputs,
settings, routing_config, created_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))
`);
stmt.run(
template.mindworkflow_id,
template.name,
template.category,
template.description,
template.system_prompt,
template.user_prompt_example,
template.inputs,
template.settings,
template.routing_config
);
console.log(` ✅ Seeded AI template: ${template.name} (${template.mindworkflow_id})`);
} catch (error) {
console.error(` ❌ Failed to seed template ${template.mindworkflow_id}:`, error.message);
}
}
}
// Run migration if executed directly
if (import.meta.url === `file://${process.argv[1]}`) {
const { getAdapter, isPostgres, getDb } = await import('../connection.js');
if (isPostgres()) {
const adapter = await getAdapter();
await runMigration(adapter);
} else {
const db = getDb();
await runMigration(db);
}
}