Skip to content

Commit 2b6035c

Browse files
feat: add local LM Studio support, Prometheus metrics, Traefik proxy, and Grafana dashboards
Add Docker infrastructure for local development with LM Studio as LLM provider, Prometheus metrics collection with custom histograms, Traefik reverse proxy configuration, and Grafana dashboard provisioning. Update SDK session handling and deriver queue management for improved reliability.
1 parent 4e7f136 commit 2b6035c

22 files changed

Lines changed: 2794 additions & 40 deletions

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,3 +191,5 @@ metrics.jsonl
191191
AGENTS.md
192192
lancedb_data/
193193
grafana-data/
194+
.codex_honcho_runtime/
195+
.codex_honcho_setup/

CLAUDE.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,37 @@ All API routes follow the pattern: `/v1/{resource}/{id}/{action}`
8484
- Typechecking: `uv run basedpyright`
8585
- Format code: `uv run ruff format src/`
8686

87+
### Local LM Studio Setup
88+
89+
- Honcho can use LM Studio for generation through the `custom` provider path.
90+
- Keep `LLM_OPENAI_API_KEY` configured for embeddings unless embedding support is added for local models.
91+
- For Docker Compose, `LLM_OPENAI_COMPATIBLE_BASE_URL` must be `http://host.docker.internal:1234/v1`, not `http://localhost:1234/v1`.
92+
- `LLM_OPENAI_COMPATIBLE_API_KEY=lm-studio` is sufficient for local use.
93+
- Current local default model is `qwen2.5-14b-instruct`.
94+
- When overriding `DIALECTIC_LEVELS__*` via env vars, each level needs its full required settings, not just `PROVIDER` and `MODEL`. Include `THINKING_BUDGET_TOKENS` and `MAX_TOOL_ITERATIONS`, and optionally `MAX_OUTPUT_TOKENS`.
95+
- Docker should own the runtime environment completely. Do not mount the repo onto `/app` and do not mount a named volume onto `/app/.venv`, or the image-built environment can be hidden and replaced with incompatible artifacts.
96+
- If Docker services fail with missing Python modules or incompatible native extensions, rebuild the image instead of trying to repair the environment in-place:
97+
98+
```bash
99+
docker compose build --no-cache api deriver
100+
docker compose up -d --force-recreate api deriver
101+
```
102+
103+
- Verify LM Studio from the host with:
104+
105+
```bash
106+
curl -sS http://localhost:1234/v1/models
107+
```
108+
109+
- Verify LM Studio from Docker with:
110+
111+
```bash
112+
docker compose run --rm --entrypoint sh api -lc 'python - <<\"PY\"
113+
import urllib.request
114+
print(urllib.request.urlopen(\"http://host.docker.internal:1234/v1/models\", timeout=5).status)
115+
PY'
116+
```
117+
87118
### SDK Testing
88119

89120
#### TypeScript SDK

Dockerfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,13 @@ RUN addgroup --system app && adduser --system --group app && mkdir -p /tmp/uv-ca
4141
COPY --chown=app:app src/ /app/src/
4242
COPY --chown=app:app migrations/ /app/migrations/
4343
COPY --chown=app:app scripts/ /app/scripts/
44+
COPY --chown=app:app docker/entrypoint.sh /app/docker/entrypoint.sh
4445
COPY --chown=app:app alembic.ini /app/alembic.ini
4546
# Copy config files - this will copy config.toml if it exists, and config.toml.example
4647
COPY --chown=app:app config.toml* /app/
4748

49+
RUN chmod +x /app/docker/entrypoint.sh
50+
4851
# Switch to non-root user
4952
USER app
5053

