human hand off bug

This commit is contained in:
debu-2 2026-10-06 18:27:06 +05:30
parent 223f846782
commit 6e7a0b9539
22 changed files with 1040 additions and 336 deletions

View file

@ -11,7 +11,7 @@ from app.database import get_mongo_database
from app.models import Account
from app.routers.auth import get_current_account
from app.routers.emails import decode_cursor, encode_cursor, summarize
from app.schemas import MessageRead, ThreadPage, ThreadRead, ThreadSummary
from app.schemas import MessageRead, ThreadPage, ThreadRead, ThreadSummary, parse_api_datetime, utc_iso
from app.services.mailbox_scope import apply_external_scope
from app.services.mime_parser import parse_mime
from app.services.reply_extractor import reply_fields_for_message
@ -23,7 +23,7 @@ router = APIRouter(prefix="/threads", tags=["threads"])
def encode_thread_cursor(thread: dict) -> str:
value = json.dumps(
{
"latest_at": thread["latest_at"].isoformat(),
"latest_at": utc_iso(thread["latest_at"]),
"id": str(thread["_id"]),
},
separators=(",", ":"),
@ -35,7 +35,7 @@ def decode_thread_cursor(value: str) -> tuple[datetime, ObjectId]:
try:
padded = value + "=" * (-len(value) % 4)
payload = json.loads(base64.urlsafe_b64decode(padded).decode())
return datetime.fromisoformat(payload["latest_at"]), ObjectId(payload["id"])
return parse_api_datetime(payload["latest_at"]), ObjectId(payload["id"])
except (ValueError, TypeError, KeyError, json.JSONDecodeError) as error:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
@ -188,9 +188,10 @@ async def list_threads(
}
)
pipeline.append({"$sort": {"latest_at": -1, "_id": -1}})
page_stages: list[dict] = []
if cursor:
latest_at, thread_id = decode_thread_cursor(cursor)
pipeline.append(
page_stages.append(
{
"$match": {
"$or": [
@ -200,8 +201,8 @@ async def list_threads(
}
}
)
pipeline.append({"$limit": limit + 1})
pipeline.append(
page_stages.append({"$limit": limit + 1})
page_stages.append(
{
"$addFields": {
"latest_entry": {
@ -215,8 +216,19 @@ async def list_threads(
}
}
)
cursor = await database.mailbox_entries.aggregate(pipeline)
rows = [row async for row in cursor]
pipeline.append(
{
"$facet": {
"total": [{"$count": "count"}],
"page": page_stages,
}
}
)
aggregate = await database.mailbox_entries.aggregate(pipeline)
facets = [row async for row in aggregate]
facet = facets[0] if facets else {"total": [], "page": []}
total = int((facet.get("total") or [{}])[0].get("count") or 0)
rows = list(facet.get("page") or [])
has_more = len(rows) > limit
rows = rows[:limit]
items = [thread_summary_from_group(row, mailbox) for row in rows]
@ -225,7 +237,7 @@ async def list_threads(
next_cursor = encode_thread_cursor(
{"latest_at": rows[-1]["latest_at"], "_id": rows[-1]["_id"]}
)
return ThreadPage(items=items, next_cursor=next_cursor)
return ThreadPage(items=items, next_cursor=next_cursor, total=total)
async def message_read(