npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

diffai-sensioerp

v0.2.1

Published

Local-AI powered git diff analyzer. Produces a structured technical summary (JSON) of what changed, with zero cloud dependencies.

Readme

diffai

Analisador de git diff com IA. Produz um resumo técnico estruturado (JSON) do que mudou.

diffai é um CLI que detecta o que mudou no Git, descobre via AST quais símbolos realmente foram alterados, monta chunks mínimos (nunca o arquivo inteiro) e pede a uma IA uma análise técnica por chunk. As análises são consolidadas em um único JSON e em uma documentação (docs/analysis.md).

Por padrão o diffai usa a IA da nuvem (OpenAI) quando encontra a variável OPENAI_API_KEY_CHECKLIST (definida no ambiente ou em um arquivo .env — veja .env.example). Se essa variável não existir, ele cai automaticamente para a IA local (Ollama / Qwen Coder), sem nenhuma configuração adicional e sem que código-fonte saia da máquina. Ambos os adapters implementam o mesmo port (AIProvider), então o restante do pipeline não sabe (nem precisa saber) qual dos dois está em uso.

A IA (local ou na nuvem) é apenas um Analista Técnico: ela nunca conversa com o usuário, nunca gera checklist de QA e nunca produz o Markdown final. Toda a arquitetura já está preparada para, no futuro, um pacote cloud-agent consumir somente o JSON consolidado (nunca o código-fonte).


Fluxo

git diff → git-analyzer → ast-parser → chunk-builder → cloud-ai | local-ai → summary-merger → { analysis.json, docs/analysis.md }

| Etapa | Pacote | Entrada | Saída | | ----- | -------------------------- | --------------------- | ---------------------------- | | 1 | git-analyzer | refs/working tree | DiffResult (arquivos) | | 2 | ast-parser | ChangedFile | FileSymbols (símbolos) | | 3 | chunk-builder | FileSymbols | AnalysisChunk[] | | 4 | cloud-ai (padrão) ou local-ai | AnalysisChunk | ChunkAnalysis (JSON) | | 5 | summary-merger | ChunkAnalysis[] | ConsolidatedSummary (JSON) | | 6 | documentation | ConsolidatedSummary | docs/analysis.md |

Regra de ouro: o diff inteiro nunca é enviado à IA. Cada chunk carrega só o trecho alterado + contexto mínimo.


Arquitetura (Clean Architecture)

Dependências apontam sempre para dentro. @diffai/shared não depende de ninguém; todos dependem dele.

                 ┌─────────────────────────────────────────────┐
                 │                @diffai/shared                │
                 │  domain (entidades)  ·  application (ports +  │
                 │  use-case)  ·  schemas (Zod)  ·  config       │
                 └─────────────────────────────────────────────┘
                        ▲     ▲     ▲     ▲     ▲     ▲     ▲
     implementam ports  │     │     │     │     │     │     │
        ┌───────────────┴─┬───┴─────┴──┬──┴──┬──┴─────┴───┬─┴──────────────┐
   git-analyzer     ast-parser   chunk-builder cloud-ai local-ai  summary-merger   documentation
   (simple-git)     (ts-morph)    (puro)     (openai) (ollama/qwen) (puro)          (puro)
        └───────────────────────────────────┬───────────────────────────────────────┘
                                        │ tudo é injetado em
                                   ┌────┴────┐
                                   │   cli   │  ← composition root (Commander + DI)
                                   └─────────┘
  • domain: entidades puras do pipeline (ChangedFile, FileSymbols, AnalysisChunk, LineRange).
  • application/ports: as interfaces (GitProvider, ParserProvider, ChunkBuilder, AIProvider, PromptBuilder, SummaryMerger, SummaryWriter, DocumentationWriter, AnalysisCache, Logger).
  • application/use-cases: AnalyzeChangesUseCase orquestra o fluxo usando só ports — é a "API interna" que o cloud-agent reaproveitará.
  • schemas (Zod): contratos JSON que cruzam fronteiras — ChunkAnalysisSchema (etapa 4) e ConsolidatedSummarySchema (etapa 5). São a fonte da verdade; os tipos TS são inferidos deles.

Por que os contratos JSON vivem em Zod, e as entidades internas não

Entidades internas (ChangedFile, etc.) são interfaces puras, sem dependência de biblioteca — domínio limpo. Já ChunkAnalysis e ConsolidatedSummary atravessam a fronteira da IA e do futuro cloud-agent, então precisam de validação em runtime. Para esses, o schema Zod é a fonte única (type = z.infer<...>), eliminando drift entre validação e tipo.


Substituindo implementações

