feat(envelope,conversations): recall hook under the user text, user_sink for the setup's reply log
This commit is contained in:
+69
-1
@@ -5,7 +5,8 @@ from pathlib import Path
|
||||
|
||||
from test_conversations import ScriptedClient, World, world
|
||||
|
||||
from beaver_gateway.core.envelope import HEADER, Envelope, render
|
||||
from beaver_gateway.core.conversations import UserSaid
|
||||
from beaver_gateway.core.envelope import HEADER, Envelope, RecallContext, render
|
||||
from beaver_gateway.core.watch import Change, VaultWatch, WatchRules
|
||||
|
||||
__all__ = ["world"]
|
||||
@@ -148,3 +149,70 @@ async def test_master_turn_gets_envelope_after_text_and_before_injects(
|
||||
await world.settle(branch, 1)
|
||||
assert "[конверт" not in ScriptedClient.instances[-1].prompts[0]
|
||||
await asyncio.sleep(0)
|
||||
|
||||
|
||||
async def test_recall_lines_follow_the_vault_block_and_reach_branches(
|
||||
world: World,
|
||||
) -> None:
|
||||
root, watch = vault()
|
||||
seen: list[tuple[str, str]] = []
|
||||
|
||||
def recall(ctx: RecallContext) -> str | None:
|
||||
seen.append((ctx.kind, ctx.text))
|
||||
return "👤 Прохор - карточка `люди/Прохор.md`" if "Прохор" in ctx.text else None
|
||||
|
||||
noted: list[UserSaid] = []
|
||||
world.conversations._envelope = Envelope(watch=watch, tz="UTC", recall=recall) # noqa: SLF001
|
||||
world.conversations._user_sink = noted.append # noqa: SLF001
|
||||
master = await world.conversations.create(kind="master", agent="a", origin="test")
|
||||
append(root / "люди" / "Прохор.md", "новое\n")
|
||||
watch.note(root / "люди" / "Прохор.md")
|
||||
await world.conversations.post(master, "что там у Прохор")
|
||||
await world.settle(master, 1)
|
||||
prompt = ScriptedClient.instances[0].prompts[0]
|
||||
head, _, rest = prompt.partition("\n\n")
|
||||
assert head == "что там у Прохор"
|
||||
lines = rest.splitlines()
|
||||
assert lines[0] == HEADER
|
||||
assert "люди/Прохор.md (+1)" in rest
|
||||
assert lines[-1] == "👤 Прохор - карточка `люди/Прохор.md`"
|
||||
assert rest.index("люди/Прохор.md (+1)") < rest.index("👤 Прохор")
|
||||
assert seen == [("master", "что там у Прохор")]
|
||||
assert [(m.kind, m.text) for m in noted] == [("master", "что там у Прохор")]
|
||||
|
||||
branch = await world.conversations.spawn(
|
||||
kind="branch", parent=master, seed="clean", text="про Прохор подробнее"
|
||||
)
|
||||
await world.settle(branch, 1)
|
||||
branch_prompt = ScriptedClient.instances[-1].prompts[0]
|
||||
assert "про Прохор подробнее\n\n" + HEADER in branch_prompt
|
||||
assert branch_prompt.endswith(f"{HEADER}\n👤 Прохор - карточка `люди/Прохор.md`")
|
||||
assert "vault, изменено" not in branch_prompt
|
||||
# the first branch turn carries the seed line above the text
|
||||
assert seen[-1][0] == "branch" and seen[-1][1].endswith("про Прохор подробнее")
|
||||
assert noted[-1].kind == "branch"
|
||||
|
||||
await world.conversations.post(master, "ничего про людей")
|
||||
await world.settle(master, 2)
|
||||
second = ScriptedClient.instances[0].prompts[1]
|
||||
assert "👤" not in second
|
||||
assert second.partition("\n\n")[2].startswith(HEADER)
|
||||
await asyncio.sleep(0)
|
||||
|
||||
|
||||
async def test_failing_recall_or_sink_never_blocks_the_turn(world: World) -> None:
|
||||
root, watch = vault()
|
||||
|
||||
def boom(_: object) -> str:
|
||||
msg = "nope"
|
||||
raise RuntimeError(msg)
|
||||
|
||||
world.conversations._envelope = Envelope(watch=watch, tz="UTC", recall=boom) # noqa: SLF001
|
||||
world.conversations._user_sink = boom # noqa: SLF001
|
||||
master = await world.conversations.create(kind="master", agent="a", origin="test")
|
||||
await world.conversations.post(master, "hello")
|
||||
await world.settle(master, 1)
|
||||
prompt = ScriptedClient.instances[0].prompts[0]
|
||||
assert prompt.startswith("hello\n\n" + HEADER)
|
||||
assert root.exists()
|
||||
await asyncio.sleep(0)
|
||||
|
||||
Reference in New Issue
Block a user