39a575617b
Reorganize app/gateway/ with: - common/ - lifespan management - dependencies/ - FastAPI dependency injection (db, checkpointer, repositories, stream_bridge) - services/runs/ - run execution services (facade_factory, input adapters, store operations) - registrar.py - router registration - router.py - main router setup Simplify app.py to use the new modular structure. Remove deprecated utils.py. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
128 lines
3.2 KiB
Python
128 lines
3.2 KiB
Python
"""App-owned request adapter for runs entrypoints."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
|
|
from deerflow.runtime.stream_bridge import JSONValue
|
|
from deerflow.runtime.runs.types import RunIntent
|
|
|
|
type RequestBody = dict[str, JSONValue]
|
|
type RequestQuery = dict[str, str]
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class AdaptedRunRequest:
|
|
"""
|
|
统一的内部请求 DTO.
|
|
|
|
路由层只负责提取 path/query/body,适配器负责转成稳定内部结构。
|
|
"""
|
|
|
|
intent: RunIntent
|
|
thread_id: str | None
|
|
run_id: str | None
|
|
body: RequestBody
|
|
headers: dict[str, str]
|
|
query: RequestQuery
|
|
|
|
@property
|
|
def last_event_id(self) -> str | None:
|
|
"""Extract Last-Event-ID from headers."""
|
|
return self.headers.get("last-event-id") or self.headers.get("Last-Event-ID")
|
|
|
|
@property
|
|
def is_stateless(self) -> bool:
|
|
"""Check if this is a stateless request."""
|
|
return self.thread_id is None
|
|
|
|
|
|
def adapt_create_run_request(
|
|
*,
|
|
thread_id: str | None,
|
|
body: RequestBody,
|
|
headers: dict[str, str] | None = None,
|
|
query: RequestQuery | None = None,
|
|
) -> AdaptedRunRequest:
|
|
"""Adapt POST /threads/{thread_id}/runs or POST /runs."""
|
|
return AdaptedRunRequest(
|
|
intent="create_background",
|
|
thread_id=thread_id,
|
|
run_id=None,
|
|
body=body,
|
|
headers=headers or {},
|
|
query=query or {},
|
|
)
|
|
|
|
|
|
def adapt_create_stream_request(
|
|
*,
|
|
thread_id: str | None,
|
|
body: RequestBody,
|
|
headers: dict[str, str] | None = None,
|
|
query: RequestQuery | None = None,
|
|
) -> AdaptedRunRequest:
|
|
"""Adapt POST /threads/{thread_id}/runs/stream or POST /runs/stream."""
|
|
return AdaptedRunRequest(
|
|
intent="create_and_stream",
|
|
thread_id=thread_id,
|
|
run_id=None,
|
|
body=body,
|
|
headers=headers or {},
|
|
query=query or {},
|
|
)
|
|
|
|
|
|
def adapt_create_wait_request(
|
|
*,
|
|
thread_id: str | None,
|
|
body: RequestBody,
|
|
headers: dict[str, str] | None = None,
|
|
query: RequestQuery | None = None,
|
|
) -> AdaptedRunRequest:
|
|
"""Adapt POST /threads/{thread_id}/runs/wait or POST /runs/wait."""
|
|
return AdaptedRunRequest(
|
|
intent="create_and_wait",
|
|
thread_id=thread_id,
|
|
run_id=None,
|
|
body=body,
|
|
headers=headers or {},
|
|
query=query or {},
|
|
)
|
|
|
|
|
|
def adapt_join_stream_request(
|
|
*,
|
|
thread_id: str,
|
|
run_id: str,
|
|
headers: dict[str, str] | None = None,
|
|
query: RequestQuery | None = None,
|
|
) -> AdaptedRunRequest:
|
|
"""Adapt GET /threads/{thread_id}/runs/{run_id}/stream."""
|
|
return AdaptedRunRequest(
|
|
intent="join_stream",
|
|
thread_id=thread_id,
|
|
run_id=run_id,
|
|
body={},
|
|
headers=headers or {},
|
|
query=query or {},
|
|
)
|
|
|
|
|
|
def adapt_join_wait_request(
|
|
*,
|
|
thread_id: str,
|
|
run_id: str,
|
|
headers: dict[str, str] | None = None,
|
|
query: RequestQuery | None = None,
|
|
) -> AdaptedRunRequest:
|
|
"""Adapt GET /threads/{thread_id}/runs/{run_id}/join."""
|
|
return AdaptedRunRequest(
|
|
intent="join_wait",
|
|
thread_id=thread_id,
|
|
run_id=run_id,
|
|
body={},
|
|
headers=headers or {},
|
|
query=query or {},
|
|
)
|