File size: 1,559 Bytes
43f41de
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
"""Typed research results shared by exploration tools and rewards."""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any


@dataclass
class ResearchChunk:
    """A ranked passage returned by a research tool."""

    source: str
    tool: str
    title: str
    url: str
    text: str
    score: float = 0.0
    rank: int = 0
    metadata: dict[str, Any] = field(default_factory=dict)

    @property
    def snippet(self) -> str:
        return self.text


@dataclass
class ResearchResult:
    """Structured response from a research tool."""

    tool: str
    query: str
    chunks: list[ResearchChunk] = field(default_factory=list)
    error: str = ""
    raw_count: int = 0

    @property
    def ok(self) -> bool:
        return not self.error and bool(self.chunks)

    @property
    def text(self) -> str:
        return "\n\n".join(chunk.text for chunk in self.chunks)

    @property
    def sources(self) -> set[str]:
        return {chunk.source for chunk in self.chunks}

    def render(self) -> str:
        """Render compact context for the agent."""
        if self.error:
            return f"{self.tool} error: {self.error}"
        if not self.chunks:
            return f"No results for {self.tool}: {self.query}"

        parts = []
        for chunk in self.chunks:
            url = f"\nURL: {chunk.url}" if chunk.url else ""
            parts.append(
                f"[{chunk.rank}] {chunk.source}: {chunk.title}{url}\n{chunk.text}"
            )
        return "\n\n---\n\n".join(parts)