Spaces:
Sleeping
Sleeping
| """M4 μ 체 κ΄ν΅ β μ½κΈ° 루ν β κ°μ ν¬μΌ(μ±ν ) β λ³΅κ· β μλ©κΉμ§ ν λ²μ.""" | |
| import json | |
| import pytest | |
| from engine.plugins.logging import TurnLoggingPlugin | |
| from engine.repositories.content import ContentRepository | |
| from engine.repositories.playlog import PlaylogRepository | |
| from engine.services.pocket import PocketService | |
| from engine.services.state import AXIS_DELTA | |
| from engine.services.story import StoryEngine | |
| from tests.fakes import ScriptedLlm, text_response, tool_call, tool_response | |
| def repo(): | |
| return ContentRepository("content") | |
| async def test_full_playthrough_with_pocket(repo, tmp_path): | |
| """E06-09κΉμ§ μ½κ³ β ν¬μΌ μ±ν 2ν΄(μλ ΄) β μν μ»€λ° β μ΄μ΄μ μλ© λλ¬.""" | |
| playlog = PlaylogRepository(tmp_path / "playlog.jsonl") | |
| svc = PocketService( | |
| repo, | |
| plugins=[TurnLoggingPlugin(playlog)], | |
| character_model=ScriptedLlm(script=[ | |
| text_response("β¦κ·Έλ. λμ λ μ¬μ΄μ μΌμ΄μΌ, λ‘λΌ."), | |
| text_response("μ°©νμ§. μ°λ¦¬λΌλ¦¬λ§ κ°μ§νμ."), | |
| text_response("β¦μ΄μ λμ΄. μ무 λ§λ νμ μμ΄."), | |
| ]), | |
| director_model=ScriptedLlm(script=[ | |
| tool_response(tool_call("update_trust", direction="trust")), | |
| text_response("κ³μ"), | |
| tool_response(tool_call("update_trust", direction="trust"), | |
| tool_call("mark_beat", beat="λλ§μ λΉλ° λμ‘°")), | |
| text_response("κ³μ"), | |
| tool_response(tool_call("finish_pocket", reason="goal_reached")), | |
| text_response("μλ ΄"), | |
| ]), | |
| ) | |
| # 1) μ½κΈ° 루ν: E06-09κΉμ§ μ λ’° μ±ν₯μΌλ‘ μ§ν | |
| engine = StoryEngine(repo) | |
| step = engine.start() | |
| while engine.current_id != "E06-09": | |
| if step.choices: | |
| idx = next((i for i, c in enumerate(step.choices) if c.axis == "trust"), | |
| next((i for i, c in enumerate(step.choices) | |
| if c.axis in (None, "neutral")), 0)) | |
| _, step = engine.choose(idx) | |
| else: | |
| step = engine.advance() | |
| trust_before = engine.state.trust_score | |
| # 2) κ°μ ν¬μΌ: μμ μ±ν 3ν΄ β director μλ ΄ (μ΅μ 체λ₯ 3ν΄) | |
| sid = await svc.open("E06-09", engine.state) | |
| t1 = await svc.run_turn(sid, "β¦μ°λ¦¬ λλ§μ μΌμ΄λΌλ κ±°μ§?") | |
| assert not t1.converged and "λ‘λΌ" in t1.reply | |
| t2 = await svc.run_turn(sid, "μμμ΄. μ무μκ²λ λ§νμ§ μμκ².") | |
| assert not t2.converged # μ΅μ 체λ₯ ν΄ λ―Έλ¬ | |
| t3 = await svc.run_turn(sid, "β¦μ. μ½μν κ².") | |
| assert t3.converged and t3.reason == "goal_reached" | |
| # 3) 볡κ·: μ¨μ μν μ»€λ° (μ±ν 2ν΄ = trust +2ΓAXIS_DELTA) | |
| log = await svc.close(sid, engine.state) | |
| assert engine.state.trust_score == trust_before + 2 * AXIS_DELTA | |
| assert log.beats_hit == ["λλ§μ λΉλ° λμ‘°"] | |
| # 4) μ΄μ΄μ μ½κΈ° β μλ© (μ λ’° μ±ν₯ μ μ§ β μμ) | |
| while step.ending is None: | |
| if step.choices: | |
| idx = next((i for i, c in enumerate(step.choices) if c.axis == "trust"), | |
| next((i for i, c in enumerate(step.choices) | |
| if c.axis in (None, "neutral")), 0)) | |
| _, step = engine.choose(idx) | |
| else: | |
| step = engine.advance() | |
| assert step.ending.id == "ending_eternal" | |
| assert "E06-10" in engine.visited # λλ¬μ μ μ±ν κ³Ό 무κ΄νκ² ν΅κ³Ό | |
| # 5) ν΄ λ‘κ·Έ: μ μ μ λ ₯/μ΄λ²€νΈ/ν΄ μμ½μ΄ κΈ°λ‘λ¨ (μ°κ΅¬ λ°μ΄ν°) | |
| records = [json.loads(l) for l in (tmp_path / "playlog.jsonl").read_text().splitlines()] | |
| kinds = {r["kind"] for r in records} | |
| assert {"user_input", "event", "turn_summary"} <= kinds | |
| tool_events = [r for r in records if r.get("tool_calls")] | |
| assert any(c["tool"] == "finish_pocket" for r in tool_events for c in r["tool_calls"]) | |