Skip to content

Changed lines

changed_lines

Map changed line intervals to symbols in an immutable snapshot.

ChangedLinesTool

Bases: AXMTool

Expose the hunk-to-symbol measurement for graph and MCP consumers.

Source code in packages/axm-ast/src/axm_ast/tools/changed_lines.py
Python
class ChangedLinesTool(AXMTool):
    """Expose the hunk-to-symbol measurement for graph and MCP consumers."""

    @property
    def name(self) -> str:
        return "ast_changed_lines"

    def execute(
        self,
        path: str = ".",
        file: str = "",
        intervals: list[list[int]] | None = None,
        **kwargs: object,
    ) -> ToolResult:
        """Resolve package-relative lines; intervals are [start, count] pairs."""
        root = Path(path).resolve()
        target = (root / file).resolve()
        if not target.is_relative_to(root):
            return ToolResult(success=False, error="file is outside package")
        if any(
            len(pair) != _INTERVAL_SIZE or min(pair) < 0 for pair in intervals or []
        ):
            return ToolResult(
                success=False, error="expected non-negative [start, count]"
            )
        try:
            symbols = symbols_for_lines(
                root, target, [(p[0], p[1]) for p in intervals or []]
            )
        except (ValueError, OSError) as exc:
            return ToolResult(success=False, error=str(exc))
        return ToolResult(
            success=True, data={"symbols": list(symbols)}, text="\n".join(symbols)
        )
execute(path='.', file='', intervals=None, **kwargs)

Resolve package-relative lines; intervals are [start, count] pairs.

Source code in packages/axm-ast/src/axm_ast/tools/changed_lines.py
Python
def execute(
    self,
    path: str = ".",
    file: str = "",
    intervals: list[list[int]] | None = None,
    **kwargs: object,
) -> ToolResult:
    """Resolve package-relative lines; intervals are [start, count] pairs."""
    root = Path(path).resolve()
    target = (root / file).resolve()
    if not target.is_relative_to(root):
        return ToolResult(success=False, error="file is outside package")
    if any(
        len(pair) != _INTERVAL_SIZE or min(pair) < 0 for pair in intervals or []
    ):
        return ToolResult(
            success=False, error="expected non-negative [start, count]"
        )
    try:
        symbols = symbols_for_lines(
            root, target, [(p[0], p[1]) for p in intervals or []]
        )
    except (ValueError, OSError) as exc:
        return ToolResult(success=False, error=str(exc))
    return ToolResult(
        success=True, data={"symbols": list(symbols)}, text="\n".join(symbols)
    )