#!/usr/bin/env python3 """CLI test script for Analog Town simulation. Run this to verify the simulation pipeline works before launching the UI. Usage: python test_cli.py """ import json import sys from pathlib import Path from schemas import Town, BroadcastEvent, AgentState from model_client import ModelClient from simulator import Simulator def load_sample_town(name: str = "graybridge") -> Town: """Load a sample town from the sample_towns directory.""" path = Path(__file__).parent / "sample_towns" / f"{name}.json" if not path.exists(): print(f"❌ Sample town '{name}' not found at {path}") sys.exit(1) with open(path) as f: data = json.load(f) return Town(**data) def main(): print("=" * 60) print("📻 ANALOG TOWN — CLI Simulation Test") print("=" * 60) print() # 1. Load town print("📁 Loading Graybridge sample town...") town = load_sample_town("graybridge") print(f" Town: {town.name} ({len(town.agents)} agents)") for agent in town.agents: print(f" 📡 {agent.frequency} FM — {agent.name} ({agent.role})") print() # 2. Set up event event = town.default_event or BroadcastEvent( title="Station Hotel Development", content="The old train station will be converted into a luxury hotel by an outside developer.", source="Town Council Announcement", ) print(f"📢 Broadcasting: \"{event.title}\"") print(f" {event.content}") print() # 3. Initialize simulator print("🔧 Initializing model client...") try: client = ModelClient() print(f" Model: {client.model_id}") except Exception as e: print(f"❌ Failed to initialize model client: {e}") sys.exit(1) simulator = Simulator(model_client=client) # 4. Run simulation print() print("🔄 Running simulation...") print("-" * 60) def progress_callback(name, status, index, total): emoji = {"processing": "⏳", "complete": "✅", "failed": "❌"}.get( status.split(":")[0], "⚠" ) print(f" {emoji} [{index+1}/{total}] {name}: {status}") result = simulator.run_town_simulation( town=town, event=event, progress_callback=progress_callback, ) print("-" * 60) print() # 5. Display results print(f"📊 Results: {len(result.transitions)}/{len(town.agents)} agents responded") print() for transition in result.transitions: agent = next((a for a in town.agents if a.id == transition.agent_id), None) freq = agent.frequency if agent else "?" name = agent.name if agent else transition.agent_id print(f"📻 {freq} FM — {name}") print(f" Mood: {transition.updated_state.mood_label}") print(f" 💭 \"{transition.internal_monologue}\"") print(f" 🔑 Value conflict: {transition.value_conflict}") print(f" 🎯 Public action: {transition.likely_public_action}") print(f" ❓ Uncertainty: {transition.uncertainty}") print() # 6. Summary if len(result.transitions) == len(town.agents): print("✅ All agents responded successfully!") elif len(result.transitions) > 0: print(f"⚠ {len(town.agents) - len(result.transitions)} agent(s) failed") else: print("❌ No agents responded. Check model configuration.") print() print(f"📝 Simulation completed at {result.created_at}") return len(result.transitions) > 0 if __name__ == "__main__": success = main() sys.exit(0 if success else 1)