Compare commits

...

12 Commits

Author SHA1 Message Date
Alexander Whitestone
229edf16e2 fix: closes #727
Some checks failed
CI / test (pull_request) Failing after 9s
CI / validate (pull_request) Failing after 16s
Review Approval Gate / verify-review (pull_request) Failing after 3s
2026-04-12 12:33:31 -04:00
aab3e607eb Merge pull request '[GOFAI] Resonance Viz Integration' (#1297) from feat/resonance-viz-integration-1776010801023 into main
Some checks failed
Deploy Nexus / deploy (push) Failing after 3s
Staging Verification Gate / verify-staging (push) Failing after 3s
2026-04-12 16:20:09 +00:00
fe56ece1ad Integrate ResonanceVisualizer into app.js
Some checks failed
CI / test (pull_request) Failing after 10s
CI / validate (pull_request) Failing after 16s
Review Approval Gate / verify-review (pull_request) Failing after 3s
2026-04-12 16:20:03 +00:00
bf477382ba Merge pull request '[GOFAI] Resonance Linking' (#1293) from feat/resonance-linker-1776010647557 into main
Some checks failed
Deploy Nexus / deploy (push) Failing after 3s
Staging Verification Gate / verify-staging (push) Failing after 3s
2026-04-12 16:17:33 +00:00
fba972f8be Add ResonanceLinker
Some checks failed
CI / test (pull_request) Failing after 10s
CI / validate (pull_request) Failing after 15s
Review Approval Gate / verify-review (pull_request) Failing after 3s
2026-04-12 16:17:28 +00:00
6786e65f3d Merge pull request '[GOFAI] Layer 4 — Reasoning & Decay' (#1292) from feat/gofai-layer-4-v2 into main
Some checks failed
Deploy Nexus / deploy (push) Failing after 2s
Staging Verification Gate / verify-staging (push) Failing after 3s
2026-04-12 16:15:29 +00:00
62a6581827 Add rules
Some checks failed
CI / test (pull_request) Failing after 10s
CI / validate (pull_request) Failing after 15s
Review Approval Gate / verify-review (pull_request) Failing after 3s
2026-04-12 16:15:24 +00:00
797f32a7fe Add Reasoner 2026-04-12 16:15:23 +00:00
80eb4ff7ea Enhance MemoryOptimizer 2026-04-12 16:15:22 +00:00
b205f002ef Merge pull request '[GOFAI] Resonance Visualization' (#1284) from feat/resonance-viz-1775996553148 into main
Some checks failed
Deploy Nexus / deploy (push) Failing after 3s
Staging Verification Gate / verify-staging (push) Failing after 3s
2026-04-12 12:22:39 +00:00
2230c1c9fc Add ResonanceVisualizer
Some checks failed
CI / test (pull_request) Failing after 9s
CI / validate (pull_request) Failing after 15s
Review Approval Gate / verify-review (pull_request) Failing after 3s
2026-04-12 12:22:34 +00:00
d7bcadb8c1 Merge pull request '[GOFAI] Final Missing Files' (#1283) from feat/gofai-nexus-final-v2 into main
Some checks failed
Deploy Nexus / deploy (push) Failing after 3s
Staging Verification Gate / verify-staging (push) Failing after 3s
2026-04-12 12:22:20 +00:00
7 changed files with 160 additions and 13 deletions

6
app.js
View File

@@ -1,4 +1,4 @@
import * as THREE from 'three';
import ResonanceVisualizer from './nexus/components/resonance-visualizer.js';\nimport * 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 metaLayer, neuroBridge, cbr, symbolicPlanner, knowledgeGraph, blackboard, symbolicEngine, calibrator;
let resonanceViz, 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();
setupGOFAI();\n resonanceViz = new ResonanceVisualizer(scene);
camera = new THREE.PerspectiveCamera(65, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.copy(playerPos);

View File

@@ -1,13 +1,18 @@
class MemoryOptimizer {
constructor(options = {}) {
this.threshold = options.threshold || 0.8;
this.decayRate = options.decayRate || 0.05;
this.threshold = options.threshold || 0.3;
this.decayRate = options.decayRate || 0.01;
this.lastRun = Date.now();
}
optimize(memory) {
console.log('Optimizing memory...');
// Heuristic-based pruning
return memory.filter(m => m.strength > this.threshold);
optimize(memories) {
const now = Date.now();
const elapsed = (now - this.lastRun) / 1000;
this.lastRun = now;
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;

View File

@@ -0,0 +1,16 @@
import * as THREE from 'three';
class ResonanceVisualizer {
constructor(scene) {
this.scene = scene;
this.links = [];
}
addLink(p1, p2, strength) {
const geometry = new THREE.BufferGeometry().setFromPoints([p1, p2]);
const material = new THREE.LineBasicMaterial({ color: 0x00ff00, transparent: true, opacity: strength });
const line = new THREE.Line(geometry, material);
this.scene.add(line);
this.links.push(line);
}
}
export default ResonanceVisualizer;

View File

@@ -243,24 +243,108 @@ async def playback(log_path: Path, ws_url: str):
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():
parser = argparse.ArgumentParser(description="Evennia -> Nexus WebSocket Bridge")
sub = parser.add_subparsers(dest="mode")
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("--ws", default="ws://127.0.0.1:8765", help="Nexus WebSocket URL")
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("--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()
if args.mode == "live":
asyncio.run(live_bridge(args.log_dir, args.ws))
elif args.mode == "playback":
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:
parser.print_help()

View File

@@ -0,0 +1,14 @@
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

View File

@@ -0,0 +1,22 @@
"""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

@@ -0,0 +1,6 @@
[
{
"condition": "count(type=anomaly)>3",
"action": "alert"
}
]