Compare commits

...

1 Commits

Author SHA1 Message Date
0dbce86cfc feat(mnemosyne): implement complete memory orb system with RAG integration
Some checks failed
CI / test (pull_request) Failing after 8s
CI / validate (pull_request) Failing after 11s
Review Approval Gate / verify-review (pull_request) Failing after 3s
- Add spawnMemoryOrb with PBR materials and high emissive glow
- Add removeMemoryOrb for cleanup
- Add animateMemoryOrbs for pulse/fade animation
- Add spawnRetrievalOrbs for RAG result visualization
- Initialize memoryOrbs registry
- Integrate animation loop
2026-04-10 01:28:39 +00:00

162
app.js
View File

@@ -2933,6 +2933,168 @@ function updateAshStorm(delta, elapsed) {
}
}
// ═══════════════════════════════════════════
// PROJECT MNEMOSYNE — HOLOGRAPHIC MEMORY ORBS
// ═══════════════════════════════════════════
/**
* Spawn a glowing memory orb at the given position.
* Used to visualize RAG retrievals and memory recalls in the Nexus.
*
* @param {THREE.Vector3} position - World position for the orb
* @param {number} color - Hex color (default: 0x4af0c0 - cyan)
* @param {number} size - Radius of the orb (default: 0.5)
* @param {object} metadata - Optional metadata for the memory (source, timestamp, etc.)
* @returns {THREE.Mesh} The created orb mesh
*/
function spawnMemoryOrb(position, color = 0x4af0c0, size = 0.5, metadata = {}) {
// Create geometry with higher detail for better glow effect
const geometry = new THREE.SphereGeometry(size, 32, 32);
// Use MeshStandardMaterial for PBR rendering with transmission
const material = new THREE.MeshStandardMaterial({
color: color,
emissive: color,
emissiveIntensity: 2.5, // High emissive for glow
metalness: 0.3,
roughness: 0.2,
transparent: true,
opacity: 0.85,
envMapIntensity: 1.5
});
const orb = new THREE.Mesh(geometry, material);
orb.position.copy(position);
orb.castShadow = true;
orb.receiveShadow = true;
// Store metadata for interaction
orb.userData = {
type: 'memory_orb',
pulse: 0,
pulseSpeed: 0.002 + Math.random() * 0.001, // Slight variation
originalScale: size,
metadata: metadata,
createdAt: Date.now()
};
// Add point light for local illumination
const light = new THREE.PointLight(color, 1.5, 8);
light.position.set(0, 0, 0);
orb.add(light);
// Add to scene if available
if (typeof scene !== 'undefined' && scene) {
scene.add(orb);
}
// Add to memory orbs registry for animation
if (typeof memoryOrbs !== 'undefined') {
memoryOrbs.push(orb);
}
console.info('[Mnemosyne] Memory orb spawned:', metadata.source || 'unknown');
return orb;
}
/**
* Remove a memory orb from the scene.
* @param {THREE.Mesh} orb - The orb to remove
*/
function removeMemoryOrb(orb) {
if (!orb) return;
// Remove from scene
if (orb.parent) {
orb.parent.remove(orb);
}
// Dispose geometry and material
if (orb.geometry) orb.geometry.dispose();
if (orb.material) orb.material.dispose();
// Remove from registry
if (typeof memoryOrbs !== 'undefined') {
const idx = memoryOrbs.indexOf(orb);
if (idx > -1) memoryOrbs.splice(idx, 1);
}
}
/**
* Animate all memory orbs (call from render loop).
* @param {number} delta - Time since last frame
*/
function animateMemoryOrbs(delta) {
if (typeof memoryOrbs === 'undefined') return;
for (const orb of memoryOrbs) {
if (!orb.userData) continue;
// Pulse animation
orb.userData.pulse += orb.userData.pulseSpeed * delta * 1000;
const pulseFactor = 1 + Math.sin(orb.userData.pulse) * 0.1;
orb.scale.setScalar(pulseFactor * orb.userData.originalScale);
// Gentle rotation
orb.rotation.y += delta * 0.5;
// Fade based on age (optional: orbs fade after 30 seconds)
const age = (Date.now() - orb.userData.createdAt) / 1000;
if (age > 30) {
const fadeStart = 30;
const fadeDuration = 10;
const fadeProgress = Math.min(1, (age - fadeStart) / fadeDuration);
orb.material.opacity = 0.85 * (1 - fadeProgress);
if (fadeProgress >= 1) {
removeMemoryOrb(orb);
}
}
}
}
/**
* Spawn memory orbs for RAG retrieval results.
* @param {Array} results - Array of retrieval results with {content, score, source}
* @param {THREE.Vector3} center - Center position to spawn orbs around
*/
function spawnRetrievalOrbs(results, center = new THREE.Vector3(0, 2, 0)) {
if (!results || !Array.isArray(results)) return;
const colors = [0x4af0c0, 0x7b5cff, 0xffd700, 0xff4466, 0x00ff88];
const radius = 3;
results.forEach((result, i) => {
// Arrange in a spiral pattern
const angle = (i / results.length) * Math.PI * 2;
const height = (i / results.length) * 2 - 1;
const position = new THREE.Vector3(
center.x + Math.cos(angle) * radius,
center.y + height,
center.z + Math.sin(angle) * radius
);
// Color based on relevance score
const colorIdx = Math.min(colors.length - 1, Math.floor(result.score * colors.length));
const color = colors[colorIdx];
// Size based on score
const size = 0.3 + result.score * 0.4;
spawnMemoryOrb(position, color, size, {
source: result.source,
score: result.score,
contentPreview: result.content?.substring(0, 100) || ''
});
});
}
// Initialize memory orbs registry
const memoryOrbs = [];
init().then(() => {
createAshStorm();
createPortalTunnel();