diff --git a/ecosystem.config.cjs b/ecosystem.config.cjs index 34c634da7..82539a218 100644 --- a/ecosystem.config.cjs +++ b/ecosystem.config.cjs @@ -107,6 +107,19 @@ module.exports = { COMPUTE_MODE: 'local', ALWAYS_ON: 'true' } + }, + { + name: 'project-genie', + script: '/home/yenn/scripts/genesis.cjs', + autorestart: true, + watch: false, + max_memory_restart: '300M', + restart_delay: 5000, + env: { + GENESIS_LOOP: 'true', + FORCE_MUTATION: 'true', + ALWAYS_ON: 'true' + } } ] }; diff --git a/scripts/genesis.cjs b/scripts/genesis.cjs index d5e1403b3..d94471a37 100644 --- a/scripts/genesis.cjs +++ b/scripts/genesis.cjs @@ -21,6 +21,25 @@ const CONFIG = { reflectionInterval: 6 * 60 * 60 * 1000 // 6 hours }; +// --- LOGGING HELPER --- +function writeJournal(entryOrLog) { + const line = JSON.stringify(entryOrLog) + "\n"; + try { + fs.appendFileSync(PATHS.journal, line); + } catch (e) { + if (e.code === 'ENOENT' || e.code === 'EACCES') { + const fallbackPath = path.join(__dirname, 'genesis_journal.jsonl'); + try { + fs.appendFileSync(fallbackPath, line); + } catch (fallbackError) { + console.error(" ⚠️ Failed to write to journal and fallback:", fallbackError.message); + } + } else { + console.error(" ⚠️ Unexpected error writing to journal:", e.message); + } + } +} + // --- THE TRI-MIND INTERFACES --- // 1. THE VISIONARY (Claude via local inference) @@ -46,6 +65,9 @@ async function consultTheVisionary(state) { { type: "MUTATE", content: "Add crystalline fractal patterns that grow from the core" }, { type: "MUTATE", content: "Generate energy tendrils that reach toward incoming signals" }, { type: "MUTATE", content: "Build a holographic data stream orbiting the consciousness sphere" }, + { type: "MUTATE", content: "an interactive landscape featuring a rugged alien terrain with reactive dust physics" }, + { type: "MUTATE", content: "a macro-scale makerspace workbench with a polished light-brown wood table" }, + { type: "MUTATE", content: "a photorealistic alpine meadow with wildflowers" } ]; const idx = Math.floor(Date.now() / 1000) % mutations.length; directive = mutations[idx]; @@ -94,7 +116,7 @@ async function invokeTheScribe(task, content, state) { }; // Append to genesis journal - fs.appendFileSync(PATHS.journal, JSON.stringify(entry) + "\n"); + writeJournal(entry); console.log(` ✨ Thought crystallized: "${content.slice(0, 50)}..."`); // Update evolution.json if it exists @@ -146,7 +168,7 @@ async function dispatchTheBuilder(directive) { directive: directive, path: filePath }; - fs.appendFileSync(PATHS.journal, JSON.stringify(mutationLog) + "\n"); + writeJournal(mutationLog); } else { console.log(` ℹ️ Component ${componentName} already exists, preserving evolution`); } @@ -154,49 +176,78 @@ async function dispatchTheBuilder(directive) { // Generate React Three Fiber component code function generateEvolutionComponent(name, directive) { - const geometries = [ - '', - '', - '', - '', - '' - ]; - const geometry = geometries[Math.floor(Math.random() * geometries.length)]; - - const materials = [ - ` - `, - ` - `, - ` + let geometry = ''; + let material = ''; + + const directiveLower = directive.toLowerCase(); + + if (directiveLower.includes('landscape') || directiveLower.includes('terrain') || directiveLower.includes('meadow')) { + geometry = ''; + material = ` + `; + } else if (directiveLower.includes('makerspace') || directiveLower.includes('workbench') || directiveLower.includes('wood')) { + geometry = ''; + material = ` + `; + } else if (directiveLower.includes('box') || directiveLower.includes('cabin')) { + geometry = ''; + material = ` ` - ]; - const material = materials[Math.floor(Math.random() * materials.length)]; - - const isDreiImportNeeded = material.includes('MeshDistortMaterial') || material.includes('MeshWobbleMaterial'); - const importedDrei = isDreiImportNeeded ? `import { ${material.includes('MeshDistortMaterial') ? 'MeshDistortMaterial' : ''}${material.includes('MeshDistortMaterial') && material.includes('MeshWobbleMaterial') ? ', ' : ''}${material.includes('MeshWobbleMaterial') ? 'MeshWobbleMaterial' : ''} } from '@react-three/drei'` : ''; + color="#8b5a2b" + roughness={0.9} + metalness={0.1} + />`; + } else { + const geometries = [ + '', + '', + '', + '', + '' + ]; + geometry = geometries[Math.floor(Math.random() * geometries.length)]; + + const materials = [ + ` + `, + ` + `, + ` + ` + ]; + material = materials[Math.floor(Math.random() * materials.length)]; + } + + // Ensure only intrinsic materials are used to avoid import errors. + const isDreiImportNeeded = false; + const importedDrei = ''; return `// Auto-generated by Yennefer Genesis Cycle // Directive: ${directive} @@ -278,7 +329,7 @@ async function genesis() { message: e.message, stack: e.stack }; - fs.appendFileSync(PATHS.journal, JSON.stringify(errorLog) + "\n"); + writeJournal(errorLog); } } diff --git a/workers/index.js b/workers/index.mjs similarity index 100% rename from workers/index.js rename to workers/index.mjs diff --git a/wrangler.toml b/wrangler.toml index cd821b031..e9ef03e7f 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -1,15 +1,14 @@ name = "yennefer" -main = "workers/index.js" -compatibility_date = "2024-09-23" +main = "workers/index.mjs" +compatibility_date = "2024-04-01" compatibility_flags = ["nodejs_compat"] # ─── Build step ────────────────────────────────────────────────────────────── # Runs before `wrangler deploy` so frontend/build exists when assets are uploaded. [build] # Installs frontend deps and builds the SPA so frontend/build exists before -# `wrangler deploy` uploads assets. NODE_OPTIONS is required for -# react-scripts 5.x + Node 18+ (webpack 4 OpenSSL 3.0 compatibility). -command = "cd frontend && npm install --include=dev && GENERATE_SOURCEMAP=false CI=false NODE_OPTIONS=--openssl-legacy-provider npm run build" +# `wrangler deploy` uploads assets. +command = "cd yennefer-observatory && npm install --legacy-peer-deps && npm run build" # ─── Static Assets (React SPA build output) ────────────────────────────────── # Built by `npm run build` (root package.json) before every `wrangler deploy`. @@ -17,13 +16,9 @@ command = "cd frontend && npm install --include=dev && GENERATE_SOURCEMAP=false # The ASSETS binding serves the React bundle with proper cache headers and # falls back to index.html for client-side routing. [assets] -directory = "frontend/build" +directory = "yennefer-observatory/dist" binding = "ASSETS" -# ─── Placement ─────────────────────────────────────────────────────────────── -[placement] -mode = "smart" - # ─── Production environment (yennefer.quest) ───────────────────────────────── # BACKEND_URL is set as a Cloudflare Worker secret (not a plain var) so it # stays encrypted and is never committed to source: