Better tools params handling

This commit is contained in:
Dejvino 2026-07-04 22:01:00 +02:00
parent f36387f1bf
commit f98392478b
2 changed files with 54 additions and 6 deletions

View File

@ -20,9 +20,38 @@ from engine_lib.paths import CHARACTER_CREATION_PATH, RULES_INJECTION_PATH
class GameEngine:
REQUIRED_TOOL_ARGS: dict[str, list[str]] = {
"add_to_inventory": ["item"],
"remove_from_inventory": ["item"],
"replace_gear": ["before", "after"],
"add_note": ["note"],
"replace_note": ["before", "after"],
"world_update": ["content"],
"journal_update": ["add", "done"],
}
def __init__(self, session_dir: str | Path | None = None):
self.config = config.load_config()
def _check_required_tool_args(self, state_changes: list[dict]) -> str:
"""Check that all state-changing tool calls have required args. Returns empty string if OK, or a description of what's missing."""
missing = []
for tc in state_changes:
name = tc.get("tool", "")
req = self.REQUIRED_TOOL_ARGS.get(name)
if not req:
continue
args = tc.get("args") or {k: v for k, v in tc.items() if k != "tool"}
if name == "journal_update":
if not args.get("add") and not args.get("done"):
missing.append(f"{name}: needs at least one of `add` or `done`")
continue
for arg in req:
val = args.get(arg)
if val is None or (isinstance(val, str) and not val.strip()):
missing.append(f"{name}: missing required `{arg}`")
return "; ".join(missing)
def generate_turn(
self,
player_action: str | None = None,
@ -130,10 +159,10 @@ class GameEngine:
for tc in tool_calls:
name = tc.get("tool", "")
args = tc.get("args", {})
args = tc.get("args") or {k: v for k, v in tc.items() if k != "tool"}
if name == "narrative":
text = args.get("text", "")
text = args.get("text", "") or ""
if text:
book_log = (book_log + "\n\n" + text) if book_log else text
elif name == "finalize_turn":
@ -148,13 +177,26 @@ class GameEngine:
if args.get("log_entry"):
log_entry = args["log_entry"]
elif name == "read_rules":
result = execute_tool("read_rules", {})
cat = args.get("category", "mechanics")
result = execute_tool("read_rules", {"category": cat})
state.append_llm_log(f"\n[READ RULES] loaded {len(result)} chars")
RULES_INJECTION_PATH.parent.mkdir(parents=True, exist_ok=True)
RULES_INJECTION_PATH.write_text(result)
else:
state_changes.append(tc)
# Required args check — reject if any state-changing tool is missing required arguments
missing_args = self._check_required_tool_args(state_changes)
if missing_args:
state.append_llm_log(f"\n[TURN MISSING ARGS] {missing_args}")
if attempt < MAX_RETRIES:
feedback = f"The following tool calls are missing required arguments: {missing_args}. Include all required fields for each tool and regenerate."
state.append_llm_log(f"\n[TURN REGENERATE] (missing args) attempt {attempt + 2}")
if on_action:
on_action("DM is consulting the fates...")
continue
state.append_llm_log(f"\n[TURN MISSING ARGS EXCEEDED] accepting despite missing args")
# Meta check — reject if state changes produced for a meta action
if is_meta and state_changes:
state.append_llm_log(f"\n[TURN META REJECTED] state changes not allowed for meta action")
@ -257,7 +299,7 @@ class GameEngine:
for tc in tool_calls:
name = tc.get("tool", "")
args = tc.get("args", {})
args = tc.get("args") or {k: v for k, v in tc.items() if k != "tool"}
if name in ("narrative", "read_rules"):
pass

View File

@ -325,7 +325,13 @@ class ChaosTUI(App):
if result.error:
self._show_error(result.error, result.debug_info)
return
if result.book_log and not result.is_meta:
if result.is_meta:
self._display_scene(result)
self._enable_input()
return
if result.book_log:
turn_num = state.archive_turn(result.book_log)
if result.log_entry:
state.append_log(f"- **Turn {turn_num}** — {result.log_entry}")
@ -333,7 +339,7 @@ class ChaosTUI(App):
summary = result.book_log.strip().split(chr(10))[0][:80]
state.append_log(f"- **Turn {turn_num}** — {summary}")
result.book_log = load_book_pages()[-1]
elif result.log_entry and not result.is_meta:
elif result.log_entry:
state.append_log(f"- {result.log_entry}")
state.apply_state(result)