fix
This commit is contained in:
@@ -217,10 +217,16 @@ async def _apply_diff(world: World, diff: list[dict[str, Any]]) -> None:
|
||||
"""Apply a propose_changes diff to the world.
|
||||
|
||||
Supported path formats:
|
||||
- `environment.<field_path>` → apply_patch to world.environment
|
||||
- `world.name` → set world.name
|
||||
- `world.description` → set world.description
|
||||
- `world.language` → set world.language
|
||||
- `schemas` → replace entire world.schemas
|
||||
- `schemas.<type>` → replace a single schema type
|
||||
- `environment.<field_path>` → apply_patch to world.environment
|
||||
- `environment` → replace entire world.environment
|
||||
- `player.<field>` → shorthand for environment.player.<field>
|
||||
- `current_location` → shorthand for environment.current_location
|
||||
- `plot_rails.<field>` → shorthand for environment.plot_rails.<field>
|
||||
"""
|
||||
from app.core.state_validator import apply_patch
|
||||
|
||||
@@ -231,25 +237,69 @@ async def _apply_diff(world: World, diff: list[dict[str, Any]]) -> None:
|
||||
path = d.get("path", "") or ""
|
||||
op = d.get("op", "replace")
|
||||
new = d.get("new")
|
||||
if path.startswith("environment."):
|
||||
field = path[len("environment."):]
|
||||
env_patch[field] = new
|
||||
elif path == "world.name":
|
||||
if isinstance(new, str):
|
||||
old = d.get("old") # noqa: F841 — not used but part of the schema
|
||||
|
||||
# Skip if new is empty dict {} (model sometimes returns empty)
|
||||
if isinstance(new, dict) and not new and op == "replace":
|
||||
_logger.warning("apply_diff_skip_empty", path=path)
|
||||
continue
|
||||
if new is None and op == "replace":
|
||||
continue
|
||||
|
||||
# World-level fields
|
||||
if path == "world.name" or path == "name":
|
||||
if isinstance(new, str) and new.strip():
|
||||
world.name = new
|
||||
elif path == "world.description":
|
||||
if new is None or isinstance(new, str):
|
||||
elif path == "world.description" or path == "description":
|
||||
if isinstance(new, str):
|
||||
world.description = new
|
||||
elif path == "world.language" or path == "language":
|
||||
if isinstance(new, str):
|
||||
world.language = new
|
||||
# Schemas
|
||||
elif path == "schemas":
|
||||
if isinstance(new, list):
|
||||
world.schemas = new
|
||||
elif path.startswith("schemas."):
|
||||
# For simplicity, replace entire schemas
|
||||
if isinstance(new, list):
|
||||
world.schemas = new
|
||||
# Environment (full replace)
|
||||
elif path == "environment":
|
||||
if isinstance(new, dict):
|
||||
world.environment = new
|
||||
# Environment field paths
|
||||
elif path.startswith("environment."):
|
||||
field = path[len("environment."):]
|
||||
env_patch[field] = new
|
||||
# Shorthand: player.xxx → environment.player.xxx
|
||||
elif path.startswith("player."):
|
||||
field = path[len("player."):]
|
||||
env_patch[f"player.{field}"] = new
|
||||
elif path == "player":
|
||||
if isinstance(new, dict):
|
||||
env_patch["player"] = new
|
||||
# Shorthand: current_location
|
||||
elif path == "current_location":
|
||||
if isinstance(new, str):
|
||||
env_patch["current_location"] = new
|
||||
elif isinstance(new, dict) and "name" in new:
|
||||
env_patch["current_location"] = new["name"]
|
||||
# Shorthand: plot_rails.xxx
|
||||
elif path.startswith("plot_rails."):
|
||||
field = path[len("plot_rails."):]
|
||||
env_patch[f"plot_rails.{field}"] = new
|
||||
elif path == "plot_rails":
|
||||
if isinstance(new, dict):
|
||||
env_patch["plot_rails"] = new
|
||||
else:
|
||||
_logger.warning("apply_diff_unknown_path", path=path)
|
||||
|
||||
if env_patch:
|
||||
new_env, errors = apply_patch(dict(world.environment or {}), env_patch)
|
||||
if not errors:
|
||||
world.environment = new_env
|
||||
# Sync plot_rails column
|
||||
if isinstance(new_env.get("plot_rails"), dict):
|
||||
world.plot_rails = new_env["plot_rails"]
|
||||
else:
|
||||
_logger.warning("apply_diff_errors", errors=errors)
|
||||
|
||||
Reference in New Issue
Block a user