Compare commits
1 Commits
mimo/code/
...
mimo/build
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c34748704e |
38
app.js
38
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 { 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);
|
||||||
|
|
||||||
@@ -704,13 +704,13 @@ async function init() {
|
|||||||
createParticles();
|
createParticles();
|
||||||
createDustParticles();
|
createDustParticles();
|
||||||
updateLoad(85);
|
updateLoad(85);
|
||||||
createAmbientStructures();
|
if (performanceTier !== "low") createAmbientStructures();
|
||||||
createAgentPresences();
|
createAgentPresences();
|
||||||
createThoughtStream();
|
if (performanceTier !== "low") createThoughtStream();
|
||||||
createHarnessPulse();
|
createHarnessPulse();
|
||||||
createSessionPowerMeter();
|
createSessionPowerMeter();
|
||||||
createWorkshopTerminal();
|
createWorkshopTerminal();
|
||||||
createAshStorm();
|
if (performanceTier !== "low") createAshStorm();
|
||||||
SpatialMemory.init(scene);
|
SpatialMemory.init(scene);
|
||||||
MemoryBirth.init(scene);
|
MemoryBirth.init(scene);
|
||||||
MemoryBirth.wrapSpatialMemory(SpatialMemory);
|
MemoryBirth.wrapSpatialMemory(SpatialMemory);
|
||||||
@@ -730,14 +730,20 @@ async function init() {
|
|||||||
fetchGiteaData();
|
fetchGiteaData();
|
||||||
setInterval(fetchGiteaData, 30000); // Refresh every 30s
|
setInterval(fetchGiteaData, 30000); // Refresh every 30s
|
||||||
|
|
||||||
composer = new EffectComposer(renderer);
|
// Quality-tier feature gating: only enable heavy post-processing on medium/high
|
||||||
composer.addPass(new RenderPass(scene, camera));
|
if (performanceTier !== 'low') {
|
||||||
const bloom = new UnrealBloomPass(
|
composer = new EffectComposer(renderer);
|
||||||
new THREE.Vector2(window.innerWidth, window.innerHeight),
|
composer.addPass(new RenderPass(scene, camera));
|
||||||
0.6, 0.4, 0.85
|
const bloomStrength = performanceTier === 'high' ? 0.6 : 0.35;
|
||||||
);
|
const bloom = new UnrealBloomPass(
|
||||||
composer.addPass(bloom);
|
new THREE.Vector2(window.innerWidth, window.innerHeight),
|
||||||
composer.addPass(new SMAAPass(window.innerWidth, window.innerHeight));
|
bloomStrength, 0.4, 0.85
|
||||||
|
);
|
||||||
|
composer.addPass(bloom);
|
||||||
|
composer.addPass(new SMAAPass(window.innerWidth, window.innerHeight));
|
||||||
|
} else {
|
||||||
|
composer = null;
|
||||||
|
}
|
||||||
|
|
||||||
updateLoad(95);
|
updateLoad(95);
|
||||||
|
|
||||||
@@ -3127,7 +3133,7 @@ function gameLoop() {
|
|||||||
core.material.emissiveIntensity = 1.5 + Math.sin(elapsed * 2) * 0.5;
|
core.material.emissiveIntensity = 1.5 + Math.sin(elapsed * 2) * 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
composer.render();
|
if (composer) { composer.render(); } else { renderer.render(scene, camera); }
|
||||||
|
|
||||||
updateAshStorm(delta, elapsed);
|
updateAshStorm(delta, elapsed);
|
||||||
|
|
||||||
@@ -3166,7 +3172,7 @@ function onResize() {
|
|||||||
camera.aspect = w / h;
|
camera.aspect = w / h;
|
||||||
camera.updateProjectionMatrix();
|
camera.updateProjectionMatrix();
|
||||||
renderer.setSize(w, h);
|
renderer.setSize(w, h);
|
||||||
composer.setSize(w, h);
|
if (composer) composer.setSize(w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ═══ AGENT SIMULATION ═══
|
// ═══ AGENT SIMULATION ═══
|
||||||
|
|||||||
@@ -1,18 +1,13 @@
|
|||||||
|
|
||||||
class MemoryOptimizer {
|
class MemoryOptimizer {
|
||||||
constructor(options = {}) {
|
constructor(options = {}) {
|
||||||
this.threshold = options.threshold || 0.3;
|
this.threshold = options.threshold || 0.8;
|
||||||
this.decayRate = options.decayRate || 0.01;
|
this.decayRate = options.decayRate || 0.05;
|
||||||
this.lastRun = Date.now();
|
|
||||||
}
|
}
|
||||||
optimize(memories) {
|
optimize(memory) {
|
||||||
const now = Date.now();
|
console.log('Optimizing memory...');
|
||||||
const elapsed = (now - this.lastRun) / 1000;
|
// Heuristic-based pruning
|
||||||
this.lastRun = now;
|
return memory.filter(m => m.strength > this.threshold);
|
||||||
return memories.map(m => {
|
|
||||||
const decay = (m.importance || 1) * this.decayRate * elapsed;
|
|
||||||
return { ...m, strength: Math.max(0, (m.strength || 1) - decay) };
|
|
||||||
}).filter(m => m.strength > this.threshold || m.locked);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export default MemoryOptimizer;
|
export default MemoryOptimizer;
|
||||||
|
|||||||
@@ -243,108 +243,24 @@ async def playback(log_path: Path, ws_url: str):
|
|||||||
await ws.send(json.dumps(event))
|
await ws.send(json.dumps(event))
|
||||||
|
|
||||||
|
|
||||||
async def inject_event(event_type: str, ws_url: str, **kwargs):
|
|
||||||
"""Inject a single Evennia event into the Nexus WS gateway. Dev/test use."""
|
|
||||||
from nexus.evennia_event_adapter import (
|
|
||||||
actor_located, command_issued, command_result,
|
|
||||||
room_snapshot, session_bound,
|
|
||||||
)
|
|
||||||
|
|
||||||
builders = {
|
|
||||||
"room_snapshot": lambda: room_snapshot(
|
|
||||||
kwargs.get("room_key", "Gate"),
|
|
||||||
kwargs.get("title", "Gate"),
|
|
||||||
kwargs.get("desc", "The entrance gate."),
|
|
||||||
exits=kwargs.get("exits"),
|
|
||||||
objects=kwargs.get("objects"),
|
|
||||||
),
|
|
||||||
"actor_located": lambda: actor_located(
|
|
||||||
kwargs.get("actor_id", "Timmy"),
|
|
||||||
kwargs.get("room_key", "Gate"),
|
|
||||||
kwargs.get("room_name"),
|
|
||||||
),
|
|
||||||
"command_result": lambda: command_result(
|
|
||||||
kwargs.get("session_id", "dev-inject"),
|
|
||||||
kwargs.get("actor_id", "Timmy"),
|
|
||||||
kwargs.get("command_text", "look"),
|
|
||||||
kwargs.get("output_text", "You see the Gate."),
|
|
||||||
success=kwargs.get("success", True),
|
|
||||||
),
|
|
||||||
"command_issued": lambda: command_issued(
|
|
||||||
kwargs.get("session_id", "dev-inject"),
|
|
||||||
kwargs.get("actor_id", "Timmy"),
|
|
||||||
kwargs.get("command_text", "look"),
|
|
||||||
),
|
|
||||||
"session_bound": lambda: session_bound(
|
|
||||||
kwargs.get("session_id", "dev-inject"),
|
|
||||||
kwargs.get("account", "Timmy"),
|
|
||||||
kwargs.get("character", "Timmy"),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
if event_type not in builders:
|
|
||||||
print(f"[inject] Unknown event type: {event_type}", flush=True)
|
|
||||||
print(f"[inject] Available: {', '.join(builders)}", flush=True)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
event = builders[event_type]()
|
|
||||||
payload = json.dumps(event)
|
|
||||||
|
|
||||||
if websockets is None:
|
|
||||||
print(f"[inject] websockets not installed, printing event:\n{payload}", flush=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
async with websockets.connect(ws_url, open_timeout=5) as ws:
|
|
||||||
await ws.send(payload)
|
|
||||||
print(f"[inject] Sent {event_type} -> {ws_url}", flush=True)
|
|
||||||
print(f"[inject] Payload: {payload}", flush=True)
|
|
||||||
except Exception as e:
|
|
||||||
print(f"[inject] Failed to send to {ws_url}: {e}", flush=True)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description="Evennia -> Nexus WebSocket Bridge")
|
parser = argparse.ArgumentParser(description="Evennia -> Nexus WebSocket Bridge")
|
||||||
sub = parser.add_subparsers(dest="mode")
|
sub = parser.add_subparsers(dest="mode")
|
||||||
|
|
||||||
live = sub.add_parser("live", help="Live tail Evennia logs and stream to Nexus")
|
live = sub.add_parser("live", help="Live tail Evennia logs and stream to Nexus")
|
||||||
live.add_argument("--log-dir", default="/root/workspace/timmy-academy/server/logs", help="Evennia logs directory")
|
live.add_argument("--log-dir", default="/root/workspace/timmy-academy/server/logs", help="Evennia logs directory")
|
||||||
live.add_argument("--ws", default="ws://127.0.0.1:8765", help="Nexus WebSocket URL")
|
live.add_argument("--ws", default="ws://127.0.0.1:8765", help="Nexus WebSocket URL")
|
||||||
|
|
||||||
replay = sub.add_parser("playback", help="Replay a telemetry JSONL file")
|
replay = sub.add_parser("playback", help="Replay a telemetry JSONL file")
|
||||||
replay.add_argument("log_path", help="Path to Evennia telemetry JSONL")
|
replay.add_argument("log_path", help="Path to Evennia telemetry JSONL")
|
||||||
replay.add_argument("--ws", default="ws://127.0.0.1:8765", help="Nexus WebSocket URL")
|
replay.add_argument("--ws", default="ws://127.0.0.1:8765", help="Nexus WebSocket URL")
|
||||||
|
|
||||||
inject = sub.add_parser("inject", help="Inject a single Evennia event (dev/test)")
|
|
||||||
inject.add_argument("event_type", choices=["room_snapshot", "actor_located", "command_result", "command_issued", "session_bound"])
|
|
||||||
inject.add_argument("--ws", default="ws://127.0.0.1:8765", help="Nexus WebSocket URL")
|
|
||||||
inject.add_argument("--room-key", default="Gate", help="Room key (room_snapshot, actor_located)")
|
|
||||||
inject.add_argument("--title", default="Gate", help="Room title (room_snapshot)")
|
|
||||||
inject.add_argument("--desc", default="The entrance gate.", help="Room description (room_snapshot)")
|
|
||||||
inject.add_argument("--actor-id", default="Timmy", help="Actor ID")
|
|
||||||
inject.add_argument("--command-text", default="look", help="Command text (command_result, command_issued)")
|
|
||||||
inject.add_argument("--output-text", default="You see the Gate.", help="Command output (command_result)")
|
|
||||||
inject.add_argument("--session-id", default="dev-inject", help="Hermes session ID")
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if args.mode == "live":
|
if args.mode == "live":
|
||||||
asyncio.run(live_bridge(args.log_dir, args.ws))
|
asyncio.run(live_bridge(args.log_dir, args.ws))
|
||||||
elif args.mode == "playback":
|
elif args.mode == "playback":
|
||||||
asyncio.run(playback(Path(args.log_path).expanduser(), args.ws))
|
asyncio.run(playback(Path(args.log_path).expanduser(), args.ws))
|
||||||
elif args.mode == "inject":
|
|
||||||
asyncio.run(inject_event(
|
|
||||||
args.event_type,
|
|
||||||
args.ws,
|
|
||||||
room_key=args.room_key,
|
|
||||||
title=args.title,
|
|
||||||
desc=args.desc,
|
|
||||||
actor_id=args.actor_id,
|
|
||||||
command_text=args.command_text,
|
|
||||||
output_text=args.output_text,
|
|
||||||
session_id=args.session_id,
|
|
||||||
))
|
|
||||||
else:
|
else:
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
|
|
||||||
class Reasoner:
|
|
||||||
def __init__(self, rules):
|
|
||||||
self.rules = rules
|
|
||||||
def evaluate(self, entries):
|
|
||||||
return [r['action'] for r in self.rules if self._check(r['condition'], entries)]
|
|
||||||
def _check(self, cond, entries):
|
|
||||||
if cond.startswith('count'):
|
|
||||||
# e.g. count(type=anomaly)>3
|
|
||||||
p = cond.replace('count(', '').split(')')
|
|
||||||
key, val = p[0].split('=')
|
|
||||||
count = sum(1 for e in entries if e.get(key) == val)
|
|
||||||
return eval(f"{count}{p[1]}")
|
|
||||||
return False
|
|
||||||
@@ -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)
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"condition": "count(type=anomaly)>3",
|
|
||||||
"action": "alert"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
Reference in New Issue
Block a user