| from typing import Annotated, NotRequired, TypedDict |
|
|
| from langchain.agents import AgentState |
|
|
|
|
| class SandboxState(TypedDict): |
| sandbox_id: NotRequired[str | None] |
|
|
|
|
| class ThreadDataState(TypedDict): |
| workspace_path: NotRequired[str | None] |
| uploads_path: NotRequired[str | None] |
| outputs_path: NotRequired[str | None] |
|
|
|
|
| class ViewedImageData(TypedDict): |
| base64: str |
| mime_type: str |
|
|
|
|
| def merge_artifacts(existing: list[str] | None, new: list[str] | None) -> list[str]: |
| """Reducer for artifacts list - merges and deduplicates artifacts.""" |
| if existing is None: |
| return new or [] |
| if new is None: |
| return existing |
| |
| return list(dict.fromkeys(existing + new)) |
|
|
|
|
| def merge_viewed_images(existing: dict[str, ViewedImageData] | None, new: dict[str, ViewedImageData] | None) -> dict[str, ViewedImageData]: |
| """Reducer for viewed_images dict - merges image dictionaries. |
| |
| Special case: If new is an empty dict {}, it clears the existing images. |
| This allows middlewares to clear the viewed_images state after processing. |
| """ |
| if existing is None: |
| return new or {} |
| if new is None: |
| return existing |
| |
| if len(new) == 0: |
| return {} |
| |
| return {**existing, **new} |
|
|
|
|
| class ThreadState(AgentState): |
| sandbox: NotRequired[SandboxState | None] |
| thread_data: NotRequired[ThreadDataState | None] |
| title: NotRequired[str | None] |
| artifacts: Annotated[list[str], merge_artifacts] |
| todos: NotRequired[list | None] |
| uploaded_files: NotRequired[list[dict] | None] |
| viewed_images: Annotated[dict[str, ViewedImageData], merge_viewed_images] |
|
|