Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions libs/deepagents/backends/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,30 @@

from collections.abc import Callable
from dataclasses import dataclass
from typing import Any, Protocol, TypeAlias, runtime_checkable
from typing import Any, Protocol, TypeAlias, TypedDict, runtime_checkable

from langchain.tools import ToolRuntime

from deepagents.backends.utils import FileInfo, GrepMatch

class FileInfo(TypedDict, total=False):
"""Structured file listing info.

Minimal contract used across backends. Only "path" is required.
Other fields are best-effort and may be absent depending on backend.
"""

path: str
is_dir: bool
size: int # bytes (approx)
modified_at: str # ISO timestamp if known


class GrepMatch(TypedDict):
"""Structured grep match entry."""

path: str
line: int
text: str


@dataclass
Expand Down
28 changes: 7 additions & 21 deletions libs/deepagents/backends/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,22 @@
import re
from datetime import UTC, datetime
from pathlib import Path
from typing import Any, Literal, TypedDict
from typing import Any, Literal

import wcmatch.glob as wcglob

from deepagents.backends.protocol import FileInfo as _FileInfo
from deepagents.backends.protocol import GrepMatch as _GrepMatch

EMPTY_CONTENT_WARNING = "System reminder: File exists but has empty contents"
MAX_LINE_LENGTH = 10000
LINE_NUMBER_WIDTH = 6
TOOL_RESULT_TOKEN_LIMIT = 20000 # Same threshold as eviction
TRUNCATION_GUIDANCE = "... [results truncated, try being more specific with your parameters]"


class FileInfo(TypedDict, total=False):
"""Structured file listing info.

Minimal contract used across backends. Only "path" is required.
Other fields are best-effort and may be absent depending on backend.
"""

path: str
is_dir: bool
size: int # bytes (approx)
modified_at: str # ISO timestamp if known


class GrepMatch(TypedDict):
"""Structured grep match entry."""

path: str
line: int
text: str
# Re-export protocol types for backwards compatibility
FileInfo = _FileInfo
GrepMatch = _GrepMatch


def sanitize_tool_call_id(tool_call_id: str) -> str:
Expand Down