from __future__ import annotations from typing import Iterable, List from app.services.code_kb.schema import CodeGraphContext, CodeSearchHit def _clip(value: str, limit: int) -> str: value = value or "" if len(value) <= limit: return value return value[:limit].rstrip() + "\n...[truncated]" def format_evidence_context( hits: Iterable[CodeSearchHit], graph_contexts: Iterable[CodeGraphContext], max_code_chars: int = 1000, max_text_chars: int = 800, ) -> str: context_by_node = {item.node_id: item for item in graph_contexts} blocks: List[str] = [] for hit in hits: item = hit.evidence graph = context_by_node.get(item.node_id) lines = [ f"[Function Evidence #{hit.rank}]", f"node_id: {item.node_id}", f"name: {item.name}", f"qualified_name: {item.qualified_name}", f"file: {item.file}", f"lines: {item.start_line}-{item.end_line}", f"similarity: {hit.similarity:.4f}", f"signature: {_clip(item.signature, 300)}", f"summary: {_clip(item.summary, max_text_chars)}", f"logic_flow: {_clip(item.logic_flow, max_text_chars)}", f"calls: {', '.join(item.calls[:20]) or '-'}", f"called_by: {', '.join(item.called_by[:20]) or '-'}", ] if graph: lines.append(f"call_chain_evidence: {'; '.join(graph.call_chains[:12]) or '-'}") if item.code_snippet: lines.extend(["code_snippet:", _clip(item.code_snippet, max_code_chars)]) blocks.append("\n".join(lines)) return "\n\n---\n\n".join(blocks)