# Contributing to LMR Thanks for your interest. This page tells you how to set up a development environment, how to run the checks, and what a good pull request looks like. ## Development setup You need Go 1.27 or newer, Node 22 or newer, Docker, and `make`. ```bash cd backend cp .env.example .env echo GATEWAY_SECURITY_ENCRYPTION_KEY=$(openssl rand -hex 32) >> .env make dev ``` `make dev` starts a Postgres container, applies the migrations, runs the Go server on port 8080, and runs the Vite dev server on port 5173 with a proxy to the Go server. The dashboard needs an OIDC provider to sign in. Any provider works; the `.env.example` file shows the Authentik shape. Run `make help` to list every target. ## Checks Run these before you open a pull request. The CI pipeline runs the same set. ```bash cd backend go vet ./... make test # unit tests, no database needed make lint # golangci-lint, config in backend/.golangci.yml cd dashboard && npx tsc --noEmit && npm run build ``` ### Database tests The `internal/store` and `internal/catalog` packages have integration tests against a real Postgres. They skip unless `GATEWAY_TEST_DB_URL` is set. ```bash cd backend make dev-db # or any Postgres 16 export GATEWAY_TEST_DB_URL='postgres://gateway:gateway@localhost:5432/gateway?sslmode=disable' GATEWAY_DB_URL=$GATEWAY_TEST_DB_URL go run ./cmd/migrate up go test ./internal/store/ ./internal/catalog/ ``` The tests delete and recreate rows, so point them at a throwaway database. ## Project layout See the "Repo layout" section of the [README](README.md) and the [architecture notes](docs/ARCHITECTURE.md). The short version: - `backend/internal/api` holds the HTTP handlers. - `backend/internal/providers` holds the provider abstraction. Each upstream type lives in its own package and registers itself in `init()`. - `backend/internal/catalog` holds the runtime model library. - `backend/internal/store` holds hand-written SQL on `pgx`. - `backend/migrations` holds the schema. Add a new numbered pair of `up` and `down` files for every schema change. Never edit an applied one. - `backend/dashboard` holds the React UI. The Go binary embeds the build. ## Adding a provider 1. Create `backend/internal/providers//` with a `New` factory and an `init()` that calls `providers.Register`. 2. Implement the capability interfaces the upstream supports: `ChatCompleter`, `Embedder`, `ImageGenerator`, `ModelLister`. 3. Import the package in `backend/internal/providers/all`. 4. If the upstream is OpenAI-compatible, embed `openaicompat.Transport` and only add what differs. See the `openrouter` package for an example. 5. Add the type to the providers table in the README and to the dashboard's provider form. ## Pull requests - Keep one change per pull request. - Add or update tests for the code you touch. Handler tests live in `backend/internal/api` and use fake dependencies, so they do not need a database. - Run `gofmt`. The lint step fails on unformatted code. - Write commit messages as `: ` in the imperative mood, for example `catalog: store output modalities as capabilities`. Explain the reason in the body when it is not obvious from the diff. - Do not include generated files. The `internal/web/dist` folder and `bin/` are ignored on purpose. ## Reporting bugs Open an issue with the version or commit, the steps to reproduce, the expected result, and the actual result. For a request that failed at the proxy, include the row from the Logs page with the key prefix removed. Security problems go to the address in [SECURITY.md](SECURITY.md), not to the issue tracker. ## License By contributing you agree that your contributions are licensed under the GNU Affero General Public License, version 3, the same as the project.