feat(ui,api): strip board redesign - island, rail by day, context view, server search, vault graph
This commit is contained in:
1 parent
85b14e2c2f
commit
025f2dbc3f
60 files changed
+5071
-2347
No files matched your search
@@ -8,6 +8,8 @@ from datetime import UTC, datetime
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
from uuid import uuid4
|
||||
|
||||
from sqlalchemy import String, func
|
||||
from sqlalchemy import cast as sa_cast
|
||||
from sqlmodel import col, select
|
||||
|
||||
from beaver_gateway.backends.transcript import (
|
||||
@@ -23,6 +25,7 @@ from beaver_gateway.storage.models import (
|
||||
ConversationBinding,
|
||||
ConversationMessage,
|
||||
RateLimit,
|
||||
TranscriptEntry,
|
||||
Usage,
|
||||
)
|
||||
|
||||
@@ -132,6 +135,30 @@ class Rows(State):
|
||||
async with self._db.session() as session:
|
||||
return list((await session.exec(stmt)).all())
|
||||
|
||||
async def search(self, query: str, *, limit: int = 20) -> list[Conversation]:
|
||||
needle = f"%{query}%"
|
||||
by_title = select(Conversation.id).where(col(Conversation.title).ilike(needle))
|
||||
by_first = select(ConversationMessage.conversation_id).where(
|
||||
ConversationMessage.seq == 0,
|
||||
col(ConversationMessage.content_json).ilike(needle),
|
||||
)
|
||||
by_entry = (
|
||||
select(Conversation.id)
|
||||
.join(
|
||||
TranscriptEntry,
|
||||
col(TranscriptEntry.session_id) == col(Conversation.session_id),
|
||||
)
|
||||
.where(sa_cast(col(TranscriptEntry.entry), String).ilike(needle))
|
||||
)
|
||||
stmt = (
|
||||
select(Conversation)
|
||||
.where(col(Conversation.id).in_(by_title.union(by_first, by_entry)))
|
||||
.order_by(col(Conversation.id).desc())
|
||||
.limit(limit)
|
||||
)
|
||||
async with self._db.session() as session:
|
||||
return list((await session.exec(stmt)).all())
|
||||
|
||||
async def bindings(self, conv: Conversation) -> list[ConversationBinding]:
|
||||
async with self._db.session() as session:
|
||||
result = await session.exec(
|
||||
@@ -317,6 +344,7 @@ class Rows(State):
|
||||
async def describe(self, conv: Conversation) -> dict[str, Any]:
|
||||
out = self.public(conv)
|
||||
out["title"] = await self.implied_title(conv)
|
||||
out["context_tokens"] = await self.context_tokens(conv)
|
||||
parent = await self.get_row(conv.parent_id) if conv.parent_id else None
|
||||
out["parent"] = parent.external_id if parent is not None else None
|
||||
out["bindings"] = [
|
||||
@@ -359,6 +387,25 @@ class Rows(State):
|
||||
).first()
|
||||
return context_of(row)
|
||||
|
||||
async def context_tokens_by_id(self, ids: Iterable[str]) -> dict[str, int]:
|
||||
wanted = list(ids)
|
||||
if not wanted:
|
||||
return {}
|
||||
latest = (
|
||||
select(func.max(Usage.id))
|
||||
.where(col(Usage.conversation_id).in_(wanted))
|
||||
.group_by(Usage.conversation_id)
|
||||
)
|
||||
async with self._db.session() as session:
|
||||
rows = (
|
||||
await session.exec(select(Usage).where(col(Usage.id).in_(latest)))
|
||||
).all()
|
||||
return {
|
||||
cast("str", row.conversation_id): context_of(row)
|
||||
for row in rows
|
||||
if row.conversation_id
|
||||
}
|
||||
|
||||
async def usage_tokens(self, since: datetime) -> int:
|
||||
async with self._db.session() as session:
|
||||
rows = (
|
||||
|
||||
Reference in new issue
Block a user