Files

64 lines
2.4 KiB
Python

"""Fast taskId + goPath history lookup for single-agent deep-link workspaces.
Messages and execution state remain canonical LangGraph threads. This API
reads only the dedicated ``task_deeplink_threads`` cards and never joins or
scans the generic ``threads_meta`` catalogue.
"""
from __future__ import annotations
from fastapi import APIRouter, HTTPException, Query, Request
from pydantic import BaseModel
from app.gateway.deps import get_task_deeplink_thread_store
from app.gateway.routers.threads import ThreadResponse
from deerflow.persistence.task_deeplink_threads.base import is_valid_task_deeplink_go_path
from deerflow.utils.time import coerce_iso
router = APIRouter(
prefix="/api/task-deeplink-threads",
tags=["task-deeplink-threads"],
)
class TaskDeeplinkThreadListResponse(BaseModel):
threads: list[ThreadResponse]
@router.get("", response_model=TaskDeeplinkThreadListResponse)
async def list_task_deeplink_threads(
request: Request,
task_id: str = Query(min_length=1, max_length=128),
go_path: str = Query(min_length=1, max_length=32),
limit: int = Query(default=100, ge=1, le=500),
# b5-1 ?type= partition. Provided (even empty) → only that sub-type;
# omitted → every sub-type of the task/goPath partition (legacy callers).
sub_type: str | None = Query(default=None, max_length=64),
) -> TaskDeeplinkThreadListResponse:
"""Return one shared deep-link history partition, newest first."""
normalized_go_path = go_path.strip().lower()
if not is_valid_task_deeplink_go_path(normalized_go_path):
raise HTTPException(status_code=422, detail="Invalid task deep-link goPath")
store = get_task_deeplink_thread_store(request)
rows = await store.list_threads(
task_id.strip(),
normalized_go_path,
limit=limit,
sub_type=sub_type.strip() if sub_type is not None else None,
)
return TaskDeeplinkThreadListResponse(
threads=[
ThreadResponse(
thread_id=row["thread_id"],
status=row.get("status", "idle"),
created_at=coerce_iso(row.get("created_at", "")),
updated_at=coerce_iso(row.get("updated_at", "")),
metadata=row.get("metadata", {}),
values=row.get("values", {}),
interrupts=row.get("interrupts", {}),
)
for row in rows
]
)