Spaces:
Sleeping
Sleeping
File size: 4,017 Bytes
1c9c13f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | """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
@pytest.fixture(scope="module")
def repo():
return ContentRepository("content")
@pytest.mark.asyncio
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"])
|