Compare commits
1 Commits
fix/1509
...
burn/1442-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d237f8e36 |
@@ -165,10 +165,10 @@
|
||||
|
||||
<!-- Top Right: Agent Log, Atlas & SOUL Toggle -->
|
||||
<div class="hud-top-right">
|
||||
<button id="atlas-toggle-btn" class="hud-icon-btn" title="World Directory">
|
||||
<button id="soul-toggle-btn" class="hud-icon-btn" title="Timmy's SOUL">
|
||||
<span class="hud-icon">✦</span>
|
||||
<span class="hud-btn-label">SOUL</span>
|
||||
</button>
|
||||
<button id="mode-toggle-btn" class="hud-icon-btn mode-toggle" title="Toggle Mode">
|
||||
<span class="hud-icon">👁</span>
|
||||
<span class="hud-btn-label" id="mode-label">VISITOR</span>
|
||||
|
||||
@@ -29,7 +29,7 @@ from typing import Any, Callable, Optional
|
||||
|
||||
import websockets
|
||||
|
||||
from nexus.bannerlord_trace import BannerlordTraceLogger
|
||||
from bannerlord_trace import BannerlordTraceLogger
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# CONFIGURATION
|
||||
|
||||
@@ -181,63 +181,6 @@ async def live_bridge(log_dir: str, ws_url: str, reconnect_delay: float = 5.0):
|
||||
await asyncio.gather(*tasks)
|
||||
|
||||
|
||||
|
||||
|
||||
def clean_lines(text: str) -> list[str]:
|
||||
"""Strip ANSI, normalize line endings, return non-empty lines."""
|
||||
text = strip_ansi(text).replace("\r", "")
|
||||
return [line.strip() for line in text.split("\n") if line.strip()]
|
||||
|
||||
|
||||
def parse_room_output(text: str) -> dict:
|
||||
"""Parse Evennia room text into structured data (title, desc, exits, objects)."""
|
||||
lines = clean_lines(text)
|
||||
if len(lines) < 2:
|
||||
return {"title": lines[0] if lines else "", "desc": "", "exits": [], "objects": []}
|
||||
title = lines[0]
|
||||
desc = lines[1]
|
||||
exits = []
|
||||
objects = []
|
||||
for line in lines[2:]:
|
||||
if line.startswith("Exits:"):
|
||||
raw = line.split(":", 1)[1].strip().replace(" and ", ", ")
|
||||
exits = [{"key": t.strip(), "destination_id": t.strip().title(), "destination_key": t.strip().title()} for t in raw.split(",") if t.strip()]
|
||||
elif line.startswith("You see:"):
|
||||
raw = line.split(":", 1)[1].strip().replace(" and ", ", ")
|
||||
parts = [t.strip() for t in raw.split(",") if t.strip()]
|
||||
objects = [{"id": p.removeprefix("a ").removeprefix("an "), "key": p.removeprefix("a ").removeprefix("an "), "short_desc": p} for p in parts]
|
||||
return {"title": title, "desc": desc, "exits": exits, "objects": objects}
|
||||
|
||||
|
||||
def normalize_event(raw: dict, hermes_session_id: str) -> list[dict]:
|
||||
"""Convert raw Evennia event dict into normalized Nexus events."""
|
||||
from nexus.evennia_event_adapter import (
|
||||
actor_located, command_issued, command_result,
|
||||
room_snapshot, session_bound,
|
||||
)
|
||||
out = []
|
||||
event = raw.get("event")
|
||||
actor = raw.get("actor", "Timmy")
|
||||
timestamp = raw.get("timestamp")
|
||||
if event == "connect":
|
||||
out.append(session_bound(hermes_session_id, evennia_account=actor, evennia_character=actor, timestamp=timestamp))
|
||||
parsed = parse_room_output(raw.get("output", ""))
|
||||
if parsed:
|
||||
out.append(actor_located(actor, parsed["title"], parsed["title"], timestamp=timestamp))
|
||||
out.append(room_snapshot(parsed["title"], parsed["title"], parsed["desc"], exits=parsed["exits"], objects=parsed["objects"], timestamp=timestamp))
|
||||
elif event == "command":
|
||||
cmd = raw.get("command", "")
|
||||
output = raw.get("output", "")
|
||||
out.append(command_issued(hermes_session_id, actor, cmd, timestamp=timestamp))
|
||||
success = not output.startswith("Command '") and not output.startswith("Could not find")
|
||||
out.append(command_result(hermes_session_id, actor, cmd, strip_ansi(output), success=success, timestamp=timestamp))
|
||||
parsed = parse_room_output(output)
|
||||
if parsed:
|
||||
out.append(actor_located(actor, parsed["title"], parsed["title"], timestamp=timestamp))
|
||||
out.append(room_snapshot(parsed["title"], parsed["title"], parsed["desc"], exits=parsed["exits"], objects=parsed["objects"], timestamp=timestamp))
|
||||
return out
|
||||
|
||||
|
||||
async def playback(log_path: Path, ws_url: str):
|
||||
"""Legacy mode: replay a telemetry JSONL file."""
|
||||
from nexus.evennia_event_adapter import (
|
||||
|
||||
21
tests/test_hud_toggle_buttons.py
Normal file
21
tests/test_hud_toggle_buttons.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def _hud_button_block() -> str:
|
||||
text = (Path(__file__).resolve().parents[1] / 'index.html').read_text(encoding='utf-8')
|
||||
start = text.index('<!-- Top Right: Agent Log, Atlas & SOUL Toggle -->')
|
||||
end = text.index('<div id="bannerlord-status"')
|
||||
return text[start:end]
|
||||
|
||||
|
||||
def test_hud_toggle_buttons_have_unique_ids():
|
||||
block = _hud_button_block()
|
||||
assert block.count('id="atlas-toggle-btn"') == 1
|
||||
assert block.count('id="soul-toggle-btn"') == 1
|
||||
assert block.count('id="mode-toggle-btn"') == 1
|
||||
|
||||
|
||||
def test_hud_toggle_buttons_are_balanced_and_closed():
|
||||
block = _hud_button_block()
|
||||
assert block.count('<button') == 3
|
||||
assert block.count('</button>') == 3
|
||||
Reference in New Issue
Block a user