diff --git a/tools/engine.py b/tools/engine.py index b1c1101..c3c121b 100644 --- a/tools/engine.py +++ b/tools/engine.py @@ -38,6 +38,7 @@ class GameEngine: state.append_llm_log(f"Player: {player_action}") if recent_narrative is None: recent_narrative = state.read_recent_book(2) + session_log = state.read_recent_log() die_roll = random.randint(1, 6) state.append_llm_log(f"Dice: {die_roll} (1d6)") @@ -51,9 +52,7 @@ class GameEngine: on_debug("config", {"model": model, "temperature": lm.get("temperature"), "max_tokens": lm.get("max_tokens"), "strategy": "tools"}) if player_action: - story = state.read_recent_book() - log = state.read_recent_log() - valid, reason = validate_action(player_action, story=story, log=log, on_debug=on_debug) + valid, reason = validate_action(player_action, story=recent_narrative, log=session_log, on_debug=on_debug) if valid: state.append_llm_log(f"\n[VALIDATION PASSED] {reason}") else: @@ -64,10 +63,8 @@ class GameEngine: user_prompt=f"*Your action:\n\t\"{player_action}\"\nwas rejected:\n\t{reason}*", ) - system = build_system_prompt() + system = build_system_prompt(recent_narrative=recent_narrative, recent_log=session_log) parts = [] - if recent_narrative: - parts.append(f"## Recent Narrative\n{recent_narrative}") if player_action: parts.append(f"## Player's Request\n{player_action}") if not player_action and not recent_narrative: diff --git a/tools/engine_lib/context.py b/tools/engine_lib/context.py index 44fdc7d..0bee4d9 100644 --- a/tools/engine_lib/context.py +++ b/tools/engine_lib/context.py @@ -5,12 +5,12 @@ from .prompts import SYSTEM_PROMPT from . import state -def build_system_prompt() -> str: +def build_system_prompt(recent_narrative: str | None = None, recent_log: str | None = None) -> str: """Assemble the system prompt with current game state.""" char = state.read_file(CHAR_PATH) or "*No character sheet.*" world = state.truncate_world(state.read_file(WORLD_PATH) or "") or "*No world state.*" - log = state.read_recent_log() - story = state.read_recent_book() + log = recent_log if recent_log is not None else state.read_recent_log() + story = recent_narrative if recent_narrative is not None else state.read_recent_book(2) return SYSTEM_PROMPT.substitute( - character=char, world=world, log=log, story=story + character=char, world=world, log=log, story=story, ) diff --git a/tools/engine_lib/state.py b/tools/engine_lib/state.py index 989a107..125f066 100644 --- a/tools/engine_lib/state.py +++ b/tools/engine_lib/state.py @@ -40,8 +40,12 @@ def read_recent_book(max_turns: int = 1) -> str: if not text: return "*No prior story.*" turns = text.split("\n## ") + if len(turns) <= 1: + return turns[0] recent = turns[-max_turns:] - return "\n## ".join(recent) if len(turns) > 1 else recent[0] + if not recent[0].startswith("## "): + recent[0] = "## " + recent[0] + return "\n## ".join(recent) def truncate_world(text: str) -> str: diff --git a/tools/engine_lib/validation.py b/tools/engine_lib/validation.py index 6a63122..92dec9c 100644 --- a/tools/engine_lib/validation.py +++ b/tools/engine_lib/validation.py @@ -101,6 +101,4 @@ def validate_action( return False, "Unrecognized" -def auto_prompt(book_log: str = "") -> str: - """Fallback player prompt.""" - return "**What do you do?**" + diff --git a/tools/test_runtime.py b/tools/test_runtime.py index a6cddc9..16daafd 100755 --- a/tools/test_runtime.py +++ b/tools/test_runtime.py @@ -30,7 +30,7 @@ def test_engine_import(): ('engine_lib.state', ['read_file', 'apply_state', 'append_log', 'append_llm_log', 'next_turn_number']), ('engine_lib.tools_handler', ['execute_tool', 'extract_tool_calls', 'TOOL_REGISTRY']), ('engine_lib.llm', ['call_llm']), - ('engine_lib.validation', ['auto_prompt', 'validate_action']), + ('engine_lib.validation', ['validate_action']), ('engine_lib.parsing', ['log_turn_details']), ('engine', ['GameEngine']), ] diff --git a/tools/test_validation.py b/tools/test_validation.py index b2b1827..ff54875 100644 --- a/tools/test_validation.py +++ b/tools/test_validation.py @@ -127,20 +127,6 @@ def test_on_debug_called(mock_call_llm, mock_truncate_world, mock_read_file): print("āœ“ on_debug callback receives action_validation event") -def test_auto_prompt_default(): - from engine_lib.validation import auto_prompt - result = auto_prompt() - assert result == "**What do you do?**" - print("āœ“ auto_prompt() returns default prompt") - - -def test_auto_prompt_with_log(): - from engine_lib.validation import auto_prompt - result = auto_prompt(book_log="Some story text") - assert result == "**What do you do?**" - print("āœ“ auto_prompt() ignores book_log argument") - - if __name__ == "__main__": test_empty_action() test_valid_action() @@ -149,6 +135,4 @@ if __name__ == "__main__": test_llm_returns_bad_json() test_missing_character_sheet() test_on_debug_called() - test_auto_prompt_default() - test_auto_prompt_with_log() print("\nāœ“ All validation tests passed")