God Mode Valhalla: Initial Standalone Commit

This commit is contained in:
cawcenter
2025-12-14 19:19:14 -05:00
commit 153102b23e
127 changed files with 30781 additions and 0 deletions

View File

@@ -0,0 +1,214 @@
// @ts-nocheck
import { SpintaxParser } from './SpintaxParser';
import { GrammarEngine } from './GrammarEngine';
import { HTMLRenderer } from './HTMLRenderer';
import { createDirectus, rest, staticToken, readItems, readItem } from '@directus/sdk';
// Config
// In a real app, client should be passed in or singleton
// For this class, we assume data is passed in or we have a method to fetch it.
export interface GenerationContext {
avatar: any;
niche: string;
city: any;
site: any;
template: any;
}
export class CartesianEngine {
private client: any;
constructor(directusClient: any) {
this.client = directusClient;
}
/**
* Generate a single article based on specific inputs.
* @param overrides Optional overrides for slug, title, etc.
*/
async generateArticle(context: GenerationContext, overrides?: any) {
const { avatar, niche, city, site, template } = context;
const variant = await this.getAvatarVariant(avatar.id, 'neutral'); // Default to neutral or specific
// 1. Process Template Blocks
const blocksData = [];
// Parse structure_json (assuming array of block IDs)
const blockIds = Array.isArray(template.structure_json) ? template.structure_json : [];
for (const blockId of blockIds) {
// Fetch Universal Block
// In production, fetch specific fields to optimize
let universal: any = {};
try {
// Assuming blockId is the ID in offer_blocks_universal (or key)
// Since we stored them as items, we query by block_id field or id
const result = await this.client.request(readItems('offer_blocks_universal' as any, {
filter: { block_id: { _eq: blockId } },
limit: 1
}));
universal = result[0] || {};
} catch (e) { console.error(`Block not found: ${blockId}`); }
// Fetch Personalized Expansion (Skipped for MVP)
// MERGE
const mergedBlock = {
id: blockId,
title: universal.title,
hook: universal.hook_generator,
pains: universal.universal_pains || [],
solutions: universal.universal_solutions || [],
value_points: universal.universal_value_points || [],
cta: universal.cta_spintax,
spintax: universal.spintax_content // Assuming a new field for full block spintax
};
// 2. Resolve Tokens Per Block
const solvedBlock = this.resolveBlock(mergedBlock, context, variant);
blocksData.push(solvedBlock);
}
// 3. Assemble HTML
const html = HTMLRenderer.renderArticle(blocksData);
// 4. Generate Meta
const metaTitle = overrides?.title || this.generateMetaTitle(context, variant);
return {
title: metaTitle,
html_content: html,
slug: overrides?.slug || this.generateSlug(metaTitle),
meta_desc: "Generated description..." // Implementation TBD
};
}
private resolveBlock(block: any, ctx: GenerationContext, variant: any): any {
const resolve = (text: string) => {
if (!text) return '';
let t = text;
// Level 1: Variables
t = t.replace(/{{NICHE}}/g, ctx.niche || 'Business');
t = t.replace(/{{CITY}}/g, ctx.city.city);
t = t.replace(/{{STATE}}/g, ctx.city.state);
t = t.replace(/{{ZIP_FOCUS}}/g, ctx.city.zip_focus || '');
t = t.replace(/{{AGENCY_NAME}}/g, "Spark Agency"); // Config
t = t.replace(/{{AGENCY_URL}}/g, ctx.site.url);
// Level 2: Spintax
t = SpintaxParser.parse(t);
// Level 3: Grammar
t = GrammarEngine.resolve(t, variant);
return t;
};
const resolvedBlock: any = {
id: block.id,
title: resolve(block.title),
hook: resolve(block.hook),
pains: (block.pains || []).map(resolve),
solutions: (block.solutions || []).map(resolve),
value_points: (block.value_points || []).map(resolve),
cta: resolve(block.cta)
};
// Handle Spintax Content & Components
if (block.spintax) {
let content = SpintaxParser.parse(block.spintax);
// Dynamic Component Replacement
if (content.includes('{{COMPONENT_AVATAR_GRID}}')) {
content = content.replace('{{COMPONENT_AVATAR_GRID}}', this.generateAvatarGrid());
}
if (content.includes('{{COMPONENT_OPTIN_FORM}}')) {
content = content.replace('{{COMPONENT_OPTIN_FORM}}', this.generateOptinForm());
}
content = GrammarEngine.resolve(content, variant);
resolvedBlock.content = content;
}
return resolvedBlock;
}
private generateAvatarGrid(): string {
const avatars = [
"Scaling Founder", "Marketing Director", "Ecom Owner", "SaaS CEO", "Local Biz Owner",
"Real Estate Agent", "Coach/Consultant", "Agency Owner", "Startup CTO", "Enterprise VP"
];
let html = '<div class="grid grid-cols-2 md:grid-cols-5 gap-4 my-8">';
avatars.forEach(a => {
html += `
<div class="p-4 border border-slate-700 rounded-lg text-center bg-slate-800">
<div class="w-12 h-12 bg-blue-600/20 rounded-full mx-auto mb-2 flex items-center justify-center text-blue-400 font-bold">
${a[0]}
</div>
<div class="text-xs font-medium text-white">${a}</div>
</div>
`;
});
html += '</div>';
return html;
}
private generateOptinForm(): string {
return `
<div class="bg-blue-900/20 border border-blue-800 p-8 rounded-xl my-8 text-center">
<h3 class="text-2xl font-bold text-white mb-4">Book Your Strategy Session</h3>
<p class="text-slate-400 mb-6">Stop guessing. Get a custom roadmap consisting of the exact systems we used to scale.</p>
<form class="max-w-md mx-auto space-y-4">
<input type="email" placeholder="Enter your work email" class="w-full p-3 bg-slate-900 border border-slate-700 rounded-lg text-white" />
<button type="button" class="w-full bg-blue-600 hover:bg-blue-500 text-white font-bold py-3 rounded-lg transition-colors">
Get My Roadmap
</button>
<p class="text-xs text-slate-500">No spam. Unsubscribe anytime.</p>
</form>
</div>
`;
}
private generateMetaTitle(ctx: GenerationContext, variant: any): string {
// Simple random pattern selection for now
// In reality, this should come from "cartesian_patterns" loaded in context
// But for robust fail-safe:
const patterns = [
`Top Rated ${ctx.niche} Company in ${ctx.city.city}`,
`${ctx.city.city} ${ctx.niche} Experts - ${ctx.site.name || 'Official Site'}`,
`The #1 ${ctx.niche} Service in ${ctx.city.city}, ${ctx.city.state}`,
`Best ${ctx.niche} Agency Serving ${ctx.city.city}`
];
const raw = patterns[Math.floor(Math.random() * patterns.length)];
return raw;
}
private generateSlug(title: string): string {
return title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '');
}
private async getAvatarVariant(avatarId: string, gender: string) {
// Try to fetch from Directus "avatar_variants"
// If fail, return default neutral
try {
// We assume variants are stored in a singleton or we query by avatar
// Since we don't have the ID handy, we return a safe default for this MVP test
// to ensure it works without complex relation queries right now.
// The GrammarEngine handles defaults if keys are missing.
return {
pronoun: 'they',
ppronoun: 'them',
pospronoun: 'their',
isare: 'are',
has_have: 'have',
does_do: 'do'
};
} catch (e) {
return {};
}
}
}