docker-compose.yml.example

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,65 @@
11
services:
2+
traefik:
3+
image: traefik:v3.2
4+
command:
5+
- --api.dashboard=true
6+
- --api.insecure=true
7+
- --providers.file.filename=/etc/traefik/dynamic.yml
8+
- --providers.file.watch=true
9+
- --entrypoints.web.address=:8000
10+
- --ping=true
11+
ports:
12+
- ${HONCHO_HTTP_PORT:-8000}:8000
13+
- ${TRAEFIK_DASHBOARD_PORT:-8080}:8080
14+
volumes:
15+
- ./docker/traefik/dynamic.yml:/etc/traefik/dynamic.yml:ro
16+
networks:
17+
- honcho
18+
219
api:
320
image: honcho:latest
421
build:
522
context: .
623
dockerfile: Dockerfile
7-
entrypoint: ["sh", "docker/entrypoint.sh"]
24+
entrypoint: ["/app/docker/entrypoint.sh"]
825
depends_on:
926
database:
1027
condition: service_healthy
1128
redis:
1229
condition: service_healthy
13-
ports:
14-
- 8000:8000
15-
volumes:
16-
- .:/app
17-
- venv:/app/.venv
30+
traefik:
31+
condition: service_started
32+
expose:
33+
- 8000
1834
environment:
1935
- DB_CONNECTION_URI=postgresql+psycopg://postgres:postgres@database:5432/postgres
2036
- CACHE_URL=redis://redis:6379/0?suppress=true
2137
env_file:
2238
- path: .env
2339
required: false
40+
networks:
41+
- honcho
42+
2443
deriver:
2544
build:
2645
context: .
2746
dockerfile: Dockerfile
28-
entrypoint: ["/app/.venv/bin/python", "-m", "src.deriver"]
47+
entrypoint: ["python", "-m", "src.deriver"]
2948
depends_on:
3049
database:
3150
condition: service_healthy
3251
redis:
3352
condition: service_healthy
34-
volumes:
35-
- .:/app
36-
- venv:/app/.venv
3753
environment:
3854
- DB_CONNECTION_URI=postgresql+psycopg://postgres:postgres@database:5432/postgres
3955
- CACHE_URL=redis://redis:6379/0?suppress=true
4056
- METRICS_ENABLED=true
4157
env_file:
4258
- path: .env
4359
required: false
60+
networks:
61+
- honcho
62+
4463
database:
4564
image: pgvector/pgvector:pg15
4665
restart: always
@@ -56,23 +75,29 @@ services:
5675
volumes:
5776
- ./database/init.sql:/docker-entrypoint-initdb.d/init.sql
5877
- pgdata:/var/lib/postgresql/data/
78+
networks:
79+
- honcho
5980
healthcheck:
6081
test: ["CMD-SHELL", "pg_isready -U postgres -d postgres"]
6182
interval: 5s
6283
timeout: 5s
6384
retries: 5
85+
6486
redis:
6587
image: redis:8.2
6688
restart: always
6789
ports:
6890
- 6379:6379
6991
volumes:
7092
- ./redis-data:/data
93+
networks:
94+
- honcho
7195
healthcheck:
7296
test: ["CMD-SHELL", "redis-cli ping"]
7397
interval: 5s
7498
timeout: 5s
7599
retries: 5
100+
76101
prometheus:
77102
image: prom/prometheus:v3.2.1
78103
ports:
@@ -83,6 +108,9 @@ services:
83108
depends_on:
84109
api:
85110
condition: service_started
111+
networks:
112+
- honcho
113+
86114
grafana:
87115
image: grafana/grafana:11.4.0
88116
ports:
@@ -98,7 +126,13 @@ services:
98126
depends_on:
99127
prometheus:
100128
condition: service_started
129+
networks:
130+
- honcho
131+
132+
networks:
133+
honcho:
134+
name: honcho
135+
101136
volumes:
102137
pgdata:
103-
venv:
104138
prometheus-data:

docker/entrypoint.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
set -e
33

44
echo "Running database migrations..."
5-
/app/.venv/bin/python scripts/provision_db.py
5+
python scripts/provision_db.py
66

77
echo "Starting API server..."
8-
exec /app/.venv/bin/fastapi run --host 0.0.0.0 src/main.py
8+
exec fastapi run --host 0.0.0.0 src/main.py

docker/grafana-dashboards.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
apiVersion: 1
2+
3+
providers:
4+
- name: Honcho
5+
orgId: 1
6+
folder: Honcho
7+
type: file
8+
disableDeletion: false
9+
editable: true
10+
options:
11+
path: /etc/grafana/provisioning/dashboards/files

0 commit comments

Comments
 (0)