Skip to main content
Glama
character-creator.js10.9 kB
#!/usr/bin/env node // Removed deprecated character-pipeline.js import - using corrected AffogatoClient from guidance notes import fs from 'fs'; import path from 'path'; import { createInterface } from 'node:readline'; // Load environment variables import dotenv from 'dotenv'; dotenv.config(); // Configuration const CONFIG = { DATABASES: { CHARACTERS_MASTER: process.env.CHARACTERS_MASTER_DB || '5b96c172-96b2-4b53-a52c-60d4874779f4', IMAGE_ASSETS: process.env.IMAGE_ASSETS_DB || '33335cfb-1cb4-4bb0-88ba-b5188456749d' } }; class CharacterCreator { constructor() { // Legacy pipeline removed - using corrected Affogato integration following user guidance notes // this.pipeline = new CharacterProductionPipeline(process.env.AFFOGATO_API_KEY); if (!process.env.AFFOGATO_API_KEY) { console.error('❌ AFFOGATO_API_KEY not found in environment variables'); process.exit(1); } } async createCharacter(characterData) { console.log('🎭 CHARACTER CREATOR TOOL'); console.log('========================\n'); // Validate input if (!characterData.name) { throw new Error('Character name is required'); } if (!characterData.referenceImagePath) { throw new Error('Reference image path is required'); } if (!fs.existsSync(characterData.referenceImagePath)) { throw new Error(`Reference image not found: ${characterData.referenceImagePath}`); } return await this.pipeline.createCharacterFromDescription(characterData); } async createScene(characterName, sceneData) { console.log('🎬 SCENE CREATOR TOOL'); console.log('====================\n'); return await this.pipeline.createSceneFromNotion(characterName, sceneData); } // Interactive character creation async interactiveCreate() { const readline = createInterface({ input: process.stdin, output: process.stdout }); const ask = (question) => new Promise((resolve) => { readline.question(question, resolve); }); try { console.log('🎭 Interactive Character Creator'); console.log('================================\n'); const name = await ask('Character name: '); const description = await ask('Character description: '); const imagePath = await ask('Reference image path: '); const typeInput = await ask('Character type (Main Character/Supporting Character/Background Character/Narrator) [Main Character]: '); const traitsInput = await ask('Personality traits (comma separated): '); const characterType = typeInput || 'Main Character'; const personalityTraits = traitsInput ? traitsInput.split(',').map(t => t.trim()) : []; const characterData = { name: name, description: description, referenceImagePath: imagePath, characterType: characterType, personalityTraits: personalityTraits }; console.log('\n🚀 Starting character creation...\n'); const result = await this.createCharacter(characterData); if (result.success) { console.log('\n✅ Character creation successful!'); console.log(`Character "${result.character.name}" is ready for production.`); } else { console.log('\n❌ Character creation failed:', result.error); } } catch (error) { console.error('❌ Error:', error.message); } finally { readline.close(); } } // List existing characters async listCharacters() { try { const notion = await this.pipeline.getNotionClient(); const response = await notion.databases.query({ database_id: CONFIG.DATABASES.CHARACTERS_MASTER }); console.log('🎭 EXISTING CHARACTERS'); console.log('=====================\n'); if (response.results.length === 0) { console.log('No characters found in database.'); return; } response.results.forEach((character, index) => { const name = character.properties['Character Name']?.title[0]?.text?.content || 'Unnamed'; const type = character.properties['Character Type']?.select?.name || 'Unknown'; const status = character.properties['Status']?.select?.name || 'Unknown'; const affogatoId = character.properties['Voice ID']?.rich_text[0]?.text?.content || 'Not set'; console.log(`${index + 1}. ${name}`); console.log(` Type: ${type}`); console.log(` Status: ${status}`); console.log(` Affogato ID: ${affogatoId}`); console.log(''); }); } catch (error) { console.error('❌ Error listing characters:', error.message); } } // Quick character creation from command line args async quickCreate(name, description, imagePath) { const result = await this.createCharacter({ name: name, description: description, referenceImagePath: imagePath, characterType: 'Main Character', personalityTraits: [] }); return result; } } // CLI Interface async function main() { const creator = new CharacterCreator(); const args = process.argv.slice(2); const command = args[0]; try { switch (command) { case 'interactive': case 'i': await creator.interactiveCreate(); break; case 'list': case 'l': await creator.listCharacters(); break; case 'quick': case 'q': if (args.length < 4) { console.error('Usage: npm run create quick <name> <description> <image-path>'); console.error('Example: npm run create quick "Maya" "A curious scientist" "./maya.png"'); process.exit(1); } const result = await creator.quickCreate(args[1], args[2], args[3]); if (result.success) { console.log('✅ Character created successfully!'); } else { console.log('❌ Character creation failed:', result.error); } break; case 'scene': case 's': if (args.length < 2) { console.error('Usage: npm run create scene <character-name> [scene-title] [scene-description]'); process.exit(1); } const characterName = args[1]; const sceneTitle = args[2] || 'Untitled Scene'; const sceneDescription = args[3] || 'Character in a scene'; const sceneResult = await creator.createScene(characterName, { sceneTitle: sceneTitle, sceneDescription: sceneDescription, generateVideo: true }); if (sceneResult.success) { console.log('✅ Scene created successfully!'); } else { console.log('❌ Scene creation failed:', sceneResult.error); } break; case 'test': case 't': // Test the system with sample data (if test image exists) const testImagePath = path.join('attached_assets', 'test-character.png'); if (fs.existsSync(testImagePath)) { const testResult = await creator.createCharacter({ name: 'Test Character', description: 'A friendly test character for pipeline validation', referenceImagePath: testImagePath, characterType: 'Main Character', personalityTraits: ['Friendly', 'Helpful'] }); if (testResult.success) { console.log('✅ Pipeline test successful!'); } else { console.log('❌ Pipeline test failed:', testResult.error); } } else { console.log('❌ Test image not found. Please upload a test-character.png to attached_assets folder.'); console.log('You can test with any image file instead:'); console.log('npm run create quick "Test" "A test character" "path/to/your/image.png"'); } break; default: console.log('🎭 Character Production System'); console.log('==============================\n'); console.log('Available commands:'); console.log(' npm run create interactive - Interactive character creation'); console.log(' npm run create list - List existing characters'); console.log(' npm run create quick <name> <description> <image-path>'); console.log(' npm run create scene <name> [title] [description]'); console.log(' npm run create test - Test the pipeline'); console.log('\nShort versions:'); console.log(' npm run create i - Interactive mode'); console.log(' npm run create l - List characters'); console.log(' npm run create q ... - Quick create'); console.log(' npm run create s ... - Create scene'); console.log(' npm run create t - Test'); console.log('\nExamples:'); console.log(' npm run create quick "Maya" "A curious scientist" "./maya.png"'); console.log(' npm run create scene "Maya" "Happy Scene" "Maya smiling in garden"'); break; } } catch (error) { console.error('❌ Error:', error.message); process.exit(1); } } // Run if called directly if (import.meta.url === `file://${process.argv[1]}`) { main().catch((error) => { console.error('❌ Fatal error:', error.message); process.exit(1); }); } export { CharacterCreator };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bermingham85/mcp-puppet-pipeline'

If you have feedback or need assistance with the MCP directory API, please join our Discord server