- engine/agents.all_agents() now enriches each agent row with its currently-assigned model (model_for_agent) and provider (provider_for_model). Same source of truth as the LLM client. - web/app.js refreshAgentCards() shows a coloured tag next to the agent name: a green '💻 <model>' badge for local Ollama models, a yellow '☁ <model>' badge for OpenRouter models. The full model name is in the title attribute (hover). - web/style.css: .model-tag.local / .cloud colour palette. - Short name helper strips 'org/' prefix and ':latest' suffix for readability (e.g. 'anthropic/claude-3.5-haiku' -> 'claude-3.5-haiku'). All 100 tests still pass. Live: Anchor + Flora show '☁ claude-3.5-haiku' / '☁ gpt-4o-mini', Lovely + Spark show '💻 gemma4' (running on 192.168.1.245).
122 lines
3.8 KiB
Python
122 lines
3.8 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():
|
|
"""Return live agents with their currently-assigned LLM model."""
|
|
from . import llm as llm_mod
|
|
agents = _all_agents_raw()
|
|
for a in agents:
|
|
a["model"] = llm_mod.model_for_agent(a["id"])
|
|
a["provider"] = llm_mod.provider_for_model(a["model"])
|
|
return agents
|
|
|
|
|
|
def _all_agents_raw():
|
|
import sqlite3
|
|
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)
|