View File

@@ -0,0 +1,49 @@
/**
* GrammarEngine
* Resolves grammar tokens like [[PRONOUN]], [[ISARE]] based on avatar variants.
*/
export class GrammarEngine {
/**
* Resolve grammar tokens in text.
* @param text Text containing [[TOKEN]] syntax
* @param variant The avatar variant object (e.g. { pronoun: "he", isare: "is" })
* @param variables Optional extra variables for function tokens like [[A_AN:{{NICHE}}]]
*/
static resolve(text: string, variant: Record<string, string>): string {
if (!text) return '';
let resolved = text;
// 1. Simple replacement from variant map
// Matches [[KEY]]
resolved = resolved.replace(/\[\[([A-Z_]+)\]\]/g, (match, key) => {
const lowerKey = key.toLowerCase();
if (variant[lowerKey]) {
return variant[lowerKey];
}
return match; // Return original if not found
});
// 2. Handling A/An logic: [[A_AN:Word]]
resolved = resolved.replace(/\[\[A_AN:(.*?)\]\]/g, (match, content) => {
return GrammarEngine.a_an(content);
});
// 3. Capitalization: [[CAP:word]]
resolved = resolved.replace(/\[\[CAP:(.*?)\]\]/g, (match, content) => {
return content.charAt(0).toUpperCase() + content.slice(1);
});
return resolved;
}
static a_an(word: string): string {
const vowels = ['a', 'e', 'i', 'o', 'u'];
const firstChar = word.trim().charAt(0).toLowerCase();
// Simple heuristic
if (vowels.includes(firstChar)) {
return `an ${word}`;
}
return `a ${word}`;
}
}

