Auto-commit via make git (triggered by NFDOS)
This commit is contained in:
parent
88fc91b330
commit
0ae10b3481
24
neurotron.in
24
neurotron.in
@ -4,18 +4,28 @@ PYTHON="/usr/bin/python3"
|
||||
NEUROTRON_HOME="/opt/kernel/neurotron"
|
||||
SRC="$NEUROTRON_HOME/src"
|
||||
|
||||
# Garante diretórios básicos
|
||||
# --- Filesystems base ---
|
||||
mkdir -p /proc /sys /dev
|
||||
|
||||
# Montar proc, sysfs e devtmpfs (idempotente, falha silenciosa se já montado)
|
||||
mount -t proc proc /proc 2>/dev/null || true
|
||||
mount -t sysfs sys /sys 2>/dev/null || true
|
||||
mount -t devtmpfs devtmpfs /dev 2>/dev/null || true
|
||||
|
||||
# Ambiente Python minimalista
|
||||
# --- Ambiente ---
|
||||
export HOME=/
|
||||
export TERM=linux
|
||||
export PYTHONHOME="/usr"
|
||||
export PYTHONPATH="$SRC:/usr/lib/python3.13:/usr/lib/python3.13/site-packages"
|
||||
export PATH="/sbin:/bin:/usr/sbin:/usr/bin:$PATH"
|
||||
export PATH="/sbin:/bin:/usr/sbin:/usr/bin"
|
||||
|
||||
# Arrancar o cérebro principal como módulo do package
|
||||
exec "$PYTHON" -m neurotron "$@"
|
||||
# --- Garante VT ---
|
||||
mkdir -p /dev/pts
|
||||
mount -t devpts devpts /dev/pts 2>/dev/null || true
|
||||
|
||||
# --- Mudar para tty1 (VGA) ---
|
||||
chvt 1
|
||||
|
||||
# --- Criar sessão e ligar ao VGA ---
|
||||
exec setsid sh -c '
|
||||
exec </dev/tty1 >/dev/tty1 2>&1
|
||||
exec '"$PYTHON"' -m neurotron
|
||||
'
|
||||
|
||||
@ -73,6 +73,7 @@ def main():
|
||||
Path(log_dir).mkdir(parents=True, exist_ok=True)
|
||||
|
||||
ctx = Cortex(runtime_dir=runtime_dir, log_dir=log_dir)
|
||||
logbus.subscribe(ctx._on_log_event)
|
||||
|
||||
# threads
|
||||
t_dash = threading.Thread(target=dashboard_loop, args=(ctx,), daemon=True)
|
||||
|
||||
@ -72,6 +72,16 @@ class Cortex:
|
||||
self.telemetry_path = Path(NEUROTRON_DATASET_PATH) / "telemetry.json"
|
||||
self.telemetry_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# ---- Dashboard ----
|
||||
self.memory = Hippocampus(
|
||||
log_dir=self.log_dir,
|
||||
on_remember=self._on_memory_event,
|
||||
)
|
||||
self.ui_bus = defaultdict(lambda: deque(maxlen=200))
|
||||
self.ui_publish("kernel", "[Placeholder (No futuro /dev/kmsg, dmesg reader ou ring buffer próprio)] ACPI: Core revision 20240415")
|
||||
self.ui_publish("kernel", "[Placeholder (No futuro /dev/kmsg, dmesg reader ou ring buffer próprio)] EXT4-fs mounted filesystem")
|
||||
|
||||
|
||||
def _init_paths(self):
|
||||
"""
|
||||
Inicializa todos os paths canónicos do runtime Neurotron.
|
||||
@ -192,6 +202,16 @@ class Cortex:
|
||||
return float(x)
|
||||
except:
|
||||
return fallback
|
||||
|
||||
def ui_publish(self, pane: str, msg: str):
|
||||
self.ui_bus[pane].append(msg)
|
||||
|
||||
def ui_tail(self, pane: str, n: int):
|
||||
q = self.ui_bus.get(pane)
|
||||
if not q:
|
||||
return []
|
||||
return list(q)[-n:]
|
||||
|
||||
|
||||
# ----------------------------------------
|
||||
# heartbeat — apenas visual, não cognitivo
|
||||
@ -286,4 +306,45 @@ class Cortex:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return snap
|
||||
return snap
|
||||
|
||||
def _on_memory_event(self, kind: str, data: dict):
|
||||
"""
|
||||
Observador de eventos lembrados (UI / TRM / futuro).
|
||||
"""
|
||||
summary = self._summarize_memory(kind, data)
|
||||
if summary:
|
||||
self.ui_publish("memory", summary)
|
||||
|
||||
|
||||
def _summarize_memory(self, kind: str, data: dict) -> str:
|
||||
"""
|
||||
Converte eventos ricos em linhas humanas (dashboard).
|
||||
"""
|
||||
try:
|
||||
if kind == "boot":
|
||||
return f"[boot] mode={data.get('mode')} tick={data.get('tick')}"
|
||||
if kind.startswith("telemetry.event"):
|
||||
return f"[tele] {kind.split('.')[-1]}"
|
||||
if kind == "trm.snapshot":
|
||||
st = data.get("state", {})
|
||||
return (
|
||||
f"[trm] cog={st.get('cog_state')} "
|
||||
f"val={st.get('valence', 0):+.2f} "
|
||||
f"depth={st.get('depth')}"
|
||||
)
|
||||
return f"[{kind}] {str(data)[:60]}"
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def _on_log_event(self, ev):
|
||||
# sempre disponível para UI
|
||||
self.ui_publish("log", ev)
|
||||
|
||||
# opcional: persistência
|
||||
if ev.level in ("error", "warn"):
|
||||
self.memory.remember("log", {
|
||||
"level": ev.level,
|
||||
"msg": ev.msg
|
||||
})
|
||||
|
||||
|
||||
@ -2,4 +2,13 @@ import sys
|
||||
|
||||
class ChatPane:
|
||||
def render(self, ctx, x, y, w, h):
|
||||
sys.stdout.write(f"\033[{y};{x}HCHAT MESSAGES (placeholder)")
|
||||
# título
|
||||
sys.stdout.write(f"\033[{y};{x}HCHAT MESSAGES:")
|
||||
sys.stdout.write("\033[K")
|
||||
|
||||
# consumir linhas já publicadas
|
||||
lines = ctx.ui_tail("log", h-1)
|
||||
for i, ev in enumerate(lines):
|
||||
sys.stdout.write(
|
||||
f"\033[{y+1+i};{x}H{ev.format()[:w]}"
|
||||
)
|
||||
@ -1,6 +1,20 @@
|
||||
# panes/kernel.py
|
||||
# neurotron/dashboard/panes/kernel.py
|
||||
import sys
|
||||
|
||||
class KernelPane:
|
||||
def render(self, ctx, x, y, w, h):
|
||||
sys.stdout.write(f"\033[{y};{x}HKERNEL MESSAGES (placeholder)")
|
||||
# título
|
||||
sys.stdout.write(f"\033[{y};{x}HKERNEL MESSAGES:")
|
||||
sys.stdout.write("\033[K")
|
||||
|
||||
# consumir linhas já publicadas
|
||||
lines = ctx.ui_tail("kernel", h - 1)
|
||||
|
||||
row = y + 1
|
||||
for line in lines:
|
||||
truncated = line[:w]
|
||||
sys.stdout.write(f"\033[{row};{x}H{truncated}")
|
||||
sys.stdout.write("\033[K")
|
||||
row += 1
|
||||
|
||||
|
||||
|
||||
@ -1,5 +1,18 @@
|
||||
# neurotron/dashboard/panes/memory.py
|
||||
import sys
|
||||
|
||||
class MemoryPane:
|
||||
def render(self, ctx, x, y, w, h):
|
||||
sys.stdout.write(f"\033[{y};{x}HMEMORY MESSAGES (placeholder)")
|
||||
# título
|
||||
sys.stdout.write(f"\033[{y};{x}HMEMORY MESSAGES:")
|
||||
sys.stdout.write("\033[K")
|
||||
|
||||
# consumir memória recente (já filtrada!)
|
||||
lines = ctx.ui_tail("memory", h - 1)
|
||||
|
||||
row = y + 1
|
||||
for line in lines:
|
||||
truncated = line[:w]
|
||||
sys.stdout.write(f"\033[{row};{x}H{truncated}")
|
||||
sys.stdout.write("\033[K")
|
||||
row += 1
|
||||
|
||||
@ -2,4 +2,30 @@ import sys
|
||||
|
||||
class TRMPane:
|
||||
def render(self, ctx, x, y, w, h):
|
||||
sys.stdout.write(f"\033[{y};{x}HTRM MESSAGES (placeholder)")
|
||||
snap = ctx.cognitive_snapshot()
|
||||
|
||||
sys.stdout.write(
|
||||
f"\033[{y};{x}HTRM STATE:"
|
||||
)
|
||||
|
||||
line1 = (
|
||||
f"State:{snap['cog_state']} "
|
||||
f"Depth:{snap['depth']} "
|
||||
f"Val:{snap['valence']:+.2f} "
|
||||
f"Energy:{snap['energy']}"
|
||||
)
|
||||
|
||||
sys.stdout.write(f"\033[{y+1};{x}H{line1[:w]}\033[K")
|
||||
|
||||
# Separador
|
||||
sys.stdout.write(f"\033[{y+2};{x}H" + "─" * w)
|
||||
|
||||
# Pensamentos recentes
|
||||
thoughts = ctx.ui_tail("trm", h - 3)
|
||||
row = y + 3
|
||||
|
||||
for t in thoughts:
|
||||
sys.stdout.write(
|
||||
f"\033[{row};{x}H• {t[:w-2]}\033[K"
|
||||
)
|
||||
row += 1
|
||||
|
||||
@ -1,18 +1,24 @@
|
||||
# neurotron/hippocampus.py
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
import json
|
||||
from typing import Optional, Callable
|
||||
|
||||
|
||||
class Hippocampus:
|
||||
"""
|
||||
Memória contextual simples (JSON Lines): append-only.
|
||||
Guarda perceções, decisões e ações para replays futuros.
|
||||
Apenas stdlib JSON — 100% compatível com Python estático.
|
||||
"""
|
||||
|
||||
def __init__(self, log_dir: Path):
|
||||
def __init__(
|
||||
self,
|
||||
log_dir: Path,
|
||||
on_remember: Optional[Callable[[str, dict], None]] = None,
|
||||
):
|
||||
self.log_dir = log_dir
|
||||
self.log_dir.mkdir(parents=True, exist_ok=True)
|
||||
self.events_file = self.log_dir / "events.jsonl"
|
||||
self.on_remember = on_remember
|
||||
|
||||
def remember(self, kind: str, data: dict) -> None:
|
||||
rec = {
|
||||
@ -22,11 +28,15 @@ class Hippocampus:
|
||||
}
|
||||
|
||||
try:
|
||||
# stdlib json → sempre string
|
||||
blob = json.dumps(rec, separators=(",", ":")) # compacto
|
||||
blob = json.dumps(rec, separators=(",", ":"))
|
||||
with self.events_file.open("a", encoding="utf-8") as f:
|
||||
f.write(blob + "\n")
|
||||
except Exception:
|
||||
# nunca crashar o Neurotron por logs
|
||||
pass
|
||||
|
||||
# 🔔 notificação opcional (não quebra nunca)
|
||||
if self.on_remember:
|
||||
try:
|
||||
self.on_remember(kind, data)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@ -1,33 +1,39 @@
|
||||
# neurotron/logbus.py
|
||||
|
||||
from collections import deque
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
import sys
|
||||
|
||||
@dataclass
|
||||
class LogEvent:
|
||||
ts: str
|
||||
level: str
|
||||
msg: str
|
||||
|
||||
def format(self) -> str:
|
||||
return f"[{self.ts}] [{self.level}] {self.msg}"
|
||||
|
||||
class LogBus:
|
||||
"""
|
||||
Canal central de logs do Neurotron.
|
||||
- escreve tudo em stdout (texto simples, sem Rich)
|
||||
- mantém um buffer em memória para o dashboard (tail)
|
||||
"""
|
||||
def __init__(self):
|
||||
self._subscribers = []
|
||||
|
||||
def __init__(self, maxlen: int = 1000):
|
||||
self._buffer = deque(maxlen=maxlen)
|
||||
def subscribe(self, fn):
|
||||
self._subscribers.append(fn)
|
||||
|
||||
# -------------------------
|
||||
# núcleo
|
||||
# -------------------------
|
||||
|
||||
def _emit(self, level: str, msg: str):
|
||||
ts = datetime.utcnow().strftime("%H:%M:%S")
|
||||
line = f"[{ts}] [{level}] {msg}"
|
||||
|
||||
# guarda em memória para o dashboard
|
||||
self._buffer.append(line)
|
||||
|
||||
# escreve em stdout (uma linha)
|
||||
sys.stdout.write(line + "\n")
|
||||
sys.stdout.flush()
|
||||
ev = LogEvent(
|
||||
ts=datetime.utcnow().strftime("%H:%M:%S"),
|
||||
level=level,
|
||||
msg=msg,
|
||||
)
|
||||
for fn in self._subscribers:
|
||||
try:
|
||||
fn(ev)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# -------------------------
|
||||
# API pública de logs
|
||||
@ -61,16 +67,5 @@ class LogBus:
|
||||
# fallback para chamadas antigas tipo logbus.emit("...")
|
||||
self.info(msg)
|
||||
|
||||
# -------------------------
|
||||
# Para o dashboard
|
||||
# -------------------------
|
||||
def tail(self, n: int = 150):
|
||||
"""Devolve as últimas n linhas de log como lista de strings."""
|
||||
if n <= 0:
|
||||
return []
|
||||
buf = list(self._buffer)
|
||||
return buf[-n:]
|
||||
|
||||
|
||||
# instância global
|
||||
logbus = LogBus()
|
||||
logbus: "LogBus" = LogBus()
|
||||
|
||||
@ -171,6 +171,10 @@ class TRMEngine:
|
||||
if len(self._history) % 10 == 0 and hasattr(self.ctx, "memory"):
|
||||
payload = make_trm_snapshot_payload(st9, telemetry)
|
||||
self.ctx.memory.remember("trm.snapshot", payload)
|
||||
self.ctx.ui_publish(
|
||||
"memory",
|
||||
f"[trm] cog={st9.cog_state} val={st9.valence:+.2f} depth={st9.depth}"
|
||||
)
|
||||
except Exception as e:
|
||||
self._dbg(f"erro ao gravar snapshot no Hippocampus: {e}")
|
||||
|
||||
|
||||
@ -136,6 +136,9 @@ class ThoughtAgent:
|
||||
payload = {"thought": t}
|
||||
try:
|
||||
self.ctx.memory.remember("trm.thought", payload)
|
||||
if hasattr(self.ctx, "ui_publish"):
|
||||
self.ctx.ui_publish("trm", t)
|
||||
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user