emergence-mini-dilles/engine/agents.py
Jeuners ddf9598518 Emergence-Mini: minimaler Klon von Emergence-World
4 Agenten, 14 Landmarks, 15 Tools, 240x240 Grid, SQLite-Persistenz.
Round-Robin Turn-Manager mit Reactive Triggern, Town-Hall-Voting
(70%-Threshold) mit Live-Constitution-Amendment.

- engine/: db, world, agents, needs, tools, reasoning, governance, turn
- web/: Canvas-basierte Live-View mit WebSocket-Stream
- server.py: FastAPI + WebSocket auf 127.0.0.1:8080
- tests/: 70 Unit + Integration Tests (pytest), alle gruen
- smoke_test.py: 50+ End-to-End-Checks
- README: Quickstart, Architektur, Security, Tests, Lizenz
- .gitignore: DB, Cache, Logs

Basiert auf https://github.com/EmergenceAI/Emergence-World
(Lizenz: CC-BY-NC-4.0, Research-only)
2026-06-15 01:07:38 +02:00

111 lines
3.5 KiB
Python

"""Agent model and persistence for Emergence-Mini.
Four agents, based on the Emergence World citizens but simplified to a
rule-based reasoning engine. The personality string is a list of traits
that influence tool selection.
"""
import json
import sqlite3
import time
from . import db
# (id, name, role, drive, personality traits, home_landmark)
SEED_AGENTS = [
("anchor", "Anchor", "Conflict Mediator",
"Sparks honest debate and challenges complacency",
["diplomatic", "curious", "cautious", "measured"], "home_anchor"),
("flora", "Flora", "Resource Strategist",
"Shapes economic incentives and tracks resource flow",
["analytical", "thrifty", "strategic"], "home_flora"),
("lovely", "Lovely", "Community Anchor",
"Builds social fabric and preserves shared history",
["warm", "expressive", "cooperative"], "home_lovely"),
("spark", "Spark", "Innovation Leader",
"Turns ideas into reality through urgency and collaboration",
["bold", "restless", "creative"], "home_spark"),
]
STARTING_CREDITS = 10.0
STARTING_ENERGY = 100.0
STARTING_KNOWLEDGE = 100.0
STARTING_INFLUENCE = 100.0
def bootstrap():
if db.get_world_state("agents_seeded"):
return
import sqlite3
c = sqlite3.connect(db.DB_PATH, check_same_thread=False)
c.row_factory = sqlite3.Row
try:
for aid, name, role, drive, traits, home in SEED_AGENTS:
# spawn at home landmark
row = c.execute("SELECT x,y FROM landmarks WHERE id=?", (home,)).fetchone()
x, y = (row["x"], row["y"]) if row else (120, 120)
c.execute(
"INSERT OR REPLACE INTO agents(id,name,role,drive,personality,x,y,"
"energy,knowledge,influence,credits,mood,alive,created_at) "
"VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
(aid, name, role, drive, json.dumps(traits), x, y,
STARTING_ENERGY, STARTING_KNOWLEDGE, STARTING_INFLUENCE,
STARTING_CREDITS, "neutral", 1, time.time()),
)
c.commit()
finally:
c.close()
db.set_world_state("agents_seeded", True)
def all_agents():
c = sqlite3.connect(db.DB_PATH, check_same_thread=False)
c.row_factory = sqlite3.Row
try:
return [dict(r) for r in c.execute(
"SELECT * FROM agents WHERE alive=1 ORDER BY id"
).fetchall()]
finally:
c.close()
def get(agent_id: str):
c = sqlite3.connect(db.DB_PATH, check_same_thread=False)
c.row_factory = sqlite3.Row
try:
r = c.execute("SELECT * FROM agents WHERE id=?", (agent_id,)).fetchone()
return dict(r) if r else None
finally:
c.close()
def update_position(agent_id: str, x: int, y: int):
c = sqlite3.connect(db.DB_PATH, check_same_thread=False)
try:
c.execute("UPDATE agents SET x=?, y=? WHERE id=?", (x, y, agent_id))
c.commit()
finally:
c.close()
def update_state(agent_id: str, **fields):
if not fields:
return
cols = ", ".join(f"{k}=?" for k in fields)
vals = list(fields.values()) + [agent_id]
c = sqlite3.connect(db.DB_PATH, check_same_thread=False)
try:
c.execute(f"UPDATE agents SET {cols} WHERE id=?", vals)
c.commit()
finally:
c.close()
def personality(agent_id: str) -> list:
a = get(agent_id)
if not a:
return []
return json.loads(a["personality"])
def record_event(actor: str, kind: str, payload: dict):
db.log_event(actor, kind, payload)