diffrag 0.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
diffrag-0.2.3/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Eduardo Nunez
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
diffrag-0.2.3/PKG-INFO ADDED
@@ -0,0 +1,425 @@
1
+ Metadata-Version: 2.3
2
+ Name: diffrag
3
+ Version: 0.2.3
4
+ Summary: AI-powered git diff analysis and code review with RAG context
5
+ Keywords: code-review,git,ai,llm,rag,openai
6
+ Author: Eduardo Nunez
7
+ Author-email: Eduardo Nunez <edu.a.n.van.eyl@gmail.com>
8
+ License: MIT License
9
+
10
+ Copyright (c) 2026 Eduardo Nunez
11
+
12
+ Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ of this software and associated documentation files (the "Software"), to deal
14
+ in the Software without restriction, including without limitation the rights
15
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ copies of the Software, and to permit persons to whom the Software is
17
+ furnished to do so, subject to the following conditions:
18
+
19
+ The above copyright notice and this permission notice shall be included in all
20
+ copies or substantial portions of the Software.
21
+
22
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
+ SOFTWARE.
29
+ Classifier: Development Status :: 3 - Alpha
30
+ Classifier: Environment :: Console
31
+ Classifier: Intended Audience :: Developers
32
+ Classifier: Natural Language :: English
33
+ Classifier: Operating System :: OS Independent
34
+ Classifier: Programming Language :: Python :: 3
35
+ Classifier: Programming Language :: Python :: 3.12
36
+ Classifier: Topic :: Software Development
37
+ Classifier: Topic :: Software Development :: Version Control :: Git
38
+ Requires-Dist: chromadb>=1.5.8
39
+ Requires-Dist: click>=8.1
40
+ Requires-Dist: httpx>=0.28
41
+ Requires-Dist: pathspec>=0.12
42
+ Requires-Dist: platformdirs>=4.0
43
+ Requires-Dist: rich>=15.0.0
44
+ Requires-Dist: tiktoken>=0.9
45
+ Requires-Dist: tqdm>=4.67.3
46
+ Requires-Python: >=3.12
47
+ Project-URL: Homepage, https://gitlab.com/eanveyl-group/ai-code-reviewer
48
+ Project-URL: Repository, https://gitlab.com/eanveyl-group/ai-code-reviewer
49
+ Project-URL: Issues, https://gitlab.com/eanveyl-group/ai-code-reviewer/-/issues
50
+ Project-URL: Changelog, https://gitlab.com/eanveyl-group/ai-code-reviewer/-/blob/main/CHANGELOG.md
51
+ Description-Content-Type: text/markdown
52
+
53
+ # diffrag
54
+
55
+ AI-powered code reviewer for git repositories. Point it at two branches and get an LLM-generated review that understands the broader codebase through RAG (Retrieval-Augmented Generation).
56
+
57
+ ## Features
58
+
59
+ - **AI code review** — analyzes the diff between any two branches and reports on breaking changes, API surface changes, SOLID violations, code smells, security concerns, missing documentation, and more.
60
+ - **RAG context** — the full repository is indexed into a ChromaDB vector store so the LLM can reference relevant surrounding code, not just the changed lines.
61
+ - **Smart index caching** — the vector index is rebuilt only when the HEAD commit changes; repeated runs on the same commit reuse the cached index instantly.
62
+ - **Interactive Q&A** — after a review you can open an interactive REPL and ask follow-up questions about the diff or the codebase; the session remembers prior exchanges so follow-up questions work naturally.
63
+ - **Flexible AI backends** — works with any OpenAI-compatible endpoint (OpenWebUI, Ollama `/v1`, OpenAI) as well as Ollama's native API.
64
+ - **Fully configurable** — settings can be set once in a user-level global config or overridden per-project; sane defaults work out of the box. Indexes are stored in the OS user cache directory — your project directories stay clean.
65
+ - **`.gitignore`-aware indexing** — the repository's `.gitignore` is parsed automatically and its patterns are respected during indexing; extra excludes can be added via config.
66
+
67
+ ## Installation
68
+
69
+ ```bash
70
+ uv add diffrag # add to a project
71
+ uv tool install diffrag # install as a standalone CLI tool
72
+ ```
73
+
74
+ Requires Python ≥ 3.12.
75
+
76
+ ## Setup
77
+
78
+ ### 1. Create a config file
79
+
80
+ diffrag looks for configuration in the following order (first match wins):
81
+
82
+ 1. `--config <path>` — explicit path passed on the command line
83
+ 2. `.diffrag.toml` — in the current working directory (project-level override)
84
+ 3. `$(diffrag config-path)` — user-level global config (set once, used everywhere)
85
+ 4. Built-in defaults — everything works without any config file
86
+
87
+ **Recommended: set up a global config once** so every repository uses the same
88
+ model and endpoint without needing its own `.diffrag.toml`:
89
+
90
+ ```bash
91
+ # Create the global config (creates the directory too)
92
+ diffrag create-config
93
+
94
+ # Open it in your editor
95
+ $EDITOR "$(diffrag config-path)"
96
+ ```
97
+
98
+ For a project-specific override (e.g. a different `base_branch` or `verbosity`):
99
+
100
+ ```bash
101
+ diffrag create-config --out .diffrag.toml
102
+ ```
103
+
104
+ Per-project `.diffrag.toml` files take precedence over the global config.
105
+
106
+ **Minimal config — Ollama for both LLM and embeddings:**
107
+
108
+ ```toml
109
+ [ai]
110
+ base_url = "http://localhost:11434"
111
+ model = "llama3.2"
112
+
113
+ [embedding]
114
+ base_url = "http://localhost:11434"
115
+ model = "nomic-embed-text"
116
+ ```
117
+
118
+ **OpenWebUI for the LLM, Ollama for embeddings:**
119
+
120
+ ```toml
121
+ [ai]
122
+ base_url = "http://localhost:3000"
123
+ model = "gpt-4o"
124
+ api_key = "your-openwebui-token"
125
+
126
+ [embedding]
127
+ base_url = "http://localhost:11434"
128
+ model = "nomic-embed-text"
129
+ ```
130
+
131
+ The `[ai]` and `[embedding]` sections are independent — you can mix and match any OpenAI-compatible endpoint for each role.
132
+
133
+ ---
134
+
135
+ ## CLI usage
136
+
137
+ ### `review` — generate a code review
138
+
139
+ ```bash
140
+ # Review current branch (HEAD) against main
141
+ diffrag review --base main
142
+
143
+ # Review a specific branch against main
144
+ diffrag review --base main --head feature/my-feature
145
+
146
+ # Review against a tag or commit SHA
147
+ diffrag review --base v1.2.0 --head HEAD
148
+
149
+ # Review a repo at a different path
150
+ diffrag review --repo /path/to/repo --base main
151
+
152
+ # Use a non-default config file
153
+ diffrag review --base main --config /path/to/my.toml
154
+ ```
155
+
156
+ **Index caching:** on the first run the repository is indexed and the result is
157
+ persisted to the OS user cache directory (run `diffrag db-path` to see the exact
158
+ path for a given repo). On subsequent runs the tool compares the current HEAD SHA
159
+ against the stored one — if they match the index is reused immediately; if they
160
+ differ (new commit or branch switch) the index is rebuilt automatically. Your
161
+ project directories are never modified.
162
+
163
+ ### `ask` — interactive Q&A about the diff
164
+
165
+ ```bash
166
+ diffrag ask --base main
167
+ diffrag ask --base main --head feature/my-feature
168
+ ```
169
+
170
+ Opens an interactive prompt backed by the same RAG index. Run `review` at least
171
+ once beforehand so the index is populated. Type `exit` or press Ctrl-D to quit.
172
+
173
+ Each answer is informed by the repository context and the diff. The session
174
+ accumulates conversation history, so follow-up questions can refer back to
175
+ earlier answers:
176
+
177
+ ```
178
+ > What does the change in auth.py affect downstream?
179
+ > Can you give a concrete example of how that breaks existing callers?
180
+ > Which tests cover the modified functions?
181
+ ```
182
+
183
+ ### `show-config` — inspect effective configuration
184
+
185
+ ```bash
186
+ diffrag show-config
187
+ diffrag show-config --config /path/to/my.toml
188
+ ```
189
+
190
+ Prints a table of every setting that is in effect, including defaults for keys
191
+ not present in your config file.
192
+
193
+ ### `db-path` — print the database path for a repository
194
+
195
+ ```bash
196
+ diffrag db-path
197
+ diffrag db-path --repo /path/to/repo
198
+ ```
199
+
200
+ Prints the path where the vector index for that repository is (or will be)
201
+ stored. Useful for inspecting or deleting a stale index.
202
+
203
+ ### `create-config` — create a starter config file
204
+
205
+ ```bash
206
+ diffrag create-config # write to user-level global config
207
+ diffrag create-config --out .diffrag.toml # write a project-level override
208
+ diffrag create-config --force # overwrite if the file already exists
209
+ ```
210
+
211
+ Creates a config file pre-populated with all available settings and their
212
+ defaults. The destination directory is created automatically.
213
+
214
+ ### `config-path` — print the user-level config path
215
+
216
+ ```bash
217
+ diffrag config-path
218
+ ```
219
+
220
+ Prints the OS-appropriate path for the user-level config file (it may not exist
221
+ yet). Useful for opening the config in an editor: `$EDITOR $(diffrag config-path)`.
222
+
223
+ ### Global options
224
+
225
+ | Option | Description |
226
+ |--------|-------------|
227
+ | `-v` / `--verbose` | Enable debug-level logging |
228
+ | `-c` / `--config PATH` | Path to a `.toml` config file (overrides auto-discovery) |
229
+
230
+ ---
231
+
232
+ ## Configuration reference
233
+
234
+ All keys are optional. Unset keys fall back to the defaults shown below.
235
+ Place the file at `$(diffrag config-path)` for global defaults, or at `.diffrag.toml`
236
+ in a project root to override per-repository.
237
+
238
+ ```toml
239
+ [ai]
240
+ # Base URL of the OpenAI-compatible or Ollama endpoint used for review generation.
241
+ # Do NOT include a /v1 suffix — it is appended automatically.
242
+ base_url = "http://localhost:11434"
243
+
244
+ # Model identifier sent with every completion request.
245
+ model = "llama3.2"
246
+
247
+ # Bearer token for the Authorization header. Leave empty for local servers.
248
+ api_key = ""
249
+
250
+ # Per-read timeout in seconds. Requests use streaming, so this is the maximum
251
+ # time allowed between consecutive chunks — not the total generation time.
252
+ # Increase only if the model stalls mid-generation for unusually long periods.
253
+ timeout = 120.0
254
+
255
+
256
+ [embedding]
257
+ # Endpoint used for computing text embeddings. Can be the same server as [ai]
258
+ # or a different one (e.g. a dedicated embedding service).
259
+ base_url = "http://localhost:11434"
260
+
261
+ # Embedding model. nomic-embed-text works well with Ollama.
262
+ model = "nomic-embed-text"
263
+
264
+ api_key = ""
265
+ timeout = 60.0
266
+
267
+
268
+ [indexing]
269
+ # The index is always stored in the OS user cache directory, keyed by repo.
270
+ # Run "diffrag db-path" to see the exact path. This cannot be configured.
271
+
272
+ # Maximum number of characters per text chunk when splitting files.
273
+ chunk_size = 1024
274
+
275
+ # Character overlap between consecutive chunks (helps preserve context at boundaries).
276
+ chunk_overlap = 128
277
+
278
+ # The repository's .gitignore is parsed automatically and its patterns are
279
+ # applied first. The list below provides additional excludes on top of .gitignore.
280
+ # Any path component matching one of these strings is also skipped.
281
+ excluded_patterns = [
282
+ ".git", ".venv", "__pycache__", "node_modules",
283
+ ".idea", ".mypy_cache", ".ruff_cache", "dist", "build"
284
+ ]
285
+
286
+ # Files larger than this (in bytes) are silently skipped.
287
+ # Binary files are always skipped regardless of this setting.
288
+ max_file_size = 1000000
289
+
290
+
291
+ [review]
292
+ # Default base branch when --base is not specified on the command line.
293
+ base_branch = "main"
294
+
295
+ # Number of context chunks retrieved from the vector index per diff chunk.
296
+ # Higher values give the LLM more surrounding context but increase prompt size.
297
+ similarity_top_k = 5
298
+
299
+ # Approximate token budget per diff chunk before it is split into individual hunks.
300
+ # Reduce this if your model has a small context window.
301
+ max_prompt_tokens = 6000
302
+
303
+ # Detail level of generated reviews. Can be overridden per-run with --verbosity.
304
+ # "brief" — top 3 critical issues only, under 200 words
305
+ # "standard" — balanced default
306
+ # "detailed" — exhaustive, includes minor nits and suggested fixes per issue
307
+ verbosity = "standard"
308
+ ```
309
+
310
+ ---
311
+
312
+ ## Library usage
313
+
314
+ `diffrag` is also usable as a Python library:
315
+
316
+ ```python
317
+ import asyncio
318
+ from pathlib import Path
319
+ from diffrag import (
320
+ Settings,
321
+ GitRepository,
322
+ OpenAICompatClient,
323
+ RepoIndexer,
324
+ CodeReviewer,
325
+ )
326
+
327
+ settings = Settings.from_toml(Path(".diffrag.toml"))
328
+
329
+ ai_client = OpenAICompatClient(
330
+ base_url=settings.ai.base_url,
331
+ model=settings.ai.model,
332
+ api_key=settings.ai.api_key,
333
+ )
334
+ embed_client = OpenAICompatClient(
335
+ base_url=settings.embedding.base_url,
336
+ model=settings.embedding.model,
337
+ api_key=settings.embedding.api_key,
338
+ )
339
+ indexer = RepoIndexer(
340
+ db_path=settings.indexing.db_path,
341
+ embedding_client=embed_client,
342
+ )
343
+ reviewer = CodeReviewer(ai_client=ai_client, indexer=indexer)
344
+ repo = GitRepository(Path("/path/to/repo"))
345
+
346
+
347
+ async def main() -> None:
348
+ # review() checks the HEAD commit hash and only rebuilds the index when needed
349
+ result = await reviewer.review(repo, base="main", head="feature/my-feature")
350
+ print(result.summary)
351
+
352
+ # ask follow-up questions about the same diff; pass history for multi-turn
353
+ diff = repo.get_diff("main", "feature/my-feature")
354
+ history: list[tuple[str, str]] = []
355
+ q1 = "Are there any breaking API changes?"
356
+ a1 = await reviewer.ask(q1, diff)
357
+ print(a1)
358
+ history.append((q1, a1))
359
+ a2 = await reviewer.ask("Which callers are affected?", diff, history=history)
360
+ print(a2)
361
+
362
+
363
+ asyncio.run(main())
364
+ ```
365
+
366
+ For Ollama's native API (supports `num_ctx` and other Ollama-specific options):
367
+
368
+ ```python
369
+ from diffrag import OllamaClient
370
+
371
+ embed_client = OllamaClient(
372
+ base_url="http://localhost:11434",
373
+ model="nomic-embed-text",
374
+ )
375
+ ```
376
+
377
+ ---
378
+
379
+ ## How the review pipeline works
380
+
381
+ 1. **Diff** — `git diff base...head` is run for each changed file; results are parsed into typed `FileDiff` / `Hunk` objects.
382
+ 2. **Index** — every non-binary file in the repository is split into overlapping character chunks and embedded into ChromaDB. The HEAD commit hash is saved alongside the index; on future runs this hash is compared and the rebuild is skipped if nothing has changed.
383
+ 3. **Per-file review** — for each changed file:
384
+ - The LLM summarises the diff in plain English (used as a targeted search query).
385
+ - The summary is embedded and the top-*k* nearest chunks are retrieved from the index.
386
+ - The LLM reviews the raw diff in light of the retrieved context.
387
+ - Large diffs are split into individual git hunks and reviewed separately.
388
+ 4. **Consolidation** — all per-file reviews are sent to the LLM in a final prompt that produces a single, cross-cutting summary.
389
+
390
+ ---
391
+
392
+ ## Development
393
+
394
+ ```bash
395
+ # Install with dev dependencies
396
+ uv sync --group dev
397
+
398
+ # Run tests
399
+ uv run pytest
400
+
401
+ # Lint and format checks
402
+ uv run ruff check src tests
403
+ uv run ruff format --check src tests
404
+
405
+ # Type checking
406
+ uv run ty check src
407
+
408
+ # Run all checks via tox
409
+ uv run tox
410
+
411
+ # Build Sphinx docs
412
+ uv run sphinx-build docs docs/_build/html
413
+ ```
414
+
415
+ ## Project structure
416
+
417
+ ```
418
+ src/diffrag/
419
+ ├── config/ # Settings dataclasses + TOML loading (settings.py)
420
+ ├── diff/ # GitRepository, FileDiff, Hunk models (git.py, models.py)
421
+ ├── ai/ # AIClient / EmbeddingClient protocols, OpenAI-compat + Ollama clients
422
+ ├── indexing/ # ChromaDB-backed RepoIndexer with staleness detection
423
+ ├── review/ # CodeReviewer orchestrator + prompt templates
424
+ └── cli/ # Click CLI: review / ask / show-config / create-config / db-path / config-path
425
+ ```