#!/usr/bin/env python3 """ Nexus Build Tool Build tool integration for the Three.js Nexus. Provides high-level functions for creating rooms, portals, lighting, and geometry with automatic code generation and validation. Functions: - create_room(name, description, style) - Generate room module - create_portal(from_room, to_room, style) - Generate portal connection - add_lighting(room, type, color, intensity) - Add lighting - add_geometry(room, shape, position, material) - Add 3D objects - generate_scene_from_mood(mood_description) - Mood-based generation - deploy_nexus_module(module_code, test=True) - Deploy and test Usage: from tools.nexus_build_tool import create_room, deploy_nexus_module # Create room room = create_room( name="zen_garden", description="Peaceful garden with floating stones", style="minimalist_ethereal" ) # Deploy result = deploy_nexus_module(room['code'], test=True) """ import json import logging import re import os import sys from typing import Dict, Any, List, Optional, Union from dataclasses import dataclass, field from datetime import datetime # Import from agent module (with fallback) sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) def _import_agent_modules(): """Lazy import agent modules to avoid circular dependencies.""" try: from agent.nexus_architect import ( get_architect as get_ai_architect, create_room as ai_create_room, create_portal as ai_create_portal, generate_scene_from_mood as ai_generate_scene, set_mental_state, NexusColors, MoodPresets, ) return ( get_ai_architect, ai_create_room, ai_create_portal, ai_generate_scene, set_mental_state, NexusColors, MoodPresets ) except ImportError: # Fallback: define minimal constants class FallbackColors: TIMMY_GOLD = "#D4AF37" ALLEGRO_BLUE = "#4A90E2" SOVEREIGNTY_CRYSTAL = "#E0F7FA" SERVICE_WARMTH = "#FFE4B5" class FallbackMoodPresets: CONTEMPLATIVE = {"lighting": "soft", "colors": ["#1A1A2E"]} def fallback_fn(*args, **kwargs): return {"success": False, "error": "Agent module not available"} return ( fallback_fn, fallback_fn, fallback_fn, fallback_fn, fallback_fn, FallbackColors, FallbackMoodPresets ) logger = logging.getLogger(__name__) # ============================================================================= # Build Tool Functions # ============================================================================= def create_room( name: str, description: str, style: str, dimensions: Optional[Dict[str, float]] = None ) -> Dict[str, Any]: """ Generate a room module from natural language description. Args: name: Room identifier (e.g., "contemplation_chamber") description: Natural language description of the room style: Visual style (minimalist_ethereal, crystalline_modern, etc.) dimensions: Optional dict with width, height, depth Returns: Dict containing: - success: bool - room_name: str - code: Generated Three.js code (when implemented with LLM) - prompt: LLM prompt for code generation - config: Room configuration - message: Status message """ # Use the AI architect to design the room _, ai_create_room, _, _, _, _, _ = _import_agent_modules() result = ai_create_room(name, description, style, dimensions) if not result.get("success"): return result # Add build-specific metadata result["build_metadata"] = { "tool": "nexus_build_tool", "function": "create_room", "timestamp": datetime.now().isoformat(), "version": "1.0.0", } # Generate template code (in production, this would come from LLM) result["template_code"] = _generate_room_template(result["design"]) return result def create_portal( from_room: str, to_room: str, name: Optional[str] = None, style: str = "energy_vortex" ) -> Dict[str, Any]: """ Generate a portal connection between rooms. Args: from_room: Source room identifier to_room: Target room identifier name: Optional portal name (auto-generated if not provided) style: Portal visual style (energy_vortex, circular_gate, etc.) Returns: Dict containing portal design and generation prompt """ if name is None: name = f"portal_{from_room}_to_{to_room}" _, _, ai_create_portal, _, _, _, _ = _import_agent_modules() result = ai_create_portal(name, from_room, to_room, style) if not result.get("success"): return result # Add build metadata result["build_metadata"] = { "tool": "nexus_build_tool", "function": "create_portal", "timestamp": datetime.now().isoformat(), "version": "1.0.0", } # Generate template code result["template_code"] = _generate_portal_template(result["design"]) return result def add_lighting( room: str, light_type: str, color: str = "#ffffff", intensity: float = 1.0, position: Optional[Dict[str, float]] = None, cast_shadow: bool = True ) -> Dict[str, Any]: """ Add lighting to a room. Args: room: Target room name light_type: Type of light (ambient, directional, point, spot, hemisphere) color: Light color (hex string) intensity: Light intensity (0.0 to 2.0) position: Optional position dict {x, y, z} cast_shadow: Whether to cast shadows Returns: Dict with lighting configuration and code """ valid_types = ["ambient", "directional", "point", "spot", "hemisphere"] if light_type.lower() not in valid_types: return { "success": False, "error": f"Invalid light type '{light_type}'. Valid: {valid_types}" } light_config = { "room": room, "type": light_type.lower(), "color": color, "intensity": intensity, "position": position or {"x": 0, "y": 5, "z": 0}, "cast_shadow": cast_shadow, } # Generate lighting code code = _generate_lighting_code(light_config) return { "success": True, "room": room, "light_config": light_config, "code": code, "message": f"Added {light_type} light to '{room}'", } def add_geometry( room: str, shape: str, position: Dict[str, float], material: Optional[Dict[str, Any]] = None, scale: Optional[Dict[str, float]] = None, rotation: Optional[Dict[str, float]] = None, name: Optional[str] = None ) -> Dict[str, Any]: """ Add 3D geometry to a room. Args: room: Target room name shape: Geometry type (box, sphere, cylinder, cone, torus, plane) position: Position dict {x, y, z} material: Material dict with color, roughness, metalness, etc. scale: Optional scale dict {x, y, z} rotation: Optional rotation dict {x, y, z} (in radians) name: Optional object name Returns: Dict with geometry configuration and code """ valid_shapes = ["box", "sphere", "cylinder", "cone", "torus", "plane", "ring"] if shape.lower() not in valid_shapes: return { "success": False, "error": f"Invalid shape '{shape}'. Valid: {valid_shapes}" } geo_config = { "room": room, "shape": shape.lower(), "position": position, "material": material or {"color": "#888888", "roughness": 0.5, "metalness": 0.0}, "scale": scale or {"x": 1, "y": 1, "z": 1}, "rotation": rotation or {"x": 0, "y": 0, "z": 0}, "name": name or f"{shape}_{room}_obj", } # Generate geometry code code = _generate_geometry_code(geo_config) return { "success": True, "room": room, "geometry_config": geo_config, "code": code, "message": f"Added {shape} to '{room}'", } def generate_scene_from_mood(mood_description: str) -> Dict[str, Any]: """ Generate a complete scene based on mood description. Args: mood_description: Description of desired mood/atmosphere Example: "Timmy is feeling introspective and seeking clarity" → Generates calm, minimalist space with clear sightlines Returns: Dict with scene design and generation prompt """ _, _, _, ai_generate_scene, _, _, _ = _import_agent_modules() result = ai_generate_scene(mood_description) if not result.get("success"): return result # Add build metadata result["build_metadata"] = { "tool": "nexus_build_tool", "function": "generate_scene_from_mood", "timestamp": datetime.now().isoformat(), "version": "1.0.0", } return result def deploy_nexus_module( module_code: str, test: bool = True, module_name: Optional[str] = None ) -> Dict[str, Any]: """ Deploy a Nexus module with optional testing. Args: module_code: The Three.js module code to deploy test: Whether to run validation tests before deployment module_name: Optional name for the module Returns: Dict with deployment results """ from tools.nexus_architect import validate_three_js_code results = { "success": True, "module_name": module_name or "unnamed_module", "timestamp": datetime.now().isoformat(), "validation": {}, "deployment": {}, } # Validation phase if test: validation_result = validate_three_js_code(module_code, strict_mode=True) results["validation"] = { "is_valid": validation_result.is_valid, "errors": validation_result.errors, "warnings": validation_result.warnings, "safety_score": max(0, 100 - len(validation_result.errors) * 20 - len(validation_result.warnings) * 5), } if not validation_result.is_valid: results["success"] = False results["message"] = "Deployment failed: Code validation errors" return results # Deployment phase (simulated - would integrate with actual deployment system) results["deployment"] = { "status": "deployed", "hot_reload_ready": True, "version": "1.0.0", "rollback_available": True, } results["message"] = f"Module '{results['module_name']}' deployed successfully" return results # ============================================================================= # Template Code Generators # ============================================================================= def _generate_room_template(design: Dict[str, Any]) -> str: """Generate a Three.js room template.""" name = design["name"] name_camel = ''.join(word.title() for word in name.split('_')) colors = design.get("color_palette", ["#1A1A2E", "#16213E"]) template = f'''// Nexus Room: {name} // Style: {design['style']} // Mood: {design['mood_preset']} (function() {{ 'use strict'; function create{name_camel}() {{ const room = new THREE.Group(); room.name = '{name}'; // Room dimensions const width = {design['dimensions']['width']}; const height = {design['dimensions']['height']}; const depth = {design['dimensions']['depth']}; // Floor const floorGeo = new THREE.PlaneGeometry(width, depth); const floorMat = new THREE.MeshStandardMaterial({{ color: '{colors[0]}', roughness: 0.8, metalness: 0.2 }}); const floor = new THREE.Mesh(floorGeo, floorMat); floor.rotation.x = -Math.PI / 2; floor.receiveShadow = true; room.add(floor); // Ambient lighting const ambientLight = new THREE.AmbientLight('{colors[0]}', 0.3); room.add(ambientLight); // Feature: {design['features'][0] if design['features'] else 'ambient glow'} // TODO: Add feature implementations based on design.features // Return room group return room; }} // Export if (typeof module !== 'undefined' && module.exports) {{ module.exports = {{ create{name_camel} }}; }} else if (typeof window !== 'undefined') {{ window.NexusRooms = window.NexusRooms || {{}}; window.NexusRooms.{name} = create{name_camel}; }} return {{ create{name_camel} }}; }})();''' return template def _generate_portal_template(design: Dict[str, Any]) -> str: """Generate a Three.js portal template.""" _, _, _, _, _, NexusColors, _ = _import_agent_modules() name = design["name"] name_camel = ''.join(word.title() for word in name.split('_')) from_room = design["from_room"] to_room = design["to_room"] template = f'''// Nexus Portal: {name} // Connection: {from_room} → {to_room} // Style: {design['style']} (function() {{ 'use strict'; function create{name_camel}() {{ const portal = new THREE.Group(); portal.name = '{name}'; portal.userData = {{ type: 'portal', fromRoom: '{from_room}', toRoom: '{to_room}', isActive: true }}; // Portal frame const frameGeo = new THREE.TorusGeometry(2, 0.2, 16, 100); const frameMat = new THREE.MeshStandardMaterial({{ color: '{NexusColors.TIMMY_GOLD}', emissive: '{NexusColors.TIMMY_GOLD}', emissiveIntensity: 0.5, roughness: 0.3, metalness: 0.8 }}); const frame = new THREE.Mesh(frameGeo, frameMat); frame.castShadow = true; portal.add(frame); // Portal energy field const fieldGeo = new THREE.CircleGeometry(1.8, 32); const fieldMat = new THREE.MeshBasicMaterial({{ color: '{NexusColors.ALLEGRO_BLUE}', transparent: true, opacity: 0.3, side: THREE.DoubleSide }}); const field = new THREE.Mesh(fieldGeo, fieldMat); portal.add(field); // Animation hook portal.userData.animate = function(time) {{ field.rotation.z = time * 0.5; const pulse = 1 + Math.sin(time * 2) * 0.1; field.scale.set(pulse, pulse, 1); }}; return portal; }} // Export if (typeof module !== 'undefined' && module.exports) {{ module.exports = {{ create{name_camel} }}; }} else if (typeof window !== 'undefined') {{ window.NexusPortals = window.NexusPortals || {{}}; window.NexusPortals.{name} = create{name_camel}; }} return {{ create{name_camel} }}; }})();''' return template def _generate_lighting_code(config: Dict[str, Any]) -> str: """Generate Three.js lighting code.""" light_type = config["type"] color = config["color"] intensity = config["intensity"] pos = config["position"] if light_type == "ambient": return f'''// Ambient Light for {config['room']} const {config['room']}Ambient = new THREE.AmbientLight('{color}', {intensity}); room.add({config['room']}Ambient);''' elif light_type == "directional": return f'''// Directional Light for {config['room']} const {config['room']}Dir = new THREE.DirectionalLight('{color}', {intensity}); {config['room']}Dir.position.set({pos['x']}, {pos['y']}, {pos['z']}); {config['room']}Dir.castShadow = {str(config['cast_shadow']).lower()}; room.add({config['room']}Dir);''' elif light_type == "point": return f'''// Point Light for {config['room']} const {config['room']}Point = new THREE.PointLight('{color}', {intensity}, 100); {config['room']}Point.position.set({pos['x']}, {pos['y']}, {pos['z']}); {config['room']}Point.castShadow = {str(config['cast_shadow']).lower()}; room.add({config['room']}Point);''' elif light_type == "spot": return f'''// Spot Light for {config['room']} const {config['room']}Spot = new THREE.SpotLight('{color}', {intensity}); {config['room']}Spot.position.set({pos['x']}, {pos['y']}, {pos['z']}); {config['room']}Spot.castShadow = {str(config['cast_shadow']).lower()}; {config['room']}Spot.angle = Math.PI / 6; {config['room']}Spot.penumbra = 0.2; room.add({config['room']}Spot);''' elif light_type == "hemisphere": return f'''// Hemisphere Light for {config['room']} const {config['room']}Hemi = new THREE.HemisphereLight('{color}', '#444444', {intensity}); room.add({config['room']}Hemi);''' return "// Unknown light type" def _generate_geometry_code(config: Dict[str, Any]) -> str: """Generate Three.js geometry code.""" shape = config["shape"] pos = config["position"] rot = config["rotation"] scale = config["scale"] mat = config["material"] name = config["name"] # Geometry mapping geo_map = { "box": "BoxGeometry(1, 1, 1)", "sphere": "SphereGeometry(0.5, 32, 32)", "cylinder": "CylinderGeometry(0.5, 0.5, 1, 32)", "cone": "ConeGeometry(0.5, 1, 32)", "torus": "TorusGeometry(0.5, 0.2, 16, 100)", "plane": "PlaneGeometry(1, 1)", "ring": "RingGeometry(0.3, 0.5, 32)", } geo_constructor = geo_map.get(shape, "BoxGeometry(1, 1, 1)") code = f'''// Geometry: {name} const {name}Geo = new THREE.{geo_constructor}; const {name}Mat = new THREE.MeshStandardMaterial({{ color: '{mat.get('color', '#888888')}', roughness: {mat.get('roughness', 0.5)}, metalness: {mat.get('metalness', 0.0)} }}); const {name} = new THREE.Mesh({name}Geo, {name}Mat); {name}.position.set({pos['x']}, {pos['y']}, {pos['z']}); {name}.rotation.set({rot['x']}, {rot['y']}, {rot['z']}); {name}.scale.set({scale['x']}, {scale['y']}, {scale['z']}); {name}.castShadow = true; {name}.receiveShadow = true; room.add({name});''' return code # ============================================================================= # Tool Schemas # ============================================================================= NEXUS_BUILD_TOOL_SCHEMAS = { "nexus_create_room": { "name": "nexus_create_room", "description": "Create a new 3D room in the Nexus from natural language description", "parameters": { "type": "object", "properties": { "name": {"type": "string"}, "description": {"type": "string"}, "style": {"type": "string"}, "dimensions": { "type": "object", "properties": { "width": {"type": "number"}, "height": {"type": "number"}, "depth": {"type": "number"}, } } }, "required": ["name", "description", "style"] } }, "nexus_create_portal": { "name": "nexus_create_portal", "description": "Create a portal connecting two rooms", "parameters": { "type": "object", "properties": { "from_room": {"type": "string"}, "to_room": {"type": "string"}, "name": {"type": "string"}, "style": {"type": "string", "default": "energy_vortex"}, }, "required": ["from_room", "to_room"] } }, "nexus_add_lighting": { "name": "nexus_add_lighting", "description": "Add lighting to a room", "parameters": { "type": "object", "properties": { "room": {"type": "string"}, "light_type": {"type": "string"}, "color": {"type": "string", "default": "#ffffff"}, "intensity": {"type": "number", "default": 1.0}, "position": { "type": "object", "properties": {"x": {"type": "number"}, "y": {"type": "number"}, "z": {"type": "number"}} }, "cast_shadow": {"type": "boolean", "default": True} }, "required": ["room", "light_type"] } }, "nexus_add_geometry": { "name": "nexus_add_geometry", "description": "Add 3D geometry to a room", "parameters": { "type": "object", "properties": { "room": {"type": "string"}, "shape": {"type": "string"}, "position": { "type": "object", "properties": {"x": {"type": "number"}, "y": {"type": "number"}, "z": {"type": "number"}} }, "material": {"type": "object"}, "scale": {"type": "object"}, "rotation": {"type": "object"}, "name": {"type": "string"} }, "required": ["room", "shape", "position"] } }, "nexus_generate_scene_from_mood": { "name": "nexus_generate_scene_from_mood", "description": "Generate a scene based on mood description", "parameters": { "type": "object", "properties": { "mood_description": {"type": "string"} }, "required": ["mood_description"] } }, "nexus_deploy_module": { "name": "nexus_deploy_module", "description": "Deploy a Nexus module with validation", "parameters": { "type": "object", "properties": { "module_code": {"type": "string"}, "test": {"type": "boolean", "default": True}, "module_name": {"type": "string"} }, "required": ["module_code"] } }, } if __name__ == "__main__": # Demo print("Nexus Build Tool - Demo") print("=" * 50) # Import NexusColors for demo _, _, _, _, _, NexusColors, _ = _import_agent_modules() # Create a room result = create_room( name="zen_garden", description="Peaceful garden with floating stones and soft light", style="minimalist_ethereal" ) print(f"\nRoom created: {result['room_name']}") print(f"Mood: {result['design']['mood_preset']}") # Add lighting result = add_lighting( room="zen_garden", light_type="point", color=NexusColors.TIMMY_GOLD, intensity=0.8, position={"x": 0, "y": 5, "z": 0} ) print(f"\nLighting added: {result['light_config']['type']}") # Add geometry result = add_geometry( room="zen_garden", shape="sphere", position={"x": 0, "y": 2, "z": 0}, material={"color": NexusColors.ALLEGRO_BLUE, "roughness": 0.2}, name="floating_orb" ) print(f"\nGeometry added: {result['geometry_config']['shape']}")