powergrid-ai 1.0.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 (56) hide show
  1. powergrid_ai-1.0.0/.github/workflows/ci.yml +66 -0
  2. powergrid_ai-1.0.0/.gitignore +52 -0
  3. powergrid_ai-1.0.0/CHANGELOG.md +37 -0
  4. powergrid_ai-1.0.0/LICENSE +21 -0
  5. powergrid_ai-1.0.0/PKG-INFO +416 -0
  6. powergrid_ai-1.0.0/README.md +375 -0
  7. powergrid_ai-1.0.0/config.example.yaml +102 -0
  8. powergrid_ai-1.0.0/powergrid/__init__.py +3 -0
  9. powergrid_ai-1.0.0/powergrid/__main__.py +6 -0
  10. powergrid_ai-1.0.0/powergrid/api/__init__.py +0 -0
  11. powergrid_ai-1.0.0/powergrid/api/app.py +232 -0
  12. powergrid_ai-1.0.0/powergrid/api/middleware/__init__.py +0 -0
  13. powergrid_ai-1.0.0/powergrid/api/middleware/logging.py +51 -0
  14. powergrid_ai-1.0.0/powergrid/api/routes/__init__.py +0 -0
  15. powergrid_ai-1.0.0/powergrid/api/routes/chat.py +202 -0
  16. powergrid_ai-1.0.0/powergrid/api/routes/models.py +37 -0
  17. powergrid_ai-1.0.0/powergrid/api/routes/status.py +84 -0
  18. powergrid_ai-1.0.0/powergrid/cli/__init__.py +0 -0
  19. powergrid_ai-1.0.0/powergrid/cli/app.py +748 -0
  20. powergrid_ai-1.0.0/powergrid/config/__init__.py +0 -0
  21. powergrid_ai-1.0.0/powergrid/config/settings.py +178 -0
  22. powergrid_ai-1.0.0/powergrid/core/__init__.py +0 -0
  23. powergrid_ai-1.0.0/powergrid/core/cache/__init__.py +0 -0
  24. powergrid_ai-1.0.0/powergrid/core/cache/manager.py +85 -0
  25. powergrid_ai-1.0.0/powergrid/core/health/__init__.py +0 -0
  26. powergrid_ai-1.0.0/powergrid/core/health/tracker.py +127 -0
  27. powergrid_ai-1.0.0/powergrid/core/quota/__init__.py +0 -0
  28. powergrid_ai-1.0.0/powergrid/core/quota/engine.py +175 -0
  29. powergrid_ai-1.0.0/powergrid/core/retry/__init__.py +0 -0
  30. powergrid_ai-1.0.0/powergrid/core/retry/handler.py +222 -0
  31. powergrid_ai-1.0.0/powergrid/core/router/__init__.py +0 -0
  32. powergrid_ai-1.0.0/powergrid/core/router/analyzer.py +156 -0
  33. powergrid_ai-1.0.0/powergrid/core/router/engine.py +288 -0
  34. powergrid_ai-1.0.0/powergrid/credentials.py +235 -0
  35. powergrid_ai-1.0.0/powergrid/models/__init__.py +0 -0
  36. powergrid_ai-1.0.0/powergrid/models/schemas.py +152 -0
  37. powergrid_ai-1.0.0/powergrid/providers/__init__.py +4 -0
  38. powergrid_ai-1.0.0/powergrid/providers/base.py +171 -0
  39. powergrid_ai-1.0.0/powergrid/providers/gemini.py +152 -0
  40. powergrid_ai-1.0.0/powergrid/providers/mock.py +153 -0
  41. powergrid_ai-1.0.0/powergrid/providers/openai_compatible.py +119 -0
  42. powergrid_ai-1.0.0/powergrid/providers/registry.py +63 -0
  43. powergrid_ai-1.0.0/powergrid/storage/__init__.py +0 -0
  44. powergrid_ai-1.0.0/powergrid/storage/database.py +407 -0
  45. powergrid_ai-1.0.0/pyproject.toml +75 -0
  46. powergrid_ai-1.0.0/tests/__init__.py +0 -0
  47. powergrid_ai-1.0.0/tests/smoke_test.py +74 -0
  48. powergrid_ai-1.0.0/tests/test_api.py +149 -0
  49. powergrid_ai-1.0.0/tests/test_cache.py +128 -0
  50. powergrid_ai-1.0.0/tests/test_failover.py +86 -0
  51. powergrid_ai-1.0.0/tests/test_mock_provider.py +55 -0
  52. powergrid_ai-1.0.0/tests/test_quota.py +133 -0
  53. powergrid_ai-1.0.0/tests/test_real_e2e.py +155 -0
  54. powergrid_ai-1.0.0/tests/test_real_groq.py +44 -0
  55. powergrid_ai-1.0.0/tests/test_routing.py +268 -0
  56. powergrid_ai-1.0.0/tests/test_security.py +89 -0
