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 +21 -0
- diffrag-0.2.3/PKG-INFO +425 -0
- diffrag-0.2.3/README.md +373 -0
- diffrag-0.2.3/pyproject.toml +85 -0
- diffrag-0.2.3/src/diffrag/__init__.py +101 -0
- diffrag-0.2.3/src/diffrag/__main__.py +3 -0
- diffrag-0.2.3/src/diffrag/ai/__init__.py +15 -0
- diffrag-0.2.3/src/diffrag/ai/base.py +106 -0
- diffrag-0.2.3/src/diffrag/ai/ollama.py +144 -0
- diffrag-0.2.3/src/diffrag/ai/openai_compat.py +193 -0
- diffrag-0.2.3/src/diffrag/cli/__init__.py +5 -0
- diffrag-0.2.3/src/diffrag/cli/main.py +440 -0
- diffrag-0.2.3/src/diffrag/config/__init__.py +21 -0
- diffrag-0.2.3/src/diffrag/config/settings.py +190 -0
- diffrag-0.2.3/src/diffrag/data/config.example.toml +53 -0
- diffrag-0.2.3/src/diffrag/diff/__init__.py +11 -0
- diffrag-0.2.3/src/diffrag/diff/git.py +227 -0
- diffrag-0.2.3/src/diffrag/diff/models.py +76 -0
- diffrag-0.2.3/src/diffrag/exceptions.py +21 -0
- diffrag-0.2.3/src/diffrag/indexing/__init__.py +5 -0
- diffrag-0.2.3/src/diffrag/indexing/indexer.py +387 -0
- diffrag-0.2.3/src/diffrag/indexing/splitter.py +296 -0
- diffrag-0.2.3/src/diffrag/py.typed +0 -0
- diffrag-0.2.3/src/diffrag/review/__init__.py +5 -0
- diffrag-0.2.3/src/diffrag/review/prompts.py +75 -0
- diffrag-0.2.3/src/diffrag/review/reviewer.py +322 -0
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
|
+
```
|