|
const fs = require('fs'); |
|
const path = require('path'); |
|
|
|
|
|
const BATCH_SIZE = 50; |
|
|
|
|
|
const configsDir = path.join(__dirname, 'configs'); |
|
const imagesDir = path.join(__dirname, 'images/avatar-photos'); |
|
const outputDir = path.join(__dirname, 'generated-configs'); |
|
const outputListFile = path.join(__dirname, 'configs-list.json'); |
|
|
|
|
|
const args = process.argv.slice(2); |
|
const startIndex = parseInt(args[0]) || 0; |
|
const batchSize = parseInt(args[1]) || BATCH_SIZE; |
|
|
|
|
|
if (!fs.existsSync(outputDir)) { |
|
fs.mkdirSync(outputDir, { recursive: true }); |
|
} |
|
|
|
|
|
const configFiles = fs.readdirSync(configsDir) |
|
.filter(file => file.endsWith('.md')) |
|
.sort((a, b) => a.localeCompare(b)); |
|
|
|
|
|
const imageFiles = fs.readdirSync(imagesDir) |
|
.filter(file => file.endsWith('.webp')); |
|
|
|
|
|
const endIndex = Math.min(startIndex + batchSize, configFiles.length); |
|
const filesToProcess = configFiles.slice(startIndex, endIndex); |
|
|
|
console.log(`Processing files ${startIndex + 1} to ${endIndex} of ${configFiles.length}`); |
|
console.log(`Found ${imageFiles.length} image files.`); |
|
|
|
|
|
let configsList = []; |
|
if (fs.existsSync(outputListFile)) { |
|
try { |
|
configsList = JSON.parse(fs.readFileSync(outputListFile, 'utf8')); |
|
console.log(`Loaded ${configsList.length} existing configurations from configs-list.json`); |
|
} catch (error) { |
|
console.error('Error loading existing configs-list.json:', error); |
|
} |
|
} |
|
|
|
|
|
filesToProcess.forEach(file => { |
|
try { |
|
const filePath = path.join(configsDir, file); |
|
const content = fs.readFileSync(filePath, 'utf8'); |
|
|
|
|
|
const name = extractSection(content, '# Name', '# Description').trim(); |
|
const description = extractSection(content, '# Description', '# System Prompt').trim(); |
|
const systemPrompt = extractSection(content, '# System Prompt', null).trim(); |
|
|
|
if (!name || !description || !systemPrompt) { |
|
console.warn(`Skipping ${file}: Missing required sections`); |
|
return; |
|
} |
|
|
|
|
|
const avatar = findMatchingAvatar(file, name, imageFiles); |
|
|
|
|
|
const configData = { |
|
name, |
|
description, |
|
systemPrompt, |
|
avatar: avatar ? `images/avatar-photos/${avatar}` : null |
|
}; |
|
|
|
|
|
const jsonFilename = file.replace('.md', '.json'); |
|
fs.writeFileSync(path.join(outputDir, jsonFilename), JSON.stringify(configData, null, 2)); |
|
|
|
|
|
const existingIndex = configsList.findIndex(c => c.filename === jsonFilename); |
|
if (existingIndex !== -1) { |
|
|
|
configsList[existingIndex] = { ...configData, filename: jsonFilename }; |
|
} else { |
|
|
|
configsList.push({ |
|
name, |
|
description, |
|
systemPrompt, |
|
filename: jsonFilename, |
|
avatar: avatar ? `images/avatar-photos/${avatar}` : null |
|
}); |
|
} |
|
|
|
console.log(`Processed: ${file} (${configsList.length} total)`); |
|
} catch (error) { |
|
console.error(`Error processing ${file}:`, error); |
|
} |
|
}); |
|
|
|
|
|
configsList.sort((a, b) => a.name.localeCompare(b.name)); |
|
|
|
|
|
fs.writeFileSync(outputListFile, JSON.stringify(configsList, null, 2)); |
|
console.log(`Updated configs-list.json with ${configsList.length} configurations.`); |
|
|
|
|
|
if (endIndex < configFiles.length) { |
|
console.log(`\nTo process the next batch, run:`); |
|
const nextCommand = `node build.js ${endIndex} ${batchSize}`; |
|
console.log(nextCommand); |
|
|
|
|
|
fs.appendFileSync('build-output.txt', `To process the next batch, run:\n${nextCommand}\n`); |
|
} else { |
|
console.log(`\nAll files processed successfully!`); |
|
|
|
|
|
fs.appendFileSync('build-output.txt', `All files processed successfully!\n`); |
|
} |
|
|
|
|
|
function extractSection(content, startMarker, endMarker) { |
|
const startIndex = content.indexOf(startMarker); |
|
if (startIndex === -1) return ''; |
|
|
|
const startContentIndex = startIndex + startMarker.length; |
|
|
|
let endContentIndex; |
|
if (endMarker) { |
|
const endIndex = content.indexOf(endMarker, startContentIndex); |
|
endContentIndex = endIndex !== -1 ? endIndex : content.length; |
|
} else { |
|
endContentIndex = content.length; |
|
} |
|
|
|
return content.substring(startContentIndex, endContentIndex); |
|
} |
|
|
|
|
|
function findMatchingAvatar(filename, name, imageFiles) { |
|
|
|
const baseFilename = path.basename(filename, '.md'); |
|
|
|
|
|
const exactMatch = imageFiles.find(img => { |
|
const imgBase = path.basename(img, '.webp'); |
|
return imgBase.toLowerCase() === baseFilename.toLowerCase(); |
|
}); |
|
|
|
if (exactMatch) return exactMatch; |
|
|
|
|
|
const partialMatches = imageFiles.filter(img => { |
|
const imgBase = path.basename(img, '.webp').toLowerCase(); |
|
const filenameWords = baseFilename.toLowerCase().split(/[-_\s]+/); |
|
|
|
|
|
return filenameWords.some(word => |
|
word.length > 3 && imgBase.includes(word) |
|
); |
|
}); |
|
|
|
if (partialMatches.length > 0) { |
|
|
|
return partialMatches[0]; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
const keywordMappings = [ |
|
{ keywords: ['sloth', 'slow', 'lazy'], images: imageFiles.filter(img => img.includes('sloth')) }, |
|
{ keywords: ['tech', 'code', 'developer', 'programming'], images: imageFiles.filter(img => img.includes('laptop') || img.includes('computer')) }, |
|
{ keywords: ['android', 'robot', 'ai', 'assistant'], images: imageFiles.filter(img => img.includes('android') || img.includes('bot')) }, |
|
{ keywords: ['business', 'corporate', 'company'], images: imageFiles.filter(img => img.includes('business') || img.includes('corporate')) }, |
|
{ keywords: ['document', 'text', 'writing'], images: imageFiles.filter(img => img.includes('doc') || img.includes('text')) } |
|
]; |
|
|
|
for (const mapping of keywordMappings) { |
|
const matchesKeyword = mapping.keywords.some(keyword => |
|
baseFilename.toLowerCase().includes(keyword) || |
|
name.toLowerCase().includes(keyword) |
|
); |
|
|
|
if (matchesKeyword && mapping.images.length > 0) { |
|
|
|
return mapping.images[Math.floor(Math.random() * mapping.images.length)]; |
|
} |
|
} |
|
|
|
|
|
return imageFiles[Math.floor(Math.random() * imageFiles.length)]; |
|
} |