@@ -0,0 +1,66 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master]
6
+ pull_request:
7
+ branches: [main, master]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ${{ matrix.os }}
12
+ strategy:
13
+ matrix:
14
+ os: [ubuntu-latest, windows-latest]
15
+ python-version: ["3.11", "3.12", "3.13"]
16
+ fail-fast: false
17
+
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - name: Set up Python ${{ matrix.python-version }}
22
+ uses: actions/setup-python@v5
23
+ with:
24
+ python-version: ${{ matrix.python-version }}
25
+
26
+ - name: Install dependencies
27
+ run: |
28
+ python -m pip install --upgrade pip
29
+ pip install -e ".[dev]"
30
+
31
+ - name: Lint with ruff
32
+ run: |
33
+ ruff check powergrid/ tests/
34
+ ruff format --check powergrid/ tests/
35
+
36
+ - name: Type check with mypy
37
+ run: mypy powergrid/ --ignore-missing-imports
38
+ continue-on-error: true
39
+
40
+ - name: Run tests
41
+ run: pytest tests/ -v --tb=short -x
42
+
43
+ publish:
44
+ needs: test
45
+ runs-on: ubuntu-latest
46
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
47
+ permissions:
48
+ id-token: write
49
+ steps:
50
+ - uses: actions/checkout@v4
51
+
52
+ - name: Set up Python
53
+ uses: actions/setup-python@v5
54
+ with:
55
+ python-version: "3.12"
56
+
57
+ - name: Install build tools
58
+ run: pip install build
59
+
60
+ - name: Build package
61
+ run: python -m build
62
+
63
+ - name: Publish to PyPI
64
+ uses: pypa/gh-action-pypi-publish@release/v1
65
+ with:
66
+ skip-existing: true
@@ -0,0 +1,52 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ *.egg
7
+ *.egg-info/
8
+ dist/
9
+ build/
10
+ eggs/
11
+ *.whl
12
+ pip-log.txt
13
+ pip-delete-this-directory.txt
14
+
15
+ # Virtual environments
16
+ venv/
17
+ .venv/
18
+ env/
19
+ ENV/
20
+
21
+ # IDE
22
+ .vscode/
23
+ .idea/
24
+ *.swp
25
+ *.swo
26
+ *~
27
+
28
+ # OS
29
+ .DS_Store
30
+ Thumbs.db
31
+ desktop.ini
32
+
33
+ # PowerGrid runtime
34
+ *.db
35
+ *.db-journal
36
+ powergrid.pid
37
+
38
+ # Test / coverage
39
+ .pytest_cache/
40
+ htmlcov/
41
+ .coverage
42
+ .coverage.*
43
+ coverage.xml
44
+
45
+ # Distribution
46
+ *.tar.gz
47
+ *.zip
48
+
49
+ # Environment / secrets
50
+ .env
51
+ .env.*
52
+ !.env.example
@@ -0,0 +1,37 @@
1
+ # Changelog
2
+
3
+ All notable changes to PowerGrid will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0] - 2026-09-01
9
+
10
+ ### Added
11
+ - **Routing Engine** — intelligent, round-robin, and priority routing strategies
12
+ - **Provider Adapters** — OpenAI-compatible, Google Gemini, and Mock providers
13
+ - **Health Tracking** — automatic provider health monitoring with cooldown and exponential backoff
14
+ - **Quota Engine** — RPM/TPM/RPD/TPD tracking with predictive rate limit protection
15
+ - **Retry & Failover** — automatic retries across providers with exponential backoff and jitter
16
+ - **Response Cache** — TTL-based exact-match caching to avoid redundant API calls
17
+ - **Request Analyzer** — task type classification (coding, reasoning, creative, etc.)
18
+ - **CLI** — 15+ commands: init, start, stop, status, providers, models, logs, test, config, cache-clear
19
+ - **Interactive Provider Wizard** — add providers with templates for 8+ services (Groq, Cerebras, Gemini, OpenRouter, Together, NVIDIA, Mistral, Azure OpenAI)
20
+ - **Secure Credential Storage** — OS keyring integration (Windows Credential Manager, macOS Keychain, Linux Secret Service) with file fallback
21
+ - **OpenAI-Compatible API** — drop-in replacement for any OpenAI SDK usage
22
+ - **Streaming Support** — SSE streaming for chat completions
23
+ - **Auth Protection** — optional API token for endpoint security
24
+ - **Request Logging** — middleware with correlation IDs and timing headers
25
+ - **Mock Provider** — simulate success, 429s, timeouts, and errors for testing
26
+ - **GitHub Actions CI** — automated testing on Python 3.11/3.12/3.13, Ubuntu and Windows
27
+ - **Graceful Shutdown** — clean provider connection cleanup on SIGTERM/SIGINT
28
+ - **Startup Health Checks** — verify provider connectivity on boot
29
+ - **Request Validation** — message count and size limits to prevent abuse
30
+ - **Localhost-Only CORS** — secure default for local development
31
+
32
+ ### Security
33
+ - API keys never appear in logs, API responses, or config dumps
34
+ - Auth token protection on `/v1/` endpoints
35
+ - Localhost-only binding by default with explicit warning for `0.0.0.0`
36
+ - OS credential store for API keys (not plaintext config files)
37
+ - Request body size limits (1MB)
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Michael Moses
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.
@@ -0,0 +1,416 @@
1
+ Metadata-Version: 2.5
2
+ Name: powergrid-ai
3
+ Version: 1.0.0
4
+ Summary: Local-first AI routing runtime — one AI, many engines
5
+ Project-URL: Homepage, https://github.com/micymike/powergrid
6
+ Project-URL: Repository, https://github.com/micymike/powergrid
7
+ Project-URL: Issues, https://github.com/micymike/powergrid/issues
8
+ Project-URL: Changelog, https://github.com/micymike/powergrid/blob/main/CHANGELOG.md
9
+ Author-email: Michael Moses <micymike@example.com>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: ai,failover,llm,local-first,multi-provider,openai,routing
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Requires-Python: >=3.11
22
+ Requires-Dist: aiosqlite>=0.20.0
23
+ Requires-Dist: click>=8.1.0
24
+ Requires-Dist: fastapi>=0.115.0
25
+ Requires-Dist: httpx>=0.27.0
26
+ Requires-Dist: keyring>=25.0.0
27
+ Requires-Dist: pydantic-settings>=2.5.0
28
+ Requires-Dist: pydantic>=2.9.0
29
+ Requires-Dist: pyyaml>=6.0.0
30
+ Requires-Dist: rich>=13.9.0
31
+ Requires-Dist: sqlalchemy>=2.0.0
32
+ Requires-Dist: sse-starlette>=2.1.0
33
+ Requires-Dist: typer>=0.12.0
34
+ Requires-Dist: uvicorn[standard]>=0.30.0
35
+ Provides-Extra: dev
36
+ Requires-Dist: mypy>=1.11.0; extra == 'dev'
37
+ Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
38
+ Requires-Dist: pytest>=8.3.0; extra == 'dev'
39
+ Requires-Dist: ruff>=0.6.0; extra == 'dev'
40
+ Description-Content-Type: text/markdown
41
+
42
+ # PowerGrid
43
+
44
+ **Local-first AI routing runtime — one AI, many engines.**
45
+
46
+ PowerGrid runs on your machine and makes multiple AI providers appear as a single OpenAI-compatible endpoint. Your applications talk to `localhost:8787`, and PowerGrid intelligently routes requests across your available providers.
47
+
48
+ [![CI](https://github.com/micymike/powergrid/actions/workflows/ci.yml/badge.svg)](https://github.com/micymike/powergrid/actions/workflows/ci.yml)
49
+ [![PyPI version](https://img.shields.io/pypi/v/powergrid)](https://pypi.org/project/powergrid/)
50
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
51
+
52
+ ## Why PowerGrid?
53
+
54
+ Developers often have access to multiple AI providers (Groq, Gemini, Cerebras, OpenRouter, etc.). PowerGrid lets you:
55
+
56
+ - **Use all your providers through one endpoint** — no app changes needed
57
+ - **Get automatic failover** — if one provider is down or rate-limited, traffic shifts seamlessly
58
+ - **Predict rate limits** — PowerGrid tracks usage and shifts traffic *before* you hit 429s
59
+ - **Stay local** — your API keys never leave your machine
60
+ - **Stay free** — PowerGrid itself costs $0/month
61
+
62
+ ## Quick Start
63
+
64
+ ```bash
65
+ # Install
66
+ pip install powergrid-ai
67
+
68
+ # Initialize
69
+ powergrid init
70
+
71
+ # Add a provider
72
+ powergrid provider
73
+
74
+ # Start
75
+ powergrid start
76
+ ```
77
+
78
+ Then use it:
79
+
80
+ ```python
81
+ from openai import OpenAI
82
+
83
+ client = OpenAI(
84
+ base_url="http://localhost:8787/v1",
85
+ api_key="powergrid"
86
+ )
87
+
88
+ response = client.chat.completions.create(
89
+ model="powergrid-auto",
90
+ messages=[{"role": "user", "content": "Hello!"}]
91
+ )
92
+ ```
93
+
94
+ ## Architecture
95
+
96
+ ```
97
+ APPLICATION
98
+ |
99
+ v
100
+ +----------------+
101
+ | POWERGRID |
102
+ | Local Runtime |
103
+ +-------+--------+
104
+ |
105
+ Request Analyzer
106
+ |
107
+ Routing Engine
108
+ |
109
+ +---------------+---------------+
110
+ | | |
111
+ v v v
112
+ Gemini Groq Cerebras
113
+ | | |
114
+ +---------------+---------------+
115
+ |
116
+ v
117
+ Unified Response
118
+ ```
119
+
120
+ ### Core Components
121
+
122
+ | Component | Purpose |
123
+ |-----------|---------|
124
+ | **Provider Adapters** | Normalize provider APIs into a common format |
125
+ | **Routing Engine** | Score and select the best provider per request |
126
+ | **Health Tracker** | Monitor provider availability and apply cooldowns |
127
+ | **Quota Engine** | Track usage and predict rate limit exhaustion |
128
+ | **Retry Handler** | Manage retries, failover, and backoff |
129
+ | **Cache** | Exact-match response caching with TTL |
130
+ | **Request Analyzer** | Classify task types with heuristics |
131
+
132
+ ## Provider Configuration
133
+
134
+ ### Interactive Setup
135
+
136
+ ```bash
137
+ powergrid provider
138
+ ```
139
+
140
+ ### YAML Configuration
141
+
142
+ Copy `config.example.yaml` to `~/.config/powergrid/config.yaml`:
143
+
144
+ ```yaml
145
+ providers:
146
+ - name: groq
147
+ type: openai_compatible
148
+ base_url: https://api.groq.com/openai/v1
149
+ api_key_env: GROQ_API_KEY
150
+ models:
151
+ - llama-3.3-70b-versatile
152
+ priority: 90
153
+ rpm_limit: 30
154
+
155
+ - name: gemini
156
+ type: gemini
157
+ api_key_env: GEMINI_API_KEY
158
+ models:
159
+ - gemini-2.0-flash
160
+ priority: 85
161
+ ```
162
+
163
+ ### Environment Variables
164
+
165
+ Set your API keys:
166
+
167
+ ```bash
168
+ export GROQ_API_KEY=gsk_...
169
+ export GEMINI_API_KEY=AI...
170
+ export CEREBRAS_API_KEY=...
171
+ ```
172
+
173
+ ## Running
174
+
175
+ ### Foreground
176
+
177
+ ```bash
178
+ powergrid start
179
+ ```
180
+
181
+ ### Background
182
+
183
+ ```bash
184
+ powergrid start --background
185
+ powergrid status
186
+ powergrid stop
187
+ ```
188
+
189
+ ### Custom Port/Host
190
+
191
+ ```bash
192
+ powergrid start --port 9000 --host 127.0.0.1
193
+ ```
194
+
195
+ ## API Endpoints
196
+
197
+ | Endpoint | Method | Description |
198
+ |----------|--------|-------------|
199
+ | `/v1/models` | GET | List available models |
200
+ | `/v1/chat/completions` | POST | Chat completions (OpenAI-compatible) |
201
+ | `/health` | GET | Health check |
202
+ | `/status` | GET | PowerGrid status and stats |
203
+ | `/providers` | GET | Provider details |
204
+ | `/routing/logs` | GET | Recent routing decisions |
205
+ | `/routing/stats` | GET | Aggregate statistics |
206
+
207
+ ## Agent Configuration
208
+
209
+ ### OpenCode
210
+
211
+ In `opencode.json`:
212
+
213
+ ```json
214
+ {
215
+ "provider": {
216
+ "name": "powergrid",
217
+ "model": "powergrid-auto",
218
+ "api_key": "powergrid",
219
+ "base_url": "http://localhost:8787/v1"
220
+ }
221
+ }
222
+ ```
223
+
224
+ ### Codex
225
+
226
+ ```bash
227
+ export OPENAI_BASE_URL=http://localhost:8787/v1
228
+ export OPENAI_API_KEY=powergrid
229
+ ```
230
+
231
+ ### Cline
232
+
233
+ In VS Code settings:
234
+
235
+ ```json
236
+ {
237
+ "cline.apiProvider": "openai-compatible",
238
+ "cline.openaiCompatibleBaseUrl": "http://localhost:8787/v1",
239
+ "cline.openaiCompatibleApiKey": "powergrid",
240
+ "cline.openaiCompatibleModelId": "powergrid-auto"
241
+ }
242
+ ```
243
+
244
+ ### Python (OpenAI SDK)
245
+
246
+ ```python
247
+ from openai import OpenAI
248
+
249
+ client = OpenAI(
250
+ base_url="http://localhost:8787/v1",
251
+ api_key="powergrid"
252
+ )
253
+
254
+ response = client.chat.completions.create(
255
+ model="powergrid-auto",
256
+ messages=[{"role": "user", "content": "Hello!"}]
257
+ )
258
+ ```
259
+
260
+ ### Node.js
261
+
262
+ ```javascript
263
+ import OpenAI from "openai";
264
+
265
+ const client = new OpenAI({
266
+ baseURL: "http://localhost:8787/v1",
267
+ apiKey: "powergrid",
268
+ });
269
+
270
+ const response = await client.chat.completions.create({
271
+ model: "powergrid-auto",
272
+ messages: [{ role: "user", content: "Hello!" }],
273
+ });
274
+ ```
275
+
276
+ ### curl
277
+
278
+ ```bash
279
+ curl http://localhost:8787/v1/chat/completions \
280
+ -H "Content-Type: application/json" \
281
+ -d '{
282
+ "model": "powergrid-auto",
283
+ "messages": [{"role": "user", "content": "Hello!"}]
284
+ }'
285
+ ```
286
+
287
+ ## Routing
288
+
289
+ PowerGrid supports three routing strategies:
290
+
291
+ ### Intelligent (default)
292
+
293
+ Scores providers on health, quota, capability, priority, and latency. Best for most use cases.
294
+
295
+ ### Round Robin
296
+
297
+ Cycles through providers evenly. Good for load distribution.
298
+
299
+ ### Priority
300
+
301
+ Always selects the highest-priority provider. Good when you have a clear preference order.
302
+
303
+ ## How Failover Works
304
+
305
+ 1. Request arrives and is routed to the best provider
306
+ 2. If the provider returns **429** (rate limited), PowerGrid:
307
+ - Parses the `Retry-After` header
308
+ - Puts the provider in cooldown
309
+ - Selects the next-best provider
310
+ 3. If the provider returns **5xx** or **times out**:
311
+ - Applies exponential backoff with jitter
312
+ - Fails over to another provider
313
+ 4. A request retries up to `max_retries` times across different providers
314
+ 5. If all providers fail, a clean error is returned
315
+
316
+ ## Predictive Rate Limit Protection
317
+
318
+ PowerGrid tracks request rates over time and estimates when a provider is approaching its limits:
319
+
320
+ ```
321
+ Groq RPM = 30
322
+ Recent: 18:01 → 21 requests, 18:02 → 26 requests, 18:03 → 29 requests
323
+ → PowerGrid shifts traffic BEFORE the 429 hits
324
+ ```
325
+
326
+ ## CLI Commands
327
+
328
+ | Command | Description |
329
+ |---------|-------------|
330
+ | `powergrid init` | Initialize configuration |
331
+ | `powergrid start` | Start the runtime |
332
+ | `powergrid stop` | Stop background process |
333
+ | `powergrid status` | Show runtime status |
334
+ | `powergrid providers` | List configured providers |
335
+ | `powergrid provider` | Add provider interactively |
336
+ | `powergrid provider-remove NAME` | Remove a provider |
337
+ | `powergrid models` | List virtual models |
338
+ | `powergrid logs` | Show recent routing decisions |
339
+ | `powergrid test` | Test provider connectivity |
340
+ | `powergrid config` | Show config (redacted) |
341
+ | `powergrid cache-clear` | Clear response cache |
342
+
343
+ ## Security
344
+
345
+ - **Local-only by default** — binds to `127.0.0.1`
346
+ - **API key protection** — optional `auth_token` for the endpoint
347
+ - **No key leakage** — API keys never appear in logs or API responses
348
+ - **Config redaction** — `powergrid config` masks secrets
349
+ - **Explicit 0.0.0.0 warning** — warns if you bind publicly
350
+
351
+ ## Privacy
352
+
353
+ - PowerGrid is fully local
354
+ - No telemetry is sent anywhere
355
+ - No API keys leave your machine
356
+ - No prompts or responses are stored externally
357
+ - All state lives in `~/.config/powergrid/`
358
+
359
+ ## Development
360
+
361
+ ```bash
362
+ git clone https://github.com/micymike/powergrid.git
363
+ cd powergrid
364
+ pip install -e ".[dev]"
365
+ pytest
366
+ ```
367
+
368
+ ### Mock Provider
369
+
370
+ For testing without real API keys:
371
+
372
+ ```yaml
373
+ providers:
374
+ - name: mock
375
+ type: mock
376
+ models:
377
+ - mock-model
378
+ priority: 50
379
+ ```
380
+
381
+ The mock provider simulates success, 429s, timeouts, and errors.
382
+
383
+ ## Adding Providers
384
+
385
+ Implement the `ProviderAdapter` interface:
386
+
387
+ ```python
388
+ from powergrid.providers.base import ProviderAdapter, ProviderModel, ProviderStatus
389
+
390
+ class MyProvider(ProviderAdapter):
391
+ name = "my_provider"
392
+ display_name = "My Provider"
393
+
394
+ async def chat_completion(self, request, model_id):
395
+ # Call provider API
396
+ ...
397
+
398
+ async def chat_completion_stream(self, request, model_id):
399
+ # Stream SSE chunks
400
+ ...
401
+
402
+ async def health_check(self):
403
+ return ProviderStatus.HEALTHY
404
+ ```
405
+
406
+ Register it:
407
+
408
+ ```python
409
+ from powergrid.providers.registry import registry
410
+
411
+ registry.register(MyProvider(name="my_provider", api_key="..."))
412
+ ```
413
+
414
+ ## License
415
+
416
+ MIT