band-aider-pub/band_aider/judgement/parser_factory.py
2026-10-17 11:57:37 -07:00

72 lines
2.8 KiB
Python

from __future__ import annotations
from dataclasses import dataclass
from typing import Iterable
from band_aider.judgement.code_parser import CodeParser
from band_aider.judgement.file_parser import FileParser
from band_aider.judgement.model2vec_code_parser import NarrowParser
from band_aider.judgement.strict_parser import StrictParser
from band_aider.judgement.repo_exec import RepoExec
from band_aider.judgement.prompt_formatter import PromptFormatterBuilder
@dataclass
class ParserFactory:
"""Construct the parser pipeline selected by the search policy.
The factory keeps parser selection in one place so callers can create the
same broad, narrow, or strict pipeline with consistent repository access,
source discovery, anchors, and semantic-threshold settings.
"""
client: object
"""Completion client used by the underlying file parser."""
repo_exec: RepoExec
"""Repository execution adapter used for file and metadata access."""
prompt_formatter_builder: PromptFormatterBuilder
"""Required builder for metadata prompt construction."""
source_discovery_strategy: object
"""Strategy used by parsers that restrict source-file consideration."""
scope: str = "broad"
"""Search scope: ``broad``, ``narrow``, or ``strict``."""
policy_anchors: tuple[str, ...] = ()
"""Symbols or terms used to focus narrow and strict parsing."""
semantic_threshold: float = 0.55
"""Minimum semantic similarity accepted by the narrow parser."""
semi_related_threshold: float | int = 0.50
def __call__(self, anchors: Iterable[str] | None = None) -> CodeParser:
"""Build and return the parser pipeline for the configured scope.
Args:
anchors: Optional per-call anchor override. When omitted, the
factory's ``policy_anchors`` are used.
Returns:
A broad ``FileParser``, a narrow ``NarrowParser``, or a strict
``StrictParser`` pipeline.
"""
lexical = tuple(self.policy_anchors if anchors is None else anchors)
file_parser = FileParser(
self.client,
repo_exec=self.repo_exec,
prompt_formatter_builder=self.prompt_formatter_builder,
)
if self.scope == "narrow":
return NarrowParser(inner=file_parser, source_discovery_strategy=self.source_discovery_strategy,
anchors=lexical, semantic_threshold=self.semantic_threshold)
if self.scope == "strict":
return StrictParser(
inner=NarrowParser(inner=file_parser, source_discovery_strategy=self.source_discovery_strategy,
anchors=(), semantic_threshold=self.semi_related_threshold),
anchors=lexical, source_discovery_strategy=self.source_discovery_strategy)
return file_parser