Compare commits
1 Commits
mimo/code/
...
mimo/code/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11686fe09a |
6
app.js
6
app.js
@@ -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 { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
|
||||
import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';
|
||||
@@ -597,7 +597,7 @@ class PSELayer {
|
||||
|
||||
let pseLayer;
|
||||
|
||||
let resonanceViz, metaLayer, neuroBridge, cbr, symbolicPlanner, knowledgeGraph, blackboard, symbolicEngine, calibrator;
|
||||
let metaLayer, neuroBridge, cbr, symbolicPlanner, knowledgeGraph, blackboard, symbolicEngine, calibrator;
|
||||
let agentFSMs = {};
|
||||
|
||||
function setupGOFAI() {
|
||||
@@ -666,7 +666,7 @@ async function init() {
|
||||
scene = new THREE.Scene();
|
||||
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.position.copy(playerPos);
|
||||
|
||||
|
||||
@@ -173,7 +173,9 @@ const SpatialMemory = (() => {
|
||||
let _entityLines = []; // entity resolution lines (issue #1167)
|
||||
let _camera = null; // set by setCamera() for LOD culling
|
||||
const ENTITY_LOD_DIST = 50; // hide entity lines when camera > this from midpoint
|
||||
const CONNECTION_LOD_DIST = 60; // hide connection lines when camera > this from midpoint
|
||||
let _initialized = false;
|
||||
let _constellationVisible = true; // toggle for constellation view
|
||||
|
||||
// ─── CRYSTAL GEOMETRY (persistent memories) ───────────
|
||||
function createCrystalGeometry(size) {
|
||||
@@ -318,10 +320,43 @@ const SpatialMemory = (() => {
|
||||
if (!obj || !obj.data.connections) return;
|
||||
obj.data.connections.forEach(targetId => {
|
||||
const target = _memoryObjects[targetId];
|
||||
if (target) _createConnectionLine(obj, target);
|
||||
if (target) _drawSingleConnection(obj, target);
|
||||
});
|
||||
}
|
||||
|
||||
function _drawSingleConnection(src, tgt) {
|
||||
const srcId = src.data.id;
|
||||
const tgtId = tgt.data.id;
|
||||
// Deduplicate — only draw from lower ID to higher
|
||||
if (srcId > tgtId) return;
|
||||
// Skip if already exists
|
||||
const exists = _connectionLines.some(l =>
|
||||
(l.userData.from === srcId && l.userData.to === tgtId) ||
|
||||
(l.userData.from === tgtId && l.userData.to === srcId)
|
||||
);
|
||||
if (exists) return;
|
||||
|
||||
const points = [src.mesh.position.clone(), tgt.mesh.position.clone()];
|
||||
const geo = new THREE.BufferGeometry().setFromPoints(points);
|
||||
const srcStrength = src.mesh.userData.strength || 0.7;
|
||||
const tgtStrength = tgt.mesh.userData.strength || 0.7;
|
||||
const blendedStrength = (srcStrength + tgtStrength) / 2;
|
||||
const lineOpacity = 0.15 + blendedStrength * 0.55;
|
||||
const srcColor = new THREE.Color(REGIONS[src.region]?.color || 0x334455);
|
||||
const tgtColor = new THREE.Color(REGIONS[tgt.region]?.color || 0x334455);
|
||||
const lineColor = new THREE.Color().lerpColors(srcColor, tgtColor, 0.5);
|
||||
const mat = new THREE.LineBasicMaterial({
|
||||
color: lineColor,
|
||||
transparent: true,
|
||||
opacity: lineOpacity
|
||||
});
|
||||
const line = new THREE.Line(geo, mat);
|
||||
line.userData = { type: 'connection', from: srcId, to: tgtId, baseOpacity: lineOpacity };
|
||||
line.visible = _constellationVisible;
|
||||
_scene.add(line);
|
||||
_connectionLines.push(line);
|
||||
}
|
||||
|
||||
return { ring, disc, glowDisc, sprite };
|
||||
}
|
||||
|
||||
@@ -399,7 +434,7 @@ const SpatialMemory = (() => {
|
||||
return [cx + Math.cos(angle) * dist, cy + height, cz + Math.sin(angle) * dist];
|
||||
}
|
||||
|
||||
// ─── CONNECTIONS ─────────────────────────────────────
|
||||
// ─── CONNECTIONS (constellation-aware) ───────────────
|
||||
function _drawConnections(memId, connections) {
|
||||
const src = _memoryObjects[memId];
|
||||
if (!src) return;
|
||||
@@ -410,9 +445,23 @@ const SpatialMemory = (() => {
|
||||
|
||||
const points = [src.mesh.position.clone(), tgt.mesh.position.clone()];
|
||||
const geo = new THREE.BufferGeometry().setFromPoints(points);
|
||||
const mat = new THREE.LineBasicMaterial({ color: 0x334455, transparent: true, opacity: 0.2 });
|
||||
// Strength-encoded opacity: blend source/target strengths, min 0.15, max 0.7
|
||||
const srcStrength = src.mesh.userData.strength || 0.7;
|
||||
const tgtStrength = tgt.mesh.userData.strength || 0.7;
|
||||
const blendedStrength = (srcStrength + tgtStrength) / 2;
|
||||
const lineOpacity = 0.15 + blendedStrength * 0.55;
|
||||
// Blend source/target region colors for the line
|
||||
const srcColor = new THREE.Color(REGIONS[src.region]?.color || 0x334455);
|
||||
const tgtColor = new THREE.Color(REGIONS[tgt.region]?.color || 0x334455);
|
||||
const lineColor = new THREE.Color().lerpColors(srcColor, tgtColor, 0.5);
|
||||
const mat = new THREE.LineBasicMaterial({
|
||||
color: lineColor,
|
||||
transparent: true,
|
||||
opacity: lineOpacity
|
||||
});
|
||||
const line = new THREE.Line(geo, mat);
|
||||
line.userData = { type: 'connection', from: memId, to: targetId };
|
||||
line.userData = { type: 'connection', from: memId, to: targetId, baseOpacity: lineOpacity };
|
||||
line.visible = _constellationVisible;
|
||||
_scene.add(line);
|
||||
_connectionLines.push(line);
|
||||
});
|
||||
@@ -489,6 +538,43 @@ const SpatialMemory = (() => {
|
||||
});
|
||||
}
|
||||
|
||||
function _updateConnectionLines() {
|
||||
if (!_constellationVisible) return;
|
||||
if (!_camera) return;
|
||||
const camPos = _camera.position;
|
||||
|
||||
_connectionLines.forEach(line => {
|
||||
const posArr = line.geometry.attributes.position.array;
|
||||
const mx = (posArr[0] + posArr[3]) / 2;
|
||||
const my = (posArr[1] + posArr[4]) / 2;
|
||||
const mz = (posArr[2] + posArr[5]) / 2;
|
||||
const dist = camPos.distanceTo(new THREE.Vector3(mx, my, mz));
|
||||
|
||||
if (dist > CONNECTION_LOD_DIST) {
|
||||
line.visible = false;
|
||||
} else {
|
||||
line.visible = true;
|
||||
const fade = Math.max(0, 1 - (dist / CONNECTION_LOD_DIST));
|
||||
// Restore base opacity from userData if stored, else use material default
|
||||
const base = line.userData.baseOpacity || line.material.opacity || 0.4;
|
||||
line.material.opacity = base * fade;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function toggleConstellation() {
|
||||
_constellationVisible = !_constellationVisible;
|
||||
_connectionLines.forEach(line => {
|
||||
line.visible = _constellationVisible;
|
||||
});
|
||||
console.info('[Mnemosyne] Constellation', _constellationVisible ? 'shown' : 'hidden');
|
||||
return _constellationVisible;
|
||||
}
|
||||
|
||||
function isConstellationVisible() {
|
||||
return _constellationVisible;
|
||||
}
|
||||
|
||||
// ─── REMOVE A MEMORY ─────────────────────────────────
|
||||
function removeMemory(memId) {
|
||||
const obj = _memoryObjects[memId];
|
||||
@@ -544,6 +630,7 @@ const SpatialMemory = (() => {
|
||||
});
|
||||
|
||||
_updateEntityLines();
|
||||
_updateConnectionLines();
|
||||
|
||||
Object.values(_regionMarkers).forEach(marker => {
|
||||
if (marker.ring && marker.ring.material) {
|
||||
@@ -866,7 +953,7 @@ const SpatialMemory = (() => {
|
||||
getCrystalMeshes, getMemoryFromMesh, highlightMemory, clearHighlight, getSelectedId,
|
||||
exportIndex, importIndex, searchNearby, REGIONS,
|
||||
saveToStorage, loadFromStorage, clearStorage,
|
||||
runGravityLayout, setCamera
|
||||
runGravityLayout, setCamera, toggleConstellation, isConstellationVisible
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
@@ -66,12 +66,7 @@ class NostrIdentity:
|
||||
if privkey_hex:
|
||||
self.privkey = int(privkey_hex, 16)
|
||||
else:
|
||||
# Rejection sampling: avoid modulo bias from % N
|
||||
while True:
|
||||
candidate = int.from_bytes(os.urandom(32), 'big')
|
||||
if 0 < candidate < N:
|
||||
self.privkey = candidate
|
||||
break
|
||||
self.privkey = int.from_bytes(os.urandom(32), 'big') % N
|
||||
self.pubkey = get_pubkey(self.privkey)
|
||||
|
||||
def sign_event(self, event):
|
||||
|
||||
20
server.py
20
server.py
@@ -50,21 +50,23 @@ async def broadcast_handler(websocket: websockets.WebSocketServerProtocol):
|
||||
# Broadcast to all OTHER clients
|
||||
if not clients:
|
||||
continue
|
||||
|
||||
|
||||
disconnected = set()
|
||||
# Track (client, task) pairs so failed clients are identified directly
|
||||
send_jobs = []
|
||||
# Create broadcast tasks for efficiency
|
||||
tasks = []
|
||||
for client in clients:
|
||||
if client != websocket and client.open:
|
||||
send_jobs.append((client, asyncio.create_task(client.send(message))))
|
||||
|
||||
if send_jobs:
|
||||
results = await asyncio.gather(*[job[1] for job in send_jobs], return_exceptions=True)
|
||||
for (target_client, _), result in zip(send_jobs, results):
|
||||
tasks.append(asyncio.create_task(client.send(message)))
|
||||
|
||||
if tasks:
|
||||
results = await asyncio.gather(*tasks, return_exceptions=True)
|
||||
for i, result in enumerate(results):
|
||||
if isinstance(result, Exception):
|
||||
# Find the client that failed
|
||||
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)
|
||||
|
||||
|
||||
if disconnected:
|
||||
clients.difference_update(disconnected)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user