Skip to main content

Ports

Interfaces que definem os contratos entre o core e os adapters.

GitlabClient

from typing import Protocol
from core.models import FileDiff, Finding, MrEvent

class GitlabClient(Protocol):
def fetch_diff(self, event: MrEvent) -> list[FileDiff]: ...
def fetch_compare(self, event: MrEvent) -> list[FileDiff]: ...
def post_inline_comment(self, event: MrEvent, finding: Finding, position: dict) -> None: ...
def post_fallback_comment(self, event: MrEvent, body: str) -> None: ...

Métodos

MétodoDescriçãoExceção
fetch_diff(event)Busca o diff completo do MR (action=open)GitlabApiError
fetch_compare(event)Busca diff incremental (action=update)GitlabApiError
post_inline_comment(event, finding, position)Posta comentário inline na linhaGitlabApiError
post_fallback_comment(event, body)Posta comentário global no MRGitlabApiError

LlmClient

from typing import Protocol
from core.models import FileDiff, Finding, MrEvent

class LlmClient(Protocol):
def review_file(self, event: MrEvent, file_diff: FileDiff) -> list[Finding]: ...

Métodos

MétodoDescriçãoExceção
review_file(event, file_diff)Envia diff para o LLM e retorna findingsLlmParseError

LlmParseError

class LlmParseError(Exception):
"""Raised when an LLM response fails schema or diff-line validation."""

Levantado quando:

  • Resposta do LLM não é JSON válido
  • JSON não segue o schema esperado
  • Algum finding referencia linha que não está no diff

Dispatcher

from typing import Protocol
from core.models import MrEvent

class Dispatcher(Protocol:
def dispatch(self, event: MrEvent) -> None: ...

Métodos

MétodoDescrição
dispatch(event)Dispara o processamento assíncrono do MR

Implementações

ClasseAmbienteMecanismo
BackgroundTaskDispatcherContainerasyncio.create_task
LambdaSelfInvokeDispatcherLambdaboto3 lambda.invoke(InvocationType="Event")

ReviewPipeline

from core.models import MrEvent

class ReviewPipeline:
def __init__(
self,
gitlab_client: GitlabClient,
llm_client: LlmClient,
max_file_lines: int = 800,
): ...

def run(self, event: MrEvent) -> None: ...

Comportamento

  1. Fetch diffs do GitLab (diff ou compare, baseado na action)
  2. Para cada arquivo:
    • Skip se linhas > max_file_lines
    • Chama llm_client.review_file()
    • Para cada finding, tenta postar inline ou fallback
  3. Erros em um arquivo não afetam outros
  4. Erro no fetch do diff aborta todo o MR