feat(ui,api): strip board redesign - island, rail by day, context view, server search, vault graph

This commit is contained in:
hh
2026-09-02 03:48:26 +02:00
parent 85b14e2c2f
commit 025f2dbc3f
60 changed files with 5071 additions and 2347 deletions
+89 -1
View File
@@ -29,7 +29,7 @@ from beaver_gateway.frontends.api import ApiFrontend
from beaver_gateway.frontends.api.frontend import build_app as build_api
from beaver_gateway.frontends.base import Frontend, GatewayRuntime
from beaver_gateway.frontends.root import build_root_app
from beaver_gateway.storage.models import RateLimit, Usage
from beaver_gateway.storage.models import RateLimit, TranscriptEntry, Usage
TOKEN = "tok"
HEADERS = {"Authorization": f"Bearer {TOKEN}"}
@@ -525,3 +525,91 @@ async def test_bind_without_a_window_materializes_one(world: World) -> None:
headers=HEADERS,
)
assert unknown.status_code == 400
async def test_search_finds_conversations_and_memory_files(world: World) -> None:
root = Path(tempfile.mkdtemp(prefix="beaver-mem-"))
(root / "notes").mkdir()
(root / "notes" / "studio.md").write_text("# studio\nthe kiln is warm\n")
api = Api(world, memory_root=root)
conv = await world.conversations.create(kind="master", agent="a", origin="test")
await world.conversations.set_title(conv, "kiln schedule")
other = await world.conversations.create(kind="deep", agent="d", origin="test")
await world.conversations.post(other, "go")
await world.settle(other, 1)
other = await world.conversations.get(other.external_id)
assert other is not None and other.session_id is not None
async with world.db.session() as db:
db.add(
TranscriptEntry(
project_key="p",
session_id=other.session_id,
seq=0,
entry={"type": "assistant", "message": {"content": "warm kiln"}},
)
)
await db.commit()
found = await api.get("/search", {"q": "kiln"})
assert {c["id"] for c in found["conversations"]} == {
conv.external_id,
other.external_id,
}
assert found["files"] == [
{"path": "notes/studio.md", "line": 2, "snippet": "the kiln is warm"}
]
short = await api.http.get("/search", params={"q": "k"}, headers=HEADERS)
assert short.status_code == 400
async def test_context_endpoint_reports_prompt_and_files(world: World) -> None:
api = Api(world)
conv = await world.conversations.create(kind="master", agent="a", origin="test")
await world.conversations.post(conv, "go")
await world.settle(conv, 1)
conv = await world.conversations.get(conv.external_id)
assert conv is not None and conv.session_id is not None
await world.store.append(
world.key(conv.session_id),
build_entries(
[
{"role": "user", "content": "go"},
{
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "t1",
"name": "Read",
"input": {"file_path": str(world.root / "note.md")},
}
],
},
{
"role": "user",
"content": [
{"type": "tool_result", "tool_use_id": "t1", "content": "x"}
],
},
],
session_id=conv.session_id,
cwd=str(world.root),
model="m",
),
)
ctx = await api.get(f"/conversations/{conv.external_id}/context", {"prompt": 1})
assert ctx["agent"]["name"] == "a"
assert ctx["prompt"]["granules"][0]["bytes"] == len("hi")
assert ctx["prompt_text"] == "hi"
assert ctx["files"] == [
{
"path": "note.md",
"reads": 1,
"writes": 0,
"other": 0,
"last_at": ctx["files"][0]["last_at"],
}
]
assert ctx["tool_counts"] == {"Read": 1}
assert ctx["turns"] == 1
graph = await api.http.get("/vault/graph", headers=HEADERS)
assert graph.status_code == 404