RAGState and AnalysisState each declared the same five fields, so the generic base could not name them: StateT was bound to BaseModel, and every access went through cast(Any, state), a getattr by string, or a loop clearing fields by name so it could skip the one only AnalysisState has. EvidenceState declares them once. RAGState adds nothing, AnalysisState adds executions and overrides begin_invocation to clear them. StateT binds to EvidenceState, which removes all ten casts and both state-shape getattrs; the three getattr(ctx.deps, "state") probes stay, since those check a host-supplied object rather than our own state. discover_evidence reached into capability.state for two fields. It now asks through evidence_record() and citation_index(), alongside the evidence_tool_names() and cite_available accessors it already used. The eval runner's _RagLikeState protocol and the chat app's getattr reads described this shape from outside and are gone. Compatibility is semantic JSON-object equivalence, not bytes: field names and nesting are unchanged, so a dict stored by 0.75.0 loads and re-dumps equal, but deriving from a shared base reorders AnalysisState's keys. Nothing serializes, hashes or string-compares this state — every carry point re-validates by key.
14 lines
422 B
Python
14 lines
422 B
Python
"""Native Pydantic AI capabilities provided by haiku.rag."""
|
|
|
|
from haiku.rag.capabilities._base import EvidenceState, RAGCapabilityBase
|
|
from haiku.rag.capabilities.analysis import AnalysisCapability, AnalysisState
|
|
from haiku.rag.capabilities.rag import RAGCapability, RAGState
|
|
|
|
__all__ = [
|
|
"AnalysisCapability",
|
|
"AnalysisState",
|
|
"EvidenceState",
|
|
"RAGCapability",
|
|
"RAGCapabilityBase",
|
|
"RAGState",
|
|
]
|