feat(injects,conversations,scheduler,gateway_tools,api): wake priority, master and parent aliases, scheduled injects start a turn

This commit is contained in:
hh
2026-08-30 20:34:12 +02:00
parent 878f7d6473
commit 3406e2e178
11 changed files with 215 additions and 47 deletions
+61
View File
@@ -781,3 +781,64 @@ async def test_observer_publishes_tool_results_for_the_panel(world: World) -> No
assert result["parent_tool_use_id"] == "toolu_0"
assert result["turn_id"] == "t1" and result["is_error"] is False
assert result["content"] == "a\nb"
async def test_wake_injects_start_a_turn_and_take_normals_along(world: World) -> None:
conv = await world.conversations.create(kind="master", agent="a", origin="test")
await world.conversations.inject(conv, "digest", urgency="normal", origin="watch")
await asyncio.sleep(0.2)
assert await world.statuses(conv) == [("normal", "queued")]
await world.conversations.inject(
conv, "reminder", urgency="wake", origin="schedule"
)
await world.settle(conv, 2)
prompts = ScriptedClient.instances[0].prompts
assert len(prompts) == 1
assert prompts[0].startswith("[инжект: schedule")
assert "reminder" in prompts[0]
assert "[инжект: watch" in prompts[0]
assert "digest" in prompts[0]
assert await world.statuses(conv) == [("normal", "done"), ("wake", "done")]
async def test_wake_does_not_cut_a_running_turn(world: World) -> None:
conv = await world.conversations.create(kind="master", agent="a", origin="test")
ScriptedClient.hold = asyncio.Event()
await world.conversations.post(conv, "first")
await asyncio.sleep(0.2)
await world.conversations.inject(conv, "later", urgency="wake", origin="schedule")
await asyncio.sleep(0.2)
assert await world.statuses(conv) == [("user", "running"), ("wake", "queued")]
assert not ScriptedClient.instances[0].interrupted
assert await world.conversations.busy(conv)
ScriptedClient.hold.set()
await world.settle(conv, 2)
assert await world.statuses(conv) == [("user", "done"), ("wake", "done")]
assert ScriptedClient.instances[0].prompts[1].endswith("later")
async def test_resolve_aliases_master_and_parent(world: World) -> None:
master = await world.conversations.create(kind="master", agent="a", origin="test")
branch = await world.conversations.create(
kind="branch", agent="a", parent=master, origin="test"
)
resolve = world.conversations.resolve
assert (await resolve("master")).id == master.id
assert (await resolve(" master ")).id == master.id
assert (await resolve("parent", origin=branch)).id == master.id
assert await resolve("parent", origin=master) is None
assert await resolve("parent") is None
assert (await resolve(branch.external_id)).id == branch.id
assert await resolve("nope") is None
await world.conversations.set_status(master, "closed")
assert await resolve("master") is None
async def test_inject_into_a_closed_master_lands_in_the_open_one(world: World) -> None:
old = await world.conversations.create(kind="master", agent="a", origin="test")
old = await world.conversations.set_status(old, "closed")
new = await world.conversations.create(kind="master", agent="a", origin="test")
item = await world.conversations.inject(old, "late", urgency="normal", origin="x")
assert item.conversation_id == new.id
assert await world.statuses(old) == []
assert await world.statuses(new) == [("normal", "queued")]