Todo recurso externo está atrás de um port. Trocar qualquer um é adicionar um adapter e uma linha no composition root — nada mais muda.

  • IA: AIProvider ← OpenAIAdapter (cloud-ai) ou AIProvider ← OllamaAdapter (local-ai) ← Qwen Coder. O composition root (packages/cli/src/container.ts) escolhe automaticamente: OPENAI_API_KEY_CHECKLIST presente → nuvem; ausente → local. Pode ser forçado via ai.provider: "openai" | "ollama" no diffai.config.json. Amanhã: LM Studio, llama.cpp, Anthropic, etc. — mesmo port, outro adapter.
  • Git: GitProvider ← SimpleGitAdapter. Amanhã: GitHub API, fixtures.
  • Parser: ParserProvider ← TsMorphParser. Amanhã: outros parsers por linguagem.

Performance & escala (5 → 500 arquivos)

  • Paralelismo controlado: mapWithConcurrency limita quantos chunks vão à IA ao mesmo tempo.
  • Cache incremental: cada chunk tem um id = hash estável do conteúdo. AnalysisCache evita reanalisar código que não mudou.
  • Minimização de tokens: só o trecho alterado + contexto mínimo entram no prompt.
  • Degradação graciosa: falha de parse em um arquivo não derruba o pipeline (FileSymbols.parseError).

Futuro: cloud-agent (não implementado)

Um pacote futuro consumirá apenas o ConsolidatedSummary (JSON) — nunca o código. Ele fará entrevista com o dev, gerará perguntas, checklist de QA e Markdown, e anexará ao PR. Nada disso é responsabilidade da IA local. O schemaVersion no JSON permite que ele evolua de forma independente.


Requisitos

  • Node.js >= 20, npm 10+
  • Opção A — IA da nuvem (padrão quando configurada): uma OPENAI_API_KEY_CHECKLIST válida, definida no ambiente ou em um .env na raiz do repo analisado (copie .env.example).
  • Opção B — IA local (fallback automático): Ollama com um modelo coder (padrão: qwen2.5-coder:7b). Há um docker/ pronto para subir o Ollama.

Comandos

npm install
npm run typecheck   # tsc --noEmit em todos os pacotes
npm test             # vitest (IA sempre mockada)
npm run lint         # eslint
npm run format       # prettier --write

Uso do CLI

# alterações pendentes: working tree vs HEAD
npm run diffai -- --cwd /caminho/do/repo

# TODA a branch: tudo que ela introduziu vs main (merge-base / estilo PR)
npm run diffai -- --base main

# variações úteis
npm run diffai -- --base main --two-dot            # diff literal main..HEAD (sem merge-base)
npm run diffai -- --base v1.0.0 --head HEAD        # intervalo entre dois refs
npm run diffai -- --staged                         # apenas o que está staged
npm run diffai -- --model qwen2.5-coder:7b --concurrency 8   # (flags de modelo/URL só valem para o Ollama)
npm run diffai -- health                           # checa se a IA (nuvem ou local) responde

# rodar sem nenhuma IA de verdade (análise offline determinística, ótimo p/ CI e testes)
DIFFAI_FAKE_AI=1 npm run diffai -- --cwd /caminho/do/repo --skip-health

Escolha automática de IA: se OPENAI_API_KEY_CHECKLIST estiver definida (no ambiente ou em um .env na pasta analisada — veja .env.example), o diffai usa a nuvem (OpenAI). Caso contrário, usa o Ollama local. Para forçar um dos dois, defina "ai": { "provider": "openai" } ou "ai": { "provider": "ollama" } no diffai.config.json.

Saídas (padrão, relativas ao --cwd): .diffai/analysis.json e docs/analysis.md. Configuração opcional via diffai.config.json na raiz do repo (precedência: defaults < arquivo < flags).

Estrutura

packages/
  shared/          # domínio, ports, schemas, config, use-case  (sem deps internas)
  git-analyzer/    # GitProvider     (simple-git)
  ast-parser/      # ParserProvider  (ts-morph)
  chunk-builder/   # ChunkBuilder    (puro)
  cloud-ai/        # AIProvider      (openai) — padrão quando OPENAI_API_KEY_CHECKLIST existe
  local-ai/        # AIProvider      (ollama/qwen) — fallback automático
  summary-merger/  # SummaryMerger   (puro)
  documentation/   # DocumentationWriter
  cli/             # Commander + composition root (DI)

Status

Pipeline completo e funcional, com o CLI executável ponta-a-ponta e IA híbrida (nuvem por padrão via OPENAI_API_KEY_CHECKLIST, local como fallback automático). Todos os pacotes implementados com testes (IA sempre mockada nos testes), typecheck e lint limpos. Próximo passo natural (fora do escopo atual): o pacote cloud-agent, que consumirá apenas o JSON consolidado.

Licença

MIT