Better tools params handling
This commit is contained in:
parent
f36387f1bf
commit
f98392478b
@ -20,9 +20,38 @@ from engine_lib.paths import CHARACTER_CREATION_PATH, RULES_INJECTION_PATH
|
|||||||
|
|
||||||
|
|
||||||
class GameEngine:
|
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):
|
def __init__(self, session_dir: str | Path | None = None):
|
||||||
self.config = config.load_config()
|
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(
|
def generate_turn(
|
||||||
self,
|
self,
|
||||||
player_action: str | None = None,
|
player_action: str | None = None,
|
||||||
@ -130,10 +159,10 @@ class GameEngine:
|
|||||||
|
|
||||||
for tc in tool_calls:
|
for tc in tool_calls:
|
||||||
name = tc.get("tool", "")
|
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":
|
if name == "narrative":
|
||||||
text = args.get("text", "")
|
text = args.get("text", "") or ""
|
||||||
if text:
|
if text:
|
||||||
book_log = (book_log + "\n\n" + text) if book_log else text
|
book_log = (book_log + "\n\n" + text) if book_log else text
|
||||||
elif name == "finalize_turn":
|
elif name == "finalize_turn":
|
||||||
@ -148,13 +177,26 @@ class GameEngine:
|
|||||||
if args.get("log_entry"):
|
if args.get("log_entry"):
|
||||||
log_entry = args["log_entry"]
|
log_entry = args["log_entry"]
|
||||||
elif name == "read_rules":
|
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")
|
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.parent.mkdir(parents=True, exist_ok=True)
|
||||||
RULES_INJECTION_PATH.write_text(result)
|
RULES_INJECTION_PATH.write_text(result)
|
||||||
else:
|
else:
|
||||||
state_changes.append(tc)
|
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
|
# Meta check — reject if state changes produced for a meta action
|
||||||
if is_meta and state_changes:
|
if is_meta and state_changes:
|
||||||
state.append_llm_log(f"\n[TURN META REJECTED] state changes not allowed for meta action")
|
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:
|
for tc in tool_calls:
|
||||||
name = tc.get("tool", "")
|
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"):
|
if name in ("narrative", "read_rules"):
|
||||||
pass
|
pass
|
||||||
|
|||||||
10
tools/run.py
10
tools/run.py
@ -325,7 +325,13 @@ class ChaosTUI(App):
|
|||||||
if result.error:
|
if result.error:
|
||||||
self._show_error(result.error, result.debug_info)
|
self._show_error(result.error, result.debug_info)
|
||||||
return
|
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)
|
turn_num = state.archive_turn(result.book_log)
|
||||||
if result.log_entry:
|
if result.log_entry:
|
||||||
state.append_log(f"- **Turn {turn_num}** — {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]
|
summary = result.book_log.strip().split(chr(10))[0][:80]
|
||||||
state.append_log(f"- **Turn {turn_num}** — {summary}")
|
state.append_log(f"- **Turn {turn_num}** — {summary}")
|
||||||
result.book_log = load_book_pages()[-1]
|
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.append_log(f"- {result.log_entry}")
|
||||||
state.apply_state(result)
|
state.apply_state(result)
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user