feat(conversations): pre-SDK rows read from canonical messages, implied titles, markdown adopts them by first prompt

This commit is contained in:
hh
2026-08-29 01:44:05 +02:00
parent 0cc2c5291f
commit 0479d7cdda
5 changed files with 145 additions and 6 deletions
+23
View File
@@ -18,6 +18,7 @@ from claude_agent_sdk import (
from httpx import ASGITransport, AsyncClient
from test_conversations import ScriptedClient, World
from beaver_gateway.core.conversation_store import rewrite_messages
from beaver_gateway.core.auth import TokenStore
from beaver_gateway.core.registry import McpRegistry
from beaver_gateway.core.transcript import build_entries
@@ -397,3 +398,25 @@ async def test_admin_login_hands_out_the_ui_bearer(world: World) -> None:
assert me.status_code == 200
assert (await http.post("/admin/auth/logout")).status_code == 204
assert (await http.get("/admin/auth/session")).status_code == 401
async def test_pre_sdk_rows_show_canonical_history_and_a_title(world: World) -> None:
api = Api(world)
conv = await world.conversations.create(kind="deep", agent="d", origin="markdown")
async with world.db.session() as session:
await rewrite_messages(
session,
conversation_id=cast("int", conv.id),
messages=[
{"role": "user", "content": "так смотри, план на май\nвторая строка"},
{"role": "assistant", "content": [{"type": "text", "text": "ок"}]},
],
)
rows = (await api.get("/conversations"))["conversations"]
assert [r["title"] for r in rows if r["id"] == conv.external_id] == [
"так смотри, план на май"
]
shown = await api.get(f"/conversations/{conv.external_id}")
assert shown["title"] == "так смотри, план на май" and shown["session_id"] is None
history = await api.get(f"/conversations/{conv.external_id}/history")
assert [m["role"] for m in history["messages"]] == ["user", "assistant"]
+30 -1
View File
@@ -1,13 +1,14 @@
import asyncio
import tempfile
from pathlib import Path
from typing import cast
import frontmatter
import httpx
import pytest
from beaver_gateway.core.auth import TokenStore
from beaver_gateway.core.conversation_store import load_messages
from beaver_gateway.core.conversation_store import load_messages, rewrite_messages
from beaver_gateway.core.gateway_tools import _tools
from beaver_gateway.core.registry import McpRegistry
from beaver_gateway.frontends.anthropic import AnthropicMessagesFrontend
@@ -255,3 +256,31 @@ async def test_markdown_edited_reply_reseeds_the_session(stack: Stack) -> None:
async with stack.world.db.session() as session:
stored = await load_messages(session, conversation_id=1)
assert stored[1]["content"] == [{"type": "text", "text": "penguin"}]
async def test_markdown_adopts_a_pre_sdk_conversation(stack: Stack) -> None:
world = stack.world
old = await world.conversations.create(kind="deep", agent="d", origin="markdown")
async with world.db.session() as session:
await rewrite_messages(
session,
conversation_id=cast("int", old.id),
messages=[
{"role": "user", "content": "hello"},
{"role": "assistant", "content": "ok:hello"},
],
)
content = "### User:\n\nhello\n\n---\n\n### Assistant:\n\nok:hello\n\n---\n\n### User:\n\nnext\n"
async with stack.client(stack.markdown) as c:
r = await c.post(
"/chat",
json={"filename": "old.md", "agent": "d", "content": content},
headers=AUTH,
)
assert r.status_code == 200, r.text
assert f"conversation_id: {old.external_id}" in r.json()["new_content"]
assert len(await world.conversations.find(kind="deep")) == 1
bindings = await world.conversations.bindings(old)
assert [(b.frontend, b.external_id) for b in bindings] == [("markdown", "old.md")]
assert ScriptedClient.instances[-1].prompts == ["next"]
assert "ok:hello" in repr(vars(world.store))