View File

@@ -0,0 +1,60 @@
/**
* HTMLRenderer (Assembler)
* Wraps raw content blocks in formatted HTML.
*/
export class HTMLRenderer {
/**
* Render a full article from blocks.
* @param blocks Array of processed content blocks objects
* @returns Full HTML string
*/
static renderArticle(blocks: any[]): string {
return blocks.map(block => this.renderBlock(block)).join('\n\n');
}
/**
* Render a single block based on its structure.
*/
static renderBlock(block: any): string {
let html = '';
// Title
if (block.title) {
html += `<h2>${block.title}</h2>\n`;
}
// Hook
if (block.hook) {
html += `<p class="lead"><strong>${block.hook}</strong></p>\n`;
}
// Pains (Unordered List)
if (block.pains && block.pains.length > 0) {
html += `<ul>\n${block.pains.map((p: string) => ` <li>${p}</li>`).join('\n')}\n</ul>\n`;
}
// Solutions (Paragraphs or Ordered List)
if (block.solutions && block.solutions.length > 0) {
// Configurable, defaulting to paragraphs for flow
html += block.solutions.map((s: string) => `<p>${s}</p>`).join('\n') + '\n';
}
// Value Points (Checkmark List style usually)
if (block.value_points && block.value_points.length > 0) {
html += `<ul class="value-points">\n${block.value_points.map((v: string) => ` <li>✅ ${v}</li>`).join('\n')}\n</ul>\n`;
}
// Raw Content (from Spintax/Components)
if (block.content) {
html += `<div class="block-content">\n${block.content}\n</div>\n`;
}
// CTA
if (block.cta) {
html += `<div class="cta-box"><p>${block.cta}</p></div>\n`;
}
return `<section class="content-block" id="${block.id || ''}">\n${html}</section>`;
}
}

View File

@@ -0,0 +1,15 @@
/**
* MetadataGenerator
* Auto-generates SEO titles and descriptions.
*/
export class MetadataGenerator {
static generateTitle(niche: string, city: string, state: string): string {
// Simple formula for now - can be expanded to use patterns
return `Top ${niche} Services in ${city}, ${state} | Verified Experts`;
}
static generateDescription(niche: string, city: string): string {
return `Looking for the best ${niche} in ${city}? We provide top-rated solutions tailored for your business needs. Get a free consultation today.`;
}
}

View File

@@ -0,0 +1,42 @@
/**
* SpintaxParser
* Handles recursive parsing of {option1|option2} syntax.
*/
export class SpintaxParser {
/**
* Parse a string containing spintax.
* Supports nested spintax like {Hi|Hello {World|Friend}}
* @param text The text with spintax
* @returns The parsed text with one option selected per block
*/
static parse(text: string): string {
if (!text) return '';
// Regex to find the innermost spintax block: {([^{}]*)}
// We execute this recursively until no braces remain.
let parsed = text;
const regex = /\{([^{}]+)\}/g;
while (regex.test(parsed)) {
parsed = parsed.replace(regex, (match, content) => {
const options = content.split('|');
const randomOption = options[Math.floor(Math.random() * options.length)];
return randomOption;
});
}
return parsed;
}
/**
* Count total variations in a spintax string.
* (Simplified estimate for preview calculator)
*/
static countVariations(text: string): number {
// Basic implementation for complexity estimation
// Real count requiring parsing tree is complex,
// this is a placeholder if needed for UI later.
return 1;
}
}

View File

@@ -0,0 +1,33 @@
import module from 'node:crypto';
const { createHash } = module;
/**
* UniquenessManager
* Handles content hashing to prevent duplicate generation.
*/
export class UniquenessManager {
/**
* Generate a unique hash for a specific combination.
* Format: {SiteID}_{AvatarID}_{Niche}_{City}_{PatternID}
*/
static generateHash(siteId: string, avatarId: string, niche: string, city: string, patternId: string): string {
const raw = `${siteId}_${avatarId}_${niche}_${city}_${patternId}`;
return createHash('md5').update(raw).digest('hex');
}
/**
* Check if a hash already exists in the database.
* (Placeholder logic - real implementation queries Directus)
*/
static async checkExists(client: any, hash: string): Promise<boolean> {
try {
// This would be a Directus query
// const res = await client.request(readItems('generated_articles', { filter: { generation_hash: { _eq: hash } }, limit: 1 }));
// return res.length > 0;
return false; // For now
} catch (e) {
return false;
}
}
}