toy-room-v3 / src /command_coercion.py
sanjuhs's picture
Sync Toy Room V3 evidence and brain fallback
d93c870 verified
Raw
History Blame Contribute Delete
22.9 kB
from __future__ import annotations
from typing import Any
from src.pet_payload import target_from_payload
from src.pet_profiles import PET_PROFILES, normalize_pet
def coerce_fireboy_command_action(action: dict[str, Any], payload: dict[str, Any]) -> None:
message = str(payload.get("message") or "").lower()
pet = normalize_pet(action.get("pet") or payload.get("pet"))
if pet != "fire_boy":
return
if is_stop_request(message):
action["animation"] = "idle"
action["intent"] = "grounded_stop_idle"
action["power"] = {"name": "ember_jump", "targetId": "self", "strength": 0.0, "durationMs": 200}
action["interaction"] = {"verb": "stop", "targetId": "self", "partnerPet": "", "durationMs": 300}
action["spell"] = cosmetic_spell("stop marker", "self", "#ffd75a")
action["speech"] = "Me stop."
mark_grounded(action, "stop", "self")
elif is_greeting_request(message):
target_id = viewer_target_id(payload)
action["animation"] = "look"
action["intent"] = "grounded_greet_player"
action["power"] = {"name": "ember_jump", "targetId": target_id, "strength": 0.2, "durationMs": 650}
action["interaction"] = {"verb": "look_at", "targetId": target_id, "partnerPet": "", "durationMs": 1200}
action["spell"] = cosmetic_spell("tiny hello", "self", "#ffb347")
action["speech"] = "Hi hi, me Fire Boy."
mark_grounded(action, "greet_player", target_id)
mark_combo(action, "wave")
elif is_dance_request(message):
target_id = viewer_target_id(payload)
action["animation"] = "look"
action["intent"] = "grounded_dance_player"
action["power"] = {"name": "ember_jump", "targetId": target_id, "strength": 0.24, "durationMs": 700}
action["interaction"] = {"verb": "look_at", "targetId": target_id, "partnerPet": "", "durationMs": 900}
action["spell"] = cosmetic_spell("dance marker", "self", "#ffb347")
action["speech"] = "Me do tiny dance."
mark_grounded(action, "dance_player", target_id)
mark_combo(action, "dance")
elif is_sit_request(message):
target_id = command_target_id(payload, {"chair", "seat", "stool", "sit"})
action["animation"] = "sit"
action["intent"] = "grounded_sit_chair"
action["power"] = {"name": "ember_jump", "targetId": target_id, "strength": 0.18, "durationMs": 650}
action["interaction"] = {"verb": "sit", "targetId": target_id, "partnerPet": "", "durationMs": 2200}
action["spell"] = cosmetic_spell("sit marker", target_id, "#ffd75a")
action["speech"] = "Me sit tiny."
mark_grounded(action, "sit_chair", target_id)
mark_combo(action, "sit")
elif is_throw_request(message):
target_id = command_target_id(payload, {"ball", "sphere", "orb", "toy"})
action["animation"] = "throw"
action["intent"] = "grounded_throw_to_player"
action["power"] = {"name": "ember_jump", "targetId": target_id, "strength": 0.3, "durationMs": 650}
action["interaction"] = {"verb": "throw", "targetId": target_id, "partnerPet": "", "durationMs": 1400}
action["spell"] = cosmetic_spell("catch throw marker", target_id, "#ffd75a")
action["speech"] = "Me toss to you."
mark_grounded(action, "throw_to_player", target_id)
mark_combo(action, "throw")
elif any(phrase in message for phrase in ["turn around", "turn back", "spin around", "face away"]):
target_id = command_target_id(payload)
action["animation"] = "turn" if "turn" in PET_PROFILES[pet]["animations"] else "bounce"
action["intent"] = "grounded_turn"
action["power"] = {"name": "ember_jump", "targetId": target_id, "strength": 0.25, "durationMs": 700}
action["interaction"] = {"verb": "turn", "targetId": target_id, "partnerPet": "", "durationMs": 1300}
action["spell"] = cosmetic_spell("turn marker", "self", "#ffb347")
action["speech"] = "Me turn round."
mark_grounded(action, "turn", target_id)
elif any(phrase in message for phrase in ["look at me", "look to me", "look toward me", "look towards me", "face me", "turn to me", "turn toward me", "turn towards me", "watch me"]):
target_id = command_target_id(payload)
action["animation"] = "look" if "look" in PET_PROFILES[pet]["animations"] else "look_left_right"
action["intent"] = "grounded_look_at_player"
action["power"] = {"name": "ember_jump", "targetId": target_id, "strength": 0.22, "durationMs": 700}
action["interaction"] = {"verb": "look_at", "targetId": target_id, "partnerPet": "", "durationMs": 1700}
action["spell"] = cosmetic_spell("look marker", "self", "#ffd75a")
action["speech"] = "Me looky."
mark_grounded(action, "look_at_player", target_id)
elif any(phrase in message for phrase in ["point at", "show me", "show the", "gesture at"]):
target_id = command_target_id(payload, {"box", "cube", "block", "toy", "ball"})
action["animation"] = "point" if "point" in PET_PROFILES[pet]["animations"] else "look_left_right"
action["intent"] = "grounded_point"
action["power"] = {"name": "ember_jump", "targetId": target_id, "strength": 0.25, "durationMs": 700}
action["interaction"] = {"verb": "point", "targetId": target_id, "partnerPet": "", "durationMs": 1800}
action["spell"] = cosmetic_spell("point marker", target_id, "#ffd75a")
action["speech"] = "Me pointy there."
mark_grounded(action, "point", target_id)
elif any(phrase in message for phrase in ["reach for", "touch the", "poke the", "tap the"]):
target_id = command_target_id(payload, {"box", "cube", "block", "toy", "ball"})
action["animation"] = "reach" if "reach" in PET_PROFILES[pet]["animations"] else "look_left_right"
action["intent"] = "grounded_reach"
action["power"] = {"name": "ember_jump", "targetId": target_id, "strength": 0.25, "durationMs": 700}
action["interaction"] = {"verb": "reach", "targetId": target_id, "partnerPet": "", "durationMs": 1900}
action["spell"] = cosmetic_spell("reach marker", target_id, "#ffd75a")
action["speech"] = "Me reach careful."
mark_grounded(action, "reach", target_id)
elif any(phrase in message for phrase in ["drop it", "put it down", "release", "let go"]):
target_id = command_target_id(payload)
action["animation"] = "reach" if "reach" in PET_PROFILES[pet]["animations"] else "bounce"
action["intent"] = "grounded_release"
action["power"] = {"name": "ember_jump", "targetId": target_id, "strength": 0.2, "durationMs": 600}
action["interaction"] = {"verb": "release", "targetId": target_id, "partnerPet": "", "durationMs": 1200}
action["spell"] = cosmetic_spell("release marker", "self", "#ffb347")
action["speech"] = "Me put down."
mark_grounded(action, "release", target_id)
elif any(phrase in message for phrase in ["look at", "face the", "watch the", "look toward", "look towards", "look to the", "turn toward", "turn towards", "turn to the", "face toward", "face towards"]):
target_id = command_target_id(payload, {"box", "cube", "block", "toy", "ball", "chair", "table", "lamp", "plant", "book", "clock"})
action["animation"] = "look" if "look" in PET_PROFILES[pet]["animations"] else "look_left_right"
action["intent"] = "grounded_look_at"
action["power"] = {"name": "ember_jump", "targetId": target_id, "strength": 0.22, "durationMs": 700}
action["interaction"] = {"verb": "look_at", "targetId": target_id, "partnerPet": "", "durationMs": 1700}
action["spell"] = cosmetic_spell("look marker", target_id, "#ffd75a")
action["speech"] = "Me looky."
mark_grounded(action, "look_at", target_id)
elif command_has_any(message, ["walk", "stroll", "patrol"]):
target_id = command_target_id(payload)
action["animation"] = "walk"
action["intent"] = "grounded_walk"
action["power"] = {"name": "ember_jump", "targetId": target_id, "strength": 0.45, "durationMs": 900}
action["interaction"] = {"verb": "walk", "targetId": target_id, "partnerPet": "", "durationMs": 5200}
action["spell"] = cosmetic_spell("walk marker", "self", "#ff9b45")
action["speech"] = "Me walky loop."
mark_grounded(action, "walk", target_id)
elif command_has_any(message, ["run", "zoom", "dash", "race"]):
target_id = command_target_id(payload)
action["animation"] = "run"
action["intent"] = "grounded_run"
action["power"] = {"name": "ember_jump", "targetId": target_id, "strength": 0.7, "durationMs": 900}
action["interaction"] = {"verb": "run", "targetId": target_id, "partnerPet": "", "durationMs": 3600}
action["spell"] = cosmetic_spell("run marker", "self", "#ff6b3d")
action["speech"] = "Me do zoom loop."
mark_grounded(action, "run", target_id)
elif is_pickup_request(message):
target_id = command_target_id(payload, {"box", "cube", "block", "toy", "ball"})
action["animation"] = "walk" if "walk" in PET_PROFILES[pet]["animations"] else action.get("animation", "flame_wiggle")
action["intent"] = "grounded_pickup"
action["power"] = {"name": "ember_jump", "targetId": target_id, "strength": 0.35, "durationMs": 800}
action["interaction"] = {"verb": "pickup", "targetId": target_id, "partnerPet": "", "durationMs": 2600}
action["spell"] = cosmetic_spell("pickup marker", target_id, "#ffd75a")
action["speech"] = "Me hold it, hehe."
mark_grounded(action, "pickup", target_id)
elif any(phrase in message for phrase in ["bring", "fetch", "carry"]):
target_id = command_target_id(payload, {"box", "cube", "block", "toy", "ball"})
verb = "bring" if any(phrase in message for phrase in ["bring", "fetch"]) else "carry"
action["animation"] = "walk" if "walk" in PET_PROFILES[pet]["animations"] else action.get("animation", "flame_wiggle")
action["intent"] = f"grounded_{verb}"
action["power"] = {"name": "ember_jump", "targetId": target_id, "strength": 0.35, "durationMs": 800}
action["interaction"] = {"verb": verb, "targetId": target_id, "partnerPet": "", "durationMs": 3000}
action["spell"] = cosmetic_spell("carry marker", target_id, "#ffd75a")
action["speech"] = "Me bring tiny thing."
mark_grounded(action, verb, target_id)
elif "fireball" in message:
target_id = command_target_id(payload, {"box", "cube", "block", "toy", "ball"})
action["animation"] = "flame_wiggle"
action["power"] = {"name": "fireball", "targetId": target_id, "strength": 0.95, "durationMs": 1400}
action["interaction"] = {"verb": "none", "targetId": target_id, "partnerPet": "", "durationMs": 1000}
action["spell"] = {
"spellName": "supervised ember",
"ops": [
{"op": "spawn_particle", "targetId": target_id, "durationMs": 1100, "color": "#ff7a33"},
{"op": "set_light", "targetId": target_id, "intensity": 70, "durationMs": 260, "color": "#ffb347"},
],
}
action["speech"] = "Me make warm sparkle."
elif is_generic_chat_message(message):
target_id = command_target_id(payload)
action["animation"] = "bounce"
action["power"] = {"name": "ember_jump", "targetId": target_id, "strength": 0.25, "durationMs": 700}
action["interaction"] = {"verb": "talk", "targetId": target_id, "partnerPet": "", "durationMs": 1400}
action["spell"] = {
"spellName": "tiny hello",
"ops": [{"op": "spawn_particle", "targetId": "self", "durationMs": 700, "color": "#ffb347"}],
}
action["speech"] = "Me here, hehe."
def is_generic_chat_message(message: str) -> bool:
explicit = [
"walk",
"run",
"pick",
"grab",
"hold",
"bring",
"fetch",
"carry",
"fireball",
"smoke",
"jump",
"turn",
"spin",
"face",
"point",
"reach",
"touch",
"tap",
"poke",
"release",
"stop",
"pause",
"idle",
"halt",
"drop",
"let go",
"inspect",
"look",
"see",
"create",
"make",
"spawn",
"wish",
"sit",
"dance",
"throw",
"toss",
"catch",
]
if any(word in message for word in explicit):
return False
chat = ["hi", "hello", "hey", "what's up", "whats up", "how are", "talk", "say"]
return not message.strip() or any(phrase in message for phrase in chat)
def is_greeting_request(message: str) -> bool:
if any(word in message for word in ["walk", "run", "go to", "move to", "pick", "grab", "eat"]):
return False
return any(phrase in message for phrase in ["say hi", "say hello", "hello", "hi", "hey", "greet", "wave"])
def is_stop_request(message: str) -> bool:
padded = f" {message} "
return any(phrase in padded for phrase in [" stop ", " pause ", " idle ", " halt ", " stay "]) or "hold still" in message
def is_dance_request(message: str) -> bool:
if any(phrase in message for phrase in ["go to", "move to", "walk to", "run to", "pick", "grab", "eat"]):
return False
return any(word in set(re_split_words(message)) for word in ["dance", "boogie", "celebrate"])
def is_sit_request(message: str) -> bool:
padded = f" {message} "
return " sit " in padded or "sit down" in message or "take a seat" in message
def is_throw_request(message: str) -> bool:
return any(phrase in message for phrase in ["play catch", "catch", "throw", "toss"])
def is_pickup_request(message: str) -> bool:
padded = f" {message} "
return (
" pick " in padded
or "pick up" in message
or "pickup" in message
or " grab " in padded
or " hold " in padded
or "lift the" in message
or "take the" in message
)
def command_has_any(message: str, words: list[str]) -> bool:
tokens = set(re_split_words(message))
return any(word in tokens or f"{word} around" in message or f"{word} the room" in message for word in words)
def command_target_id(payload: dict[str, Any], preferred_words: set[str] | None = None) -> str:
message = str(payload.get("message") or "").lower()
scene = payload.get("scene") if isinstance(payload.get("scene"), dict) else {}
objects = scene.get("objects") if isinstance(scene.get("objects"), list) else []
preferred_words = preferred_words or set()
message_words = expanded_message_terms(message)
requested_groups = requested_target_groups(message_words)
grouped_objects = []
if requested_groups:
for item in objects:
if not isinstance(item, dict) or not item.get("id"):
continue
terms = object_terms(item)
if any(terms & TARGET_GROUP_ALIASES.get(group, {group}) for group in requested_groups):
grouped_objects.append(item)
scan_objects = grouped_objects or objects
explicit_best: tuple[int, float, dict[str, Any]] | None = None
preferred_best: tuple[int, float, dict[str, Any]] | None = None
for item in scan_objects:
if not isinstance(item, dict) or not item.get("id"):
continue
terms = object_terms(item)
normalized = " ".join(sorted(terms))
exact_score = sum(12 for word in message_words if word in terms)
for color, aliases in TARGET_COLOR_ALIASES.items():
if color in message_words or aliases & message_words:
if aliases & terms:
exact_score += 14
for group in requested_groups:
if TARGET_GROUP_ALIASES.get(group, {group}) & terms:
exact_score += 18
if "soft ball" in message and {"soft", "ball"} <= terms:
exact_score += 8
if "reading lamp" in message and str(item.get("id")) == "reading-lamp":
exact_score += 12
if "tea table" in message and str(item.get("id")) == "tea-table":
exact_score += 12
preferred_score = sum(1 for word in preferred_words if word in terms or word in normalized)
distance = -float(item.get("distanceToPet") or 999)
if exact_score > 0:
candidate = (exact_score + preferred_score, distance, item)
if explicit_best is None or candidate[:2] > explicit_best[:2]:
explicit_best = candidate
elif preferred_score > 0:
candidate = (preferred_score, distance, item)
if preferred_best is None or candidate[:2] > preferred_best[:2]:
preferred_best = candidate
if explicit_best:
return str(explicit_best[2]["id"])
if preferred_best:
return str(preferred_best[2]["id"])
return target_from_payload(payload)
def viewer_target_id(payload: dict[str, Any]) -> str:
scene = payload.get("scene") if isinstance(payload.get("scene"), dict) else {}
objects = scene.get("objects") if isinstance(scene.get("objects"), list) else []
for item in objects:
if not isinstance(item, dict) or not item.get("id"):
continue
terms = object_terms(item)
if {"viewer", "camera", "player", "me", "user", "here"} & terms or str(item.get("id")) == "player-camera":
return str(item.get("id"))
return "player-camera"
def re_split_words(value: str) -> list[str]:
return [word for word in "".join(char if char.isalnum() else " " for char in value).split() if word]
TARGET_GROUP_ALIASES = {
"berry": {"berry", "berries", "food", "snack"},
"ball": {"ball", "sphere", "orb", "round"},
"cube": {"cube", "block", "box"},
"chair": {"chair", "seat", "stool", "sit"},
"table": {"table", "desk"},
"lamp": {"lamp", "light"},
"plant": {"plant", "fern", "sprout", "pot"},
"book": {"book", "notes", "story"},
"clock": {"clock", "timer"},
"bottle": {"bottle"},
"can": {"can", "tin"},
"paper": {"paper"},
"waste": {"waste", "trash", "garbage", "peel"},
"bin": {"bin", "recycle"},
"ramp": {"ramp"},
"domino": {"domino"},
"viewer": {"me", "camera", "viewer", "player", "user", "here"},
}
TARGET_COLOR_ALIASES = {
"blue": {"blue", "cyan", "teal"},
"mint": {"mint", "green", "teal"},
"green": {"green", "mint", "leaf", "fern"},
"yellow": {"yellow", "amber", "honey", "gold", "golden"},
"orange": {"orange", "coral", "ember", "fire"},
"red": {"red", "rose", "pink"},
"purple": {"purple", "violet", "moon"},
"white": {"white", "pale", "cream"},
"black": {"black", "dark"},
"brown": {"brown", "wood", "wooden"},
}
def expanded_message_terms(message: str) -> set[str]:
terms = {word for word in re_split_words(message) if len(word) >= 3}
expanded = set(terms)
for aliases in TARGET_GROUP_ALIASES.values():
if aliases & terms:
expanded |= aliases
for aliases in TARGET_COLOR_ALIASES.values():
if aliases & terms:
expanded |= aliases
return expanded
def requested_target_groups(message_words: set[str]) -> set[str]:
return {group for group, aliases in TARGET_GROUP_ALIASES.items() if aliases & message_words}
def object_terms(item: dict[str, Any]) -> set[str]:
fields = [
str(item.get("id") or ""),
str(item.get("kind") or ""),
str(item.get("name") or ""),
" ".join(str(tag) for tag in (item.get("tags") or [])),
" ".join(str(affordance) for affordance in (item.get("affordances") or [])),
]
terms = set(re_split_words(" ".join(fields).lower().replace("-", " ")))
object_id = str(item.get("id") or "").lower()
kind = str(item.get("kind") or "").lower()
if kind == "ball":
terms.update({"sphere", "orb", "round", "toy"})
elif kind == "berry":
terms.update({"berries", "food", "snack", "sphere", "round"})
elif kind == "cube":
terms.update({"block", "box"})
elif kind == "chair":
terms.update({"seat", "furniture"})
elif kind == "table":
terms.update({"desk", "furniture"})
elif kind == "lamp":
terms.update({"light"})
elif kind == "plant":
terms.update({"fern", "sprout", "pot", "green"})
elif kind == "recycle-bin":
terms.update({"bin", "recycle", "trash", "waste"})
if object_id == "soft-ball":
terms.update({"yellow", "gold", "golden", "soft", "ball", "sphere", "orb"})
elif object_id == "moon-ball":
terms.update({"moon", "pale", "mint", "blue", "purple", "ball", "sphere"})
elif object_id == "beach-orb":
terms.update({"beach", "white", "pale", "orb", "ball", "sphere"})
if "blue" in object_id:
terms.update({"blue", "cyan", "teal"})
if "mint" in object_id:
terms.update({"mint", "green", "teal"})
if "coral" in object_id:
terms.update({"coral", "orange", "red"})
if "honey" in object_id:
terms.update({"honey", "yellow", "gold", "golden"})
if "amber" in object_id:
terms.update({"amber", "yellow", "orange", "gold", "golden"})
if "ember" in object_id or "fire" in object_id:
terms.update({"ember", "fire", "orange", "red", "warm"})
if "rose" in object_id:
terms.update({"rose", "red", "pink"})
if "reading-lamp" in object_id:
terms.update({"reading", "blue", "cyan", "lamp", "light"})
elif "lamp" in object_id:
terms.update({"yellow", "warm", "lamp", "light"})
if "fern" in object_id or "sprout" in object_id:
terms.update({"green", "plant", "leaf"})
if "paper" in object_id:
terms.update({"paper", "white", "waste", "trash", "sphere"})
if "can" in object_id:
terms.update({"can", "tin", "metal", "waste"})
if "bottle" in object_id:
terms.update({"bottle", "blue", "waste"})
if "peel" in object_id:
terms.update({"peel", "banana", "yellow", "waste"})
return terms
def cosmetic_spell(name: str, target_id: str, color: str) -> dict[str, Any]:
return {
"spellName": name,
"ops": [{"op": "spawn_particle", "targetId": target_id, "durationMs": 700, "color": color}],
}
def mark_grounded(action: dict[str, Any], command: str, target_id: str) -> None:
debug = action.setdefault("debug", {})
if isinstance(debug, dict):
debug["commandCoercion"] = command
debug["groundedTargetId"] = target_id
def mark_combo(action: dict[str, Any], combo: str) -> None:
debug = action.setdefault("debug", {})
if isinstance(debug, dict):
debug["postActionCombo"] = combo