Compare commits

..

1 Commits

Author SHA1 Message Date
Alexander Whitestone
4706861619 fix: closes #1208
Some checks failed
CI / test (pull_request) Failing after 10s
CI / validate (pull_request) Failing after 17s
Review Approval Gate / verify-review (pull_request) Failing after 3s
2026-04-12 12:18:58 -04:00
4 changed files with 48 additions and 35 deletions

6
app.js
View File

@@ -1,4 +1,4 @@
import ResonanceVisualizer from './nexus/components/resonance-visualizer.js';\nimport * as THREE from 'three'; import * as THREE from 'three';
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js'; import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js'; import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js'; import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';
@@ -597,7 +597,7 @@ class PSELayer {
let pseLayer; let pseLayer;
let resonanceViz, metaLayer, neuroBridge, cbr, symbolicPlanner, knowledgeGraph, blackboard, symbolicEngine, calibrator; let metaLayer, neuroBridge, cbr, symbolicPlanner, knowledgeGraph, blackboard, symbolicEngine, calibrator;
let agentFSMs = {}; let agentFSMs = {};
function setupGOFAI() { function setupGOFAI() {
@@ -666,7 +666,7 @@ async function init() {
scene = new THREE.Scene(); scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x050510, 0.012); scene.fog = new THREE.FogExp2(0x050510, 0.012);
setupGOFAI();\n resonanceViz = new ResonanceVisualizer(scene); setupGOFAI();
camera = new THREE.PerspectiveCamera(65, window.innerWidth / window.innerHeight, 0.1, 1000); camera = new THREE.PerspectiveCamera(65, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.copy(playerPos); camera.position.copy(playerPos);

View File

@@ -815,6 +815,42 @@ const SpatialMemory = (() => {
return results.slice(0, maxResults); return results.slice(0, maxResults);
} }
// ─── CONTENT SEARCH ─────────────────────────────────
/**
* Search memories by text content — case-insensitive substring match.
* @param {string} query - Search text
* @param {object} [options] - Optional filters
* @param {string} [options.category] - Restrict to a specific region
* @param {number} [options.maxResults=20] - Cap results
* @returns {Array<{memory: object, score: number, position: THREE.Vector3}>}
*/
function searchByContent(query, options = {}) {
if (!query || !query.trim()) return [];
const { category, maxResults = 20 } = options;
const needle = query.trim().toLowerCase();
const results = [];
Object.values(_memoryObjects).forEach(obj => {
if (category && obj.region !== category) return;
const content = (obj.data.content || '').toLowerCase();
if (!content.includes(needle)) return;
// Score: number of occurrences + strength bonus
let matches = 0, idx = 0;
while ((idx = content.indexOf(needle, idx)) !== -1) { matches++; idx += needle.length; }
const score = matches + (obj.mesh.userData.strength || 0.7);
results.push({
memory: obj.data,
score,
position: obj.mesh.position.clone()
});
});
results.sort((a, b) => b.score - a.score);
return results.slice(0, maxResults);
}
// ─── CRYSTAL MESH COLLECTION (for raycasting) ──────── // ─── CRYSTAL MESH COLLECTION (for raycasting) ────────
function getCrystalMeshes() { function getCrystalMeshes() {
@@ -864,7 +900,7 @@ const SpatialMemory = (() => {
init, placeMemory, removeMemory, update, importMemories, updateMemory, init, placeMemory, removeMemory, update, importMemories, updateMemory,
getMemoryAtPosition, getRegionAtPosition, getMemoriesInRegion, getAllMemories, getMemoryAtPosition, getRegionAtPosition, getMemoriesInRegion, getAllMemories,
getCrystalMeshes, getMemoryFromMesh, highlightMemory, clearHighlight, getSelectedId, getCrystalMeshes, getMemoryFromMesh, highlightMemory, clearHighlight, getSelectedId,
exportIndex, importIndex, searchNearby, REGIONS, exportIndex, importIndex, searchNearby, searchByContent, REGIONS,
saveToStorage, loadFromStorage, clearStorage, saveToStorage, loadFromStorage, clearStorage,
runGravityLayout, setCamera runGravityLayout, setCamera
}; };

View File

@@ -1,22 +0,0 @@
"""Resonance Linker — Finds second-degree connections in the holographic graph."""
class ResonanceLinker:
def __init__(self, archive):
self.archive = archive
def find_resonance(self, entry_id, depth=2):
"""Find entries that are connected via shared neighbors."""
if entry_id not in self.archive._entries: return []
entry = self.archive._entries[entry_id]
neighbors = set(entry.links)
resonance = {}
for neighbor_id in neighbors:
if neighbor_id in self.archive._entries:
for second_neighbor in self.archive._entries[neighbor_id].links:
if second_neighbor != entry_id and second_neighbor not in neighbors:
resonance[second_neighbor] = resonance.get(second_neighbor, 0) + 1
return sorted(resonance.items(), key=lambda x: x[1], reverse=True)

View File

@@ -52,20 +52,19 @@ async def broadcast_handler(websocket: websockets.WebSocketServerProtocol):
continue continue
disconnected = set() disconnected = set()
# Create broadcast tasks, tracking which client each task targets # Create broadcast tasks for efficiency
task_client_pairs = [] tasks = []
for client in clients: for client in clients:
if client != websocket and client.open: if client != websocket and client.open:
task = asyncio.create_task(client.send(message)) tasks.append(asyncio.create_task(client.send(message)))
task_client_pairs.append((task, client))
if tasks:
if task_client_pairs:
tasks = [pair[0] for pair in task_client_pairs]
results = await asyncio.gather(*tasks, return_exceptions=True) results = await asyncio.gather(*tasks, return_exceptions=True)
for i, result in enumerate(results): for i, result in enumerate(results):
if isinstance(result, Exception): if isinstance(result, Exception):
target_client = task_client_pairs[i][1] # Find the client that failed
logger.error(f"Failed to send to client {target_client.remote_address}: {result}") target_client = [c for c in clients if c != websocket][i]
logger.error(f"Failed to send to a client {target_client.remote_address}: {result}")
disconnected.add(target_client) disconnected.add(target_client)
if disconnected: if disconnected: