denai 0.4.0__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.
Files changed (48) hide show
  1. denai-0.4.0/.gitignore +38 -0
  2. denai-0.4.0/LICENSE +21 -0
  3. denai-0.4.0/PKG-INFO +444 -0
  4. denai-0.4.0/README.md +403 -0
  5. denai-0.4.0/denai/__init__.py +3 -0
  6. denai-0.4.0/denai/__main__.py +19 -0
  7. denai-0.4.0/denai/app.py +132 -0
  8. denai-0.4.0/denai/config.py +132 -0
  9. denai-0.4.0/denai/db.py +66 -0
  10. denai-0.4.0/denai/llm/__init__.py +6 -0
  11. denai-0.4.0/denai/llm/context.py +86 -0
  12. denai-0.4.0/denai/llm/ollama.py +304 -0
  13. denai-0.4.0/denai/llm/prompt.py +76 -0
  14. denai-0.4.0/denai/network.py +18 -0
  15. denai-0.4.0/denai/plugins/__init__.py +185 -0
  16. denai-0.4.0/denai/rag/__init__.py +341 -0
  17. denai-0.4.0/denai/routes/__init__.py +25 -0
  18. denai-0.4.0/denai/routes/chat.py +100 -0
  19. denai-0.4.0/denai/routes/conversations.py +147 -0
  20. denai-0.4.0/denai/routes/memories.py +24 -0
  21. denai-0.4.0/denai/routes/models.py +94 -0
  22. denai-0.4.0/denai/routes/plans.py +73 -0
  23. denai-0.4.0/denai/routes/plugins.py +26 -0
  24. denai-0.4.0/denai/routes/questions.py +33 -0
  25. denai-0.4.0/denai/routes/rag.py +143 -0
  26. denai-0.4.0/denai/routes/ui.py +90 -0
  27. denai-0.4.0/denai/security/__init__.py +18 -0
  28. denai-0.4.0/denai/security/auth.py +34 -0
  29. denai-0.4.0/denai/security/command_filter.py +42 -0
  30. denai-0.4.0/denai/security/rate_limit.py +33 -0
  31. denai-0.4.0/denai/security/sandbox.py +44 -0
  32. denai-0.4.0/denai/static/login.html +460 -0
  33. denai-0.4.0/denai/static/ui.html +4086 -0
  34. denai-0.4.0/denai/static/vendor/github-dark-dimmed.min.css +9 -0
  35. denai-0.4.0/denai/static/vendor/highlight.min.js +1213 -0
  36. denai-0.4.0/denai/static/vendor/marked.min.js +69 -0
  37. denai-0.4.0/denai/tools/__init__.py +5 -0
  38. denai-0.4.0/denai/tools/command_exec.py +145 -0
  39. denai-0.4.0/denai/tools/file_ops.py +361 -0
  40. denai-0.4.0/denai/tools/grep.py +175 -0
  41. denai-0.4.0/denai/tools/memory.py +197 -0
  42. denai-0.4.0/denai/tools/planning.py +188 -0
  43. denai-0.4.0/denai/tools/question.py +141 -0
  44. denai-0.4.0/denai/tools/rag_search.py +128 -0
  45. denai-0.4.0/denai/tools/registry.py +61 -0
  46. denai-0.4.0/denai/tools/think.py +46 -0
  47. denai-0.4.0/denai/tools/web_fetch.py +302 -0
  48. denai-0.4.0/pyproject.toml +84 -0
denai-0.4.0/.gitignore ADDED
@@ -0,0 +1,38 @@
1
+ # Byte-compiled
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Virtual envs
7
+ .venv/
8
+ venv/
9
+ ENV/
10
+
11
+ # Distribution
12
+ dist/
13
+ build/
14
+ *.egg-info/
15
+ *.egg
16
+
17
+ # IDE
18
+ .idea/
19
+ .vscode/
20
+ *.swp
21
+ *.swo
22
+ *~
23
+
24
+ # OS
25
+ .DS_Store
26
+ Thumbs.db
27
+
28
+ # DenAI data (local)
29
+ .denai/
30
+
31
+ # Testing
32
+ .coverage
33
+ htmlcov/
34
+ .pytest_cache/
35
+
36
+ # Env files
37
+ .env
38
+ .env.local
denai-0.4.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rodrigo Gobbo
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.
denai-0.4.0/PKG-INFO ADDED
@@ -0,0 +1,444 @@
1
+ Metadata-Version: 2.4
2
+ Name: denai
3
+ Version: 0.4.0
4
+ Summary: 🐺 Your private AI den. Local LLM assistant with tools, memory and zero cloud dependency.
5
+ Project-URL: Homepage, https://github.com/rodrigogobbo/denai
6
+ Project-URL: Repository, https://github.com/rodrigogobbo/denai
7
+ Project-URL: Issues, https://github.com/rodrigogobbo/denai/issues
8
+ Project-URL: Changelog, https://github.com/rodrigogobbo/denai/releases
9
+ Author-email: Rodrigo Gobbo <rodrigo@gobbo.dev>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: ai,assistant,llm,local,ollama,privacy,tools
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Environment :: Console
15
+ Classifier: Environment :: Web Environment
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: Intended Audience :: End Users/Desktop
18
+ Classifier: License :: OSI Approved :: MIT License
19
+ Classifier: Operating System :: OS Independent
20
+ Classifier: Programming Language :: Python :: 3
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Topic :: Communications :: Chat
26
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
27
+ Classifier: Typing :: Typed
28
+ Requires-Python: >=3.10
29
+ Requires-Dist: aiosqlite>=0.20
30
+ Requires-Dist: fastapi>=0.115
31
+ Requires-Dist: httpx>=0.28
32
+ Requires-Dist: python-multipart>=0.0.18
33
+ Requires-Dist: pyyaml>=6.0
34
+ Requires-Dist: uvicorn[standard]>=0.34
35
+ Provides-Extra: dev
36
+ Requires-Dist: build; extra == 'dev'
37
+ Requires-Dist: pytest-asyncio>=1.0; extra == 'dev'
38
+ Requires-Dist: pytest>=8.0; extra == 'dev'
39
+ Requires-Dist: ruff>=0.8; extra == 'dev'
40
+ Description-Content-Type: text/markdown
41
+
42
+ # 🐺 DenAI
43
+
44
+ **Your private AI den.**
45
+
46
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
47
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
48
+ [![PyPI version](https://img.shields.io/pypi/v/denai.svg)](https://pypi.org/project/denai/)
49
+ [![GitHub stars](https://img.shields.io/github/stars/rodrigogobbo/denai?style=social)](https://github.com/rodrigogobbo/denai)
50
+ [![Tests](https://github.com/rodrigogobbo/denai/actions/workflows/ci.yml/badge.svg)](https://github.com/rodrigogobbo/denai/actions/workflows/ci.yml)
51
+
52
+ A fully local AI assistant with tools, memory, and **zero cloud dependency**. Chat with LLMs on your machine — your data never leaves your computer.
53
+
54
+ ---
55
+
56
+ ## ✨ Features
57
+
58
+ - 🔒 **100% Private** — Everything runs locally. No data leaves your machine. Ever.
59
+ - 🧠 **Persistent Memory** — Remembers context across conversations (SQLite)
60
+ - 🛠️ **Built-in Tools** — File I/O, grep, web search, shell commands, planning, and more (16 tools)
61
+ - 🌐 **Web UI** — Clean chat interface served automatically at `localhost:4078`
62
+ - 🔄 **Model Switching** — Swap between Ollama models on the fly
63
+ - 📡 **Share Mode** — Expose your instance with authentication via `--share`
64
+ - ⚡ **Streaming** — Real-time token-by-token responses with tool-specific icons
65
+ - 🎨 **Dark/Light Mode** — Toggle with `Ctrl+T`, persists across sessions
66
+ - 📤 **Export** — Download conversations as JSON or Markdown
67
+ - 🔍 **Search** — Find conversations by title or content
68
+ - 🧙 **Setup Wizard** — Guided first-boot experience for beginners
69
+ - 🧩 **Extensible** — Drop a Python file in `denai/tools/` and it's auto-discovered
70
+ - 🧠 **Smart Context** — Dynamic context window (8k→32k→64k) with auto-summarization
71
+ - 🔄 **Deep Tool Chains** — Up to 25 tool call rounds per message (configurable)
72
+ - ⚡ **Parallel Tools** — Read-only tools run concurrently for faster responses
73
+ - 📋 **Plans UI** — Visual plan management with progress tracking in sidebar
74
+ - ⚙️ **config.yaml** — Persistent configuration in `~/.denai/config.yaml`
75
+ - 🌍 **Offline First** — Works without internet after initial setup
76
+
77
+ ---
78
+
79
+ ## 🏗️ Architecture
80
+
81
+ ```
82
+ ┌─────────────────────────────────────────────┐
83
+ │ Browser │
84
+ │ localhost:4078 │
85
+ └────────────────────┬────────────────────────┘
86
+ │ HTTP / WebSocket
87
+ ┌────────────────────▼────────────────────────┐
88
+ │ DenAI Server │
89
+ │ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │
90
+ │ │ FastAPI │ │ Tools │ │ Memory │ │
91
+ │ │ (routes) │ │ (auto- │ │ (SQLite / │ │
92
+ │ │ │ │ discover)│ │ JSON) │ │
93
+ │ └─────┬────┘ └────┬─────┘ └──────┬──────┘ │
94
+ │ │ │ │ │
95
+ │ └───────────┼──────────────┘ │
96
+ │ │ │
97
+ └────────────────────┼────────────────────────┘
98
+ │ Ollama API (:11434)
99
+ ┌────────────────────▼────────────────────────┐
100
+ │ Ollama │
101
+ │ LLM Models (local) │
102
+ └─────────────────────────────────────────────┘
103
+ ```
104
+
105
+ ---
106
+
107
+ ## 🚀 Quickstart
108
+
109
+ ### 1. Install Ollama
110
+
111
+ ```bash
112
+ # macOS / Linux
113
+ curl -fsSL https://ollama.com/install.sh | sh
114
+
115
+ # Windows — download from https://ollama.com/download
116
+ ```
117
+
118
+ ### 2. Pull a model
119
+
120
+ ```bash
121
+ ollama pull llama3.1:8b
122
+ ```
123
+
124
+ ### 3. Install DenAI
125
+
126
+ ```bash
127
+ pip install denai
128
+ ```
129
+
130
+ ### 4. Run
131
+
132
+ ```bash
133
+ denai
134
+ ```
135
+
136
+ Open your browser at **http://localhost:4078** — that's it! 🎉
137
+
138
+ ---
139
+
140
+ ## 🛠️ Available Tools
141
+
142
+ DenAI comes with **16 built-in tools** that the AI can use automatically:
143
+
144
+ | Tool | Description | Internet? |
145
+ |------|-------------|:-:|
146
+ | `file_read` | Read files with line numbers (offset/limit for large files) | ❌ |
147
+ | `file_write` | Create or overwrite files (auto-backup + auto-creates directories) | ❌ |
148
+ | `list_files` | List directory contents with glob patterns | ❌ |
149
+ | `file_edit` | Search/replace in files (exact text matching, auto-backup) | ❌ |
150
+ | `grep` | Regex search across files (include filter, skips .git/node_modules) | ❌ |
151
+ | `command_exec` | Execute shell commands (sandboxed + filtered) | ❌ |
152
+ | `web_search` | Search DuckDuckGo or fetch content from any URL | ✅ |
153
+ | `memory_save` | Save persistent memory (fact/decision/preference/observation) | ❌ |
154
+ | `memory_search` | Search saved memories by keywords and type | ❌ |
155
+ | `rag_search` | Search indexed local documents (BM25) | ❌ |
156
+ | `rag_index` | Reindex `~/.denai/documents/` | ❌ |
157
+ | `rag_stats` | Show RAG index statistics | ❌ |
158
+ | `question` | Ask the user a question and wait for the answer | ❌ |
159
+ | `plan_create` | Create a multi-step execution plan (persisted in SQLite) | ❌ |
160
+ | `plan_update` | Mark plan steps as done / in progress | ❌ |
161
+ | `think` | Internal reasoning scratchpad (no side-effects) | ❌ |
162
+
163
+ Tools are auto-discovered from `denai/tools/`. Drop a new `.py` file and it just works.
164
+
165
+ ---
166
+
167
+ ## 💻 System Requirements
168
+
169
+ | Tier | RAM | Storage | GPU | Experience |
170
+ |------|-----|---------|-----|------------|
171
+ | 🟢 **Mínimo** | 8 GB | 10 GB livre | Não precisa | Modelos 3B — respostas simples, sem tool calling confiável |
172
+ | ⭐ **Recomendado** | 16 GB | 20 GB livre | Não precisa | Modelos 7-8B — bom tool calling, respostas consistentes |
173
+ | 🏆 **Ideal** | 32 GB+ | 40 GB livre | Qualquer GPU com 8GB+ VRAM | Modelos 14-32B — tool calling preciso, planning multi-step |
174
+
175
+ ### "Consigo fazer o mesmo que o ChatGPT/Copilot?"
176
+
177
+ Resposta honesta:
178
+
179
+ | Capacidade | Cloud (GPT-4, Claude) | DenAI 8B | DenAI 32B |
180
+ |------------|----------------------|----------|-----------|
181
+ | Conversa geral | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
182
+ | Gerar código | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
183
+ | Tool calling (ler/editar/executar) | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐ |
184
+ | Planning multi-step | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐ |
185
+ | Contexto longo (100k+ tokens) | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ (auto 8-32k) | ⭐⭐⭐⭐ (auto 32-64k) |
186
+ | Privacidade | ❌ Dados vão pra nuvem | ✅ 100% local | ✅ 100% local |
187
+ | Custo | $20-200/mês | **Grátis** | **Grátis** |
188
+ | Funciona offline | ❌ | ✅ | ✅ |
189
+
190
+ > 💡 **Resumo prático:** Com **8 GB RAM + modelo 8B**, o DenAI é um bom assistente de conversa e código, mas erra em tool calling complexo. Com **32 GB RAM + qwen2.5-coder:32b**, chega perto da experiência de cloud — tool calling confiável, planning, edição de arquivos em sequência. O contexto agora escala automaticamente de 8k a 64k tokens, com sumarização automática de mensagens antigas para sessões longas.
191
+
192
+ ### Qual computador comprar?
193
+
194
+ Se está pensando em montar/comprar um PC pra rodar IA local:
195
+
196
+ - **Orçamento mínimo (~R$2.500):** PC usado com 16 GB RAM + SSD. Roda modelos 7-8B bem.
197
+ - **Orçamento ideal (~R$5.000-8.000):** 32 GB RAM + GPU com 8 GB VRAM (RTX 3060/4060). Roda modelos 14-32B com velocidade.
198
+ - **Notebook:** MacBook com Apple Silicon (M1/M2/M3 com 16 GB+) é excelente pra IA local — memória unificada beneficia muito os modelos.
199
+
200
+ ---
201
+
202
+ ## 🧠 AI Models
203
+
204
+ | Model | Size | RAM | What it can do | Recommendation |
205
+ |-------|------|-----|----------------|:-:|
206
+ | `llama3.2:3b` | ~2 GB | 8 GB | Conversa, Q&A, texto simples | 🟢 PCs fracos |
207
+ | `gemma3:4b` | ~3.3 GB | 8 GB | Conversa, código básico | 🟢 Alternativa leve |
208
+ | `llama3.1:8b` | ~4.7 GB | 10 GB | Conversa + tool calling básico | ⭐ **Recomendado** |
209
+ | `qwen2.5-coder:7b` | ~4.4 GB | 10 GB | Código + tools, bom em programação | 🔵 Devs |
210
+ | `mistral:7b` | ~4.1 GB | 10 GB | Versátil, multilingual | 🟡 All-rounder |
211
+ | `deepseek-r1:8b` | ~4.9 GB | 10 GB | Raciocínio, matemática, lógica | 🟣 Problemas complexos |
212
+ | `qwen2.5-coder:14b` | ~9 GB | 16 GB | Tool calling confiável, planning | 🔵 Devs com 16 GB |
213
+ | `qwen2.5-coder:32b` | ~18 GB | 24 GB | Melhor tool calling + planning multi-step | 🏆 **Power users** |
214
+
215
+ ```bash
216
+ # Install any model
217
+ ollama pull <model-name>
218
+
219
+ # List installed models
220
+ ollama list
221
+ ```
222
+
223
+ ---
224
+
225
+ ## ⚙️ Configuration
226
+
227
+ | Variable | Default | Description |
228
+ |----------|---------|-------------|
229
+ | `DENAI_HOST` | `127.0.0.1` | Bind address |
230
+ | `DENAI_PORT` | `4078` | Server port |
231
+ | `DENAI_MODEL` | `llama3.1:8b` | Default Ollama model |
232
+ | `DENAI_OLLAMA_URL` | `http://localhost:11434` | Ollama API endpoint |
233
+ | `DENAI_MAX_TOOL_ROUNDS` | `25` | Max tool call rounds per message |
234
+ | `DENAI_MAX_CONTEXT` | `65536` | Max context window size (tokens) |
235
+ | `DENAI_SHARE` | `false` | Enable share mode |
236
+
237
+ ```bash
238
+ # Example: larger context + custom model
239
+ DENAI_MAX_CONTEXT=131072 DENAI_MODEL=qwen2.5-coder:32b denai
240
+ ```
241
+
242
+ ---
243
+
244
+ ## 🧩 Plugins
245
+
246
+ Extend DenAI with custom tools by dropping Python files in `~/.denai/plugins/`:
247
+
248
+ ### Single-file plugin
249
+
250
+ ```python
251
+ # ~/.denai/plugins/calculator.py
252
+ """Plugin: calculadora."""
253
+
254
+ SPEC = {
255
+ "type": "function",
256
+ "function": {
257
+ "name": "calculator",
258
+ "description": "Calcula expressões matemáticas.",
259
+ "parameters": {
260
+ "type": "object",
261
+ "properties": {
262
+ "expression": {"type": "string", "description": "Ex: '2 + 3 * 4'"}
263
+ },
264
+ "required": ["expression"],
265
+ },
266
+ },
267
+ }
268
+
269
+ async def calculator(args: dict) -> str:
270
+ expr = args.get("expression", "")
271
+ allowed = set("0123456789+-*/.() ")
272
+ if not all(c in allowed for c in expr):
273
+ return "Caracteres não permitidos"
274
+ return f"Resultado: {eval(expr, {'__builtins__': {}}, {})}"
275
+
276
+ TOOLS = [(SPEC, "calculator")]
277
+ ```
278
+
279
+ ### Directory plugin
280
+
281
+ ```
282
+ ~/.denai/plugins/weather/
283
+ ├── plugin.json # {"name": "weather", "version": "1.0.0"}
284
+ └── main.py # TOOLS + functions (same format)
285
+ ```
286
+
287
+ Plugins are auto-discovered on startup. Use `POST /api/plugins/reload` to reload without restart.
288
+
289
+ See `examples/plugins/` for ready-to-use examples.
290
+
291
+ ---
292
+
293
+ ## 🔗 Share Mode
294
+
295
+ Expose your local DenAI to others on the network (or via tunnel):
296
+
297
+ ```bash
298
+ denai --share
299
+ ```
300
+
301
+ - Generates a login page with API key authentication
302
+ - Only authenticated users can access the chat
303
+ - All traffic stays in your local network by default
304
+
305
+ ---
306
+
307
+ ## 🔐 Security
308
+
309
+ | Layer | Description |
310
+ |-------|-------------|
311
+ | **API Key** | Required for share mode; auto-generated or set via `DENAI_API_KEY` |
312
+ | **Command Sandbox** | Dangerous commands (`rm -rf /`, `format`, etc.) are blocked |
313
+ | **Command Filter** | Allowlist/blocklist for shell commands |
314
+ | **Rate Limiting** | Configurable requests-per-minute to prevent abuse |
315
+ | **Local Only** | By default, binds to `127.0.0.1` — no external access |
316
+
317
+ ---
318
+
319
+ ## ⚙️ Configuration
320
+
321
+ Configuration priority: **CLI args > env vars > `~/.denai/config.yaml` > defaults**
322
+
323
+ ### config.yaml (recommended)
324
+
325
+ Create `~/.denai/config.yaml`:
326
+
327
+ ```yaml
328
+ model: llama3.1:8b
329
+ ollama_url: http://localhost:11434
330
+ port: 4078
331
+ share: false
332
+ max_tool_rounds: 25
333
+ max_context: 65536
334
+ ```
335
+
336
+ A `config.example.yaml` is included in the repo as reference.
337
+
338
+ ### Environment Variables
339
+
340
+ | Variable | Default | Description |
341
+ |----------|---------|-------------|
342
+ | `DENAI_HOST` | `127.0.0.1` | Bind address |
343
+ | `DENAI_PORT` | `4078` | Server port |
344
+ | `DENAI_MODEL` | `llama3.1:8b` | Default Ollama model |
345
+ | `DENAI_OLLAMA_URL` | `http://localhost:11434` | Ollama API endpoint |
346
+ | `DENAI_API_KEY` | *(auto-generated)* | API key for share mode |
347
+ | `DENAI_MAX_TOOL_ROUNDS` | `25` | Max tool call rounds per message |
348
+ | `DENAI_MAX_CONTEXT` | `65536` | Max context window (tokens) |
349
+
350
+ ---
351
+
352
+ ## 🧑‍💻 Development
353
+
354
+ ```bash
355
+ # Clone the repo
356
+ git clone https://github.com/your-org/denai.git
357
+ cd denai
358
+
359
+ # Create virtual environment
360
+ python -m venv .venv
361
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
362
+
363
+ # Install in dev mode
364
+ pip install -e ".[dev]"
365
+
366
+ # Run tests
367
+ pytest
368
+
369
+ # Lint
370
+ ruff check .
371
+
372
+ # Run locally
373
+ python -m denai
374
+ ```
375
+
376
+ ### Project Structure
377
+
378
+ ```
379
+ denai/
380
+ ├── denai/
381
+ │ ├── __init__.py
382
+ │ ├── __main__.py # CLI entrypoint
383
+ │ ├── app.py # FastAPI app factory
384
+ │ ├── config.py # Settings & env vars
385
+ │ ├── db.py # SQLite (aiosqlite)
386
+ │ ├── network.py # Local IP detection
387
+ │ ├── llm/ # LLM integration
388
+ │ │ ├── ollama.py # Ollama streaming + tool loop
389
+ │ │ └── prompt.py # System prompt builder
390
+ │ ├── rag/ # RAG engine
391
+ │ │ └── __init__.py # BM25 index, tokenizer, chunker
392
+ │ ├── routes/ # API endpoints
393
+ │ │ ├── chat.py # POST /api/chat (SSE)
394
+ │ │ ├── conversations.py # CRUD conversations
395
+ │ │ ├── models.py # Ollama models
396
+ │ │ ├── plugins.py # Plugin management
397
+ │ │ └── rag.py # RAG endpoints
398
+ │ ├── security/ # Security layers
399
+ │ │ ├── auth.py # API key
400
+ │ │ ├── sandbox.py # Path validation
401
+ │ │ ├── command_filter.py# Command blocklist
402
+ │ │ └── rate_limit.py # Per-IP rate limiting
403
+ │ ├── plugins/ # Plugin autodiscovery
404
+ │ ├── static/ # Web UI (SPA)
405
+ │ └── tools/ # Auto-discovered tools
406
+ │ ├── registry.py # Tool dispatcher
407
+ │ ├── file_ops.py # file_read, file_write, list_files
408
+ │ ├── command_exec.py # command_exec
409
+ │ ├── memory.py # memory_save, memory_search
410
+ │ ├── web_fetch.py # web_search
411
+ │ └── rag_search.py # rag_search, rag_index, rag_stats
412
+ ├── tests/ # 237 tests
413
+ ├── examples/plugins/ # Example plugins
414
+ ├── pyproject.toml
415
+ ├── README.md
416
+ ├── CHANGELOG.md
417
+ └── LICENSE
418
+ ```
419
+
420
+ ---
421
+
422
+ ## 🤝 Contributing
423
+
424
+ We'd love your help! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
425
+
426
+ ---
427
+
428
+ ## 📄 License
429
+
430
+ [MIT](LICENSE) — use it, fork it, ship it.
431
+
432
+ ---
433
+
434
+ ## 🙏 Credits
435
+
436
+ Built on the shoulders of giants:
437
+
438
+ - **[Ollama](https://ollama.com)** — Local LLM runtime
439
+ - **[FastAPI](https://fastapi.tiangolo.com)** — High-performance Python web framework
440
+ - **[DuckDuckGo](https://duckduckgo.com)** — Privacy-first web search
441
+
442
+ ---
443
+
444
+ > 🐺 *Your den, your data, your AI.*