Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
3a868dc
fix: more base model name extraction and add tests
tazlin Nov 25, 2025
4eeb5d1
feat: cache hydration and better backend variation support
tazlin Nov 26, 2025
c6d17c6
fix: imports in shared.py
tazlin Nov 26, 2025
b6c4f87
lint: fix
tazlin Nov 26, 2025
4aa1c8a
feat: add model/attribute registries; move text helpers
tazlin Feb 19, 2026
dc78084
style: fix
tazlin Feb 19, 2026
ef24671
feat: audit trail, pending queue, and diff service
tazlin Mar 2, 2026
8ef79db
docs: rebuild mkdocs module stubs
tazlin Mar 2, 2026
b07dfa2
feat: add instruct_format to text generation models, make controlnet_…
tazlin Mar 15, 2026
a73c714
refactor: settings, CORS configuration, and infrastructure cleanup
tazlin Mar 15, 2026
e86a73e
feat: fluent ModelQuery API and FieldRef DSL
tazlin Mar 15, 2026
ad17a40
ci/chore: docs tweaks, 3.12+, check query field drift on ci
tazlin Mar 15, 2026
3115cbb
lint: autofixes from 3.12+ and updated ruff
tazlin Mar 15, 2026
5403164
lint/chore: typing, enums, and missing docstrings
tazlin Mar 15, 2026
bc7456f
refactor: type hints and validations
tazlin Mar 16, 2026
e3894a6
style/lint: formatting + type hint fixes
tazlin Mar 19, 2026
f7b9bc3
lint/chore: fix lingering typing issues
tazlin Mar 19, 2026
1ddbfbf
refactor: rename query "f" classes, add typed queries
tazlin Mar 19, 2026
b871712
fix/docs: remove import causes doc to recurse
tazlin Mar 20, 2026
d06fa0e
fix: @computed_field @property ordering fix
tazlin Mar 20, 2026
7fae678
fix: ttl regression in base_cache
tazlin Mar 20, 2026
aeb1336
docs: 'concepts', tutorials, and Query API examples
tazlin Mar 20, 2026
416685a
refactor: `_unsafe` to `_or_none`
tazlin Mar 20, 2026
0de71fa
feat: v2 search/popularity endpoints and helpers
tazlin Mar 20, 2026
25256fd
fix/tests: improve search filters, typing, and add tests
tazlin Mar 20, 2026
7211c5a
lint: autoapplied formatting fixes
tazlin Mar 20, 2026
84f3b02
build: make redis optional, remove accidental mkdocs dep
tazlin Mar 20, 2026
b825c6b
build: latest deps uv.lock
tazlin Mar 20, 2026
08046c8
docs: CONTRIBUTING.md add testing & git workflow
tazlin Mar 20, 2026
656ef19
chore: remove moot comments, apply formatter
tazlin Mar 21, 2026
1b06099
refactor: model constants into model_consts package
tazlin Mar 21, 2026
06f4abd
fox" Use true()/false() helpers and expand query typing
tazlin Mar 21, 2026
fe7ddf5
fix: incorrect truthy short circut in cost_benefit_score
tazlin Mar 25, 2026
18cd6a6
feat: CSV-based text_generation serialization
tazlin Mar 25, 2026
e62f7a4
docs: remove leading . from `CONTRIBUTING.md`
tazlin Mar 26, 2026
0e85a80
fix: audit system "APPLY" for atomic ops; bug/standards fixes
tazlin Mar 26, 2026
e5018bd
style: docstring and formatting cleanup
tazlin Mar 26, 2026
e52aca2
refactor: 'audit' analysis to deletion_risk
tazlin Mar 28, 2026
35f3b04
refactor: HTTP retry/circuit breaker and refactor HTTP paths
tazlin Mar 28, 2026
c1da2b8
fix: addtl. logging/validators, tweak tests, add tenacity
tazlin Mar 29, 2026
d4b1789
refactor/fix: improve text model grouping, parsing
tazlin Apr 4, 2026
06c5dbd
docs: rebuild mkdocstrings stubs
tazlin Apr 5, 2026
0aeb9f5
fix: use default `__` env var setting delimiter
tazlin Apr 5, 2026
6db226f
docs: fix wrong aihorde.net references
tazlin Apr 7, 2026
323f244
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 7, 2026
380c2b2
chore: update uv.lock; trivy pin
tazlin Apr 7, 2026
59222df
ci: fix duplicate job entry, bump lagging tool versions
tazlin Apr 7, 2026
ae748a3
chore: uv.lock w/o local deps
tazlin Apr 7, 2026
96a1e96
fix/lint: typing fixes and field metadata
tazlin Apr 7, 2026
17ee8da
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 7, 2026
416bf61
fix: remove 204 from delete; set no model for delete content
tazlin Apr 7, 2026
406bef3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 7, 2026
ab05075
ci/lint: hadolint config; update pre-commit & Dockerfile
tazlin Apr 7, 2026
759c02d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 7, 2026
eccaa9d
chore/ci: legacy -> LEGACY
tazlin Apr 7, 2026
ba26d48
tests: remove dated test
tazlin Apr 7, 2026
663d363
ci: scope mypy hook to src/ in pre-commit
tazlin Apr 7, 2026
f927578
ci: only upload hadolint sarif if it has content
tazlin Apr 7, 2026
61964e9
Revert "ci: scope mypy hook to src/ in pre-commit"
tazlin Apr 7, 2026
f2be457
ci: skip mypy on pre-commit
tazlin Apr 7, 2026
605d653
ci: remove stale hadolint SARIF before writing
tazlin Apr 7, 2026
0a93e4f
fix: improve diff compare; guard against false-positives
tazlin Apr 12, 2026
83581d8
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 12, 2026
117eef0
lint: declarative docstring in test
tazlin Apr 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
379 changes: 356 additions & 23 deletions .env.example

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions .env.primary.example
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ HORDE_MODEL_REFERENCE_CACHE_TTL_SECONDS=60
# - 'legacy': v1 API has CRUD, v2 API is read-only (converts from legacy to v2)
# - 'v2': v2 API has CRUD, v1 API is read-only (converts from v2 to legacy)
# Default is 'v2' but set to 'legacy' during transition period
HORDE_MODEL_REFERENCE_CANONICAL_FORMAT=legacy
HORDE_MODEL_REFERENCE_CANONICAL_FORMAT=LEGACY

# ============================================================================
# GitHub Seeding (First-Time Setup)
Expand All @@ -37,19 +37,19 @@ HORDE_MODEL_REFERENCE_GITHUB_SEED_ENABLED=false
# ============================================================================

# Enable Redis for distributed caching (required for multi-worker setups)
# HORDE_MODEL_REFERENCE_REDIS_USE_REDIS=true
# HORDE_MODEL_REFERENCE_REDIS__USE_REDIS=true

# Redis connection URL
# HORDE_MODEL_REFERENCE_REDIS_URL=redis://redis:6379/0
# HORDE_MODEL_REFERENCE_REDIS__URL=redis://redis:6379/0

# Redis connection pool size
# HORDE_MODEL_REFERENCE_REDIS_POOL_SIZE=10
# HORDE_MODEL_REFERENCE_REDIS__POOL_SIZE=10

# Redis TTL (uses cache_ttl_seconds if not specified)
# HORDE_MODEL_REFERENCE_REDIS_TTL_SECONDS=60
# HORDE_MODEL_REFERENCE_REDIS__TTL_SECONDS=60

# Enable pub/sub for cache invalidation across workers
# HORDE_MODEL_REFERENCE_REDIS_USE_PUBSUB=true
# HORDE_MODEL_REFERENCE_REDIS__USE_PUBSUB=true

# ============================================================================
# Data Directory
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/docker-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ jobs:
output-file: hadolint-results.sarif
no-fail: false

- name: Ensure valid SARIF file
if: always()
run: |
if [ ! -s hadolint-results.sarif ] || ! python3 -c "import json,sys; json.load(open(sys.argv[1]))" hadolint-results.sarif 2>/dev/null; then
rm -f hadolint-results.sarif
echo '{"version":"2.1.0","$schema":"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/main/sarif-2.1/schema/sarif-schema-2.1.0.json","runs":[{"tool":{"driver":{"name":"hadolint","rules":[]}},"results":[]}]}' > hadolint-results.sarif
fi

- name: Upload hadolint SARIF results
if: always()
uses: github/codeql-action/upload-sarif@v3
Expand Down
4 changes: 1 addition & 3 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
run: uv sync --locked --all-extras --dev

- name: Run pre-commit
run: uv run pre-commit run --all-files
run: SKIP=mypy uv run pre-commit run --all-files --show-diff-on-failure

lint:
name: Lint (Ruff lint)
Expand Down Expand Up @@ -76,8 +76,6 @@ jobs:
strategy:
matrix:
python-version:
- "3.10"
- "3.11"
- "3.12"
- "3.13"
steps:
Expand Down
9 changes: 3 additions & 6 deletions .github/workflows/maintests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ jobs:
strategy:
matrix:
python-version:
- "3.10"
- "3.11"
- "3.12"
- "3.13"

Expand Down Expand Up @@ -57,9 +55,9 @@ jobs:
- "3.13"

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Install uv and set the python version
uses: astral-sh/setup-uv@v6
uses: astral-sh/setup-uv@v8.0.0
with:
python-version: ${{ matrix.python-version }}
enable-cache: true
Expand All @@ -70,6 +68,7 @@ jobs:
- name: Check that query fields have not drifted
run: uv run python scripts/verify_query_fields.py


build:
env:
AIWORKER_CACHE_HOME: ${{ github.workspace }}/.cache
Expand All @@ -79,8 +78,6 @@ jobs:
strategy:
matrix:
python-version:
- "3.10"
- "3.11"
- "3.12"
- "3.13"

Expand Down
18 changes: 6 additions & 12 deletions .github/workflows/prtests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ jobs:
strategy:
matrix:
python-version:
- "3.10"
- "3.11"
- "3.12"
- "3.13"

Expand Down Expand Up @@ -60,11 +58,9 @@ jobs:
- "3.13"

steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- uses: actions/checkout@v6
- name: Install uv and set the python version
uses: astral-sh/setup-uv@v6
uses: astral-sh/setup-uv@v8.0.0
with:
python-version: ${{ matrix.python-version }}
enable-cache: true
Expand All @@ -84,8 +80,6 @@ jobs:
strategy:
matrix:
python-version:
- "3.10"
- "3.11"
- "3.12"
- "3.13"

Expand Down Expand Up @@ -120,7 +114,7 @@ jobs:
- name: Start fastapi server
env:
HORDE_MODEL_REFERENCE_REPLICATE_MODE: PRIMARY
HORDE_MODEL_REFERENCE_CANONICAL_FORMAT: legacy
HORDE_MODEL_REFERENCE_CANONICAL_FORMAT: LEGACY
HORDE_MODEL_REFERENCE_PRIMARY_API_URL: http://localhost:19800/api
HORDE_MODEL_REFERENCE_GITHUB_SEED_ENABLED: True
run: |
Expand Down Expand Up @@ -169,8 +163,8 @@ jobs:
- name: Start fastapi server with redis backend
env:
HORDE_MODEL_REFERENCE_REPLICATE_MODE: PRIMARY
HORDE_MODEL_REFERENCE_CANONICAL_FORMAT: legacy
HORDE_MODEL_REFERENCE_REDIS_URL: redis://localhost:6379/0
HORDE_MODEL_REFERENCE_CANONICAL_FORMAT: LEGACY
HORDE_MODEL_REFERENCE_REDIS__URL: redis://localhost:6379/0
HORDE_MODEL_REFERENCE_PRIMARY_API_URL: http://localhost:19800/api
HORDE_MODEL_REFERENCE_GITHUB_SEED_ENABLED: True
run: |
Expand All @@ -192,4 +186,4 @@ jobs:
- name: Run integration tests
run: uv run pytest tests -m integration
env:
HORDE_MODEL_REFERENCE_REDIS_URL: redis://localhost:6379/0
HORDE_MODEL_REFERENCE_REDIS__URL: redis://localhost:6379/0
10 changes: 10 additions & 0 deletions .hadolint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
failure-threshold: error
format: tty
ignored:
- DL3008
override:
error:
- DL3015
trustedRegistries:
- docker.io
- ://registry.com
3 changes: 2 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ repos:
- id: ruff-check
- id: ruff-format
- repo: https://github.com/pre-commit/mirrors-mypy
rev: 'v1.18.2'
rev: 'v1.19.1'
hooks:
- id: mypy
args: [--strict, --disallow-untyped-defs, --warn-unused-configs]
Expand All @@ -35,6 +35,7 @@ repos:
- redis[hiredis]
- settings-doc
- strenum
- tenacity
- typing-extensions
- ujson
- types-aiofiles
Expand Down
54 changes: 43 additions & 11 deletions .CONTRIBUTING.md → CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ All pull requests, large or small, from anyone are welcome!
- [Environment Management](#environment-management)
- [First time setup](#first-time-setup)
- [Code Quality Tools](#code-quality-tools)
- [Testing](#testing)
- [Writing Tests](#writing-tests)
- [Git Workflow](#git-workflow)
- [Code Style and System Design](#code-style-and-system-design)

## Environment Management
Expand All @@ -18,12 +21,13 @@ All pull requests, large or small, from anyone are welcome!
### First time setup

- Install uv, as described [in the uv installation guide](https://github.com/astral-sh/uv/#installation).
- `uv python install 3.10 3.11 3.12 3.13` # We currently support these versions.
- `uv set 3.12` # Set to your desired default version.
- `uv python install 3.12` -- This project requires Python 3.12+.
- `uv python pin 3.12` -- Pin the default version.
- `uv self update`
- `uv sync --all-groups`
- The `.venv/` directory will now be created with all project, development and documentation dependencies installed.
- Be sure to point your IDE to the python binary appropriate for your OS in this directory.
- `pre-commit install` -- Set up pre-commit hooks for automatic formatting and linting on commit.

## Code Quality Tools

Expand All @@ -38,27 +42,55 @@ All pull requests, large or small, from anyone are welcome!
> Note: Many of the tools below are run by `pre-commit` automatically, but can also be run manually if desired.

- [**ruff**](https://github.com/astral-sh/ruff)
- Also provides formatting (replacing `black`) with `ruff format . --fix`
- Linting rules from a wide variety of selectable rule sets
- Provides both formatting and linting
- Format: `ruff format .`
- Lint: `ruff check . --fix`
- Combined: `ruff format . && ruff check . --fix`
- See `pyproject.toml` for the rules used.
- See all rules (but not necessarily used in the project) [available in ruff here](https://beta.ruff.rs/docs/rules/).
- Run with `ruff check .`
- Note: When using autofixing (`ruff check . --fix`), changes may be made that require running black, which can then result in needing to run `ruff check . --fix` again.
- Consider running `black . && ruff check . --fix && black . && ruff check . --fix` to avoid this.
- [**mypy**](https://mypy-lang.org/)
- Static type safety
- I recommending using the [mypy daemon](https://mypy.readthedocs.io/en/stable/mypy_daemon.html) instead of periodically running `pre-commit` (or `mypy` directly.).
- [**ty**](https://github.com/astral-sh/ty)
- Type checker: `ty check .`
- [**pyright**](https://github.com/microsoft/pyright)
- Shipped with vscode by default (via the python extension `ms-python.vscode-pylance`)
- Suggested settings:
- `"python.analysis.typeCheckingMode": "off"`
- The pylance extension has certain opinionated type checking assertions which are clash with mypy.
- The pylance extension has certain opinionated type checking assertions which clash with other type checkers.
- For example, overriding an optional field to be non-optional is considered by pylance to be a type error due to the field being invariant and the parent class potentially settings it to `None`. However, by convention in the SDK, this is a forbidden pattern.
- `"python.analysis.languageServerMode": "full"`
- `"python.testing.pytestEnabled": true`
- [**tach**](https://github.com/gauge-sh/tach)
- Enforces internal namespace dependency constraints. This helps avoid circular dependencies and helps ensure implementations are in a logical place.

## Testing

Tests require the `AI_HORDE_TESTING=True` environment variable to be set. This prevents interference from user-specific environment variables.

```bash
# Set the required env var and run tests
export AI_HORDE_TESTING=True
pytest

# Run with coverage
pytest --cov=horde_model_reference --cov-report=html

# Run a specific test file
pytest tests/test_model_reference_manager.py
```

### Writing Tests

- **Singleton reset:** Use the `restore_manager_singleton` fixture to ensure `ModelReferenceManager` is restored to its pre-test state after your test. This is critical when testing with different manager configurations.
- **Temp directories:** Use the `primary_base` fixture for tests that need an isolated temp directory for PRIMARY mode file operations.
- **Test ordering:** Tests in `test_scripts`, `test_convert_legacy_database`, and `test_model_reference_manager` run in a fixed order (defined in `conftest.py`). Other tests run in arbitrary order.

## Git Workflow

1. Fork the repository and create a feature branch from `main`
2. Make your changes
3. Run the quality checks: `ruff format . && ruff check . --fix && ty check .`
4. Run the tests: `AI_HORDE_TESTING=True pytest`
5. Commit with a clear message and open a pull request

## Code Style and System Design

- See the [python haidra style guide](docs/haidra-assets/docs/meta/python.md) for standards on code style, system design, testing, and documentation.
12 changes: 6 additions & 6 deletions DEPLOYMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ Create a `.env` file:
```bash
HORDE_MODEL_REFERENCE_REPLICATE_MODE=PRIMARY
HORDE_MODEL_REFERENCE_MAKE_FOLDERS=true
HORDE_MODEL_REFERENCE_CANONICAL_FORMAT=legacy
HORDE_MODEL_REFERENCE_CANONICAL_FORMAT=LEGACY
```

Or use `.env.primary.example` as a template:
Expand All @@ -120,13 +120,13 @@ fastapi dev src/horde_model_reference/service/app.py --port 19800
# Linux/macOS
export HORDE_MODEL_REFERENCE_REPLICATE_MODE=PRIMARY
export HORDE_MODEL_REFERENCE_MAKE_FOLDERS=true
export HORDE_MODEL_REFERENCE_CANONICAL_FORMAT=legacy
export HORDE_MODEL_REFERENCE_CANONICAL_FORMAT=LEGACY
fastapi dev src/horde_model_reference/service/app.py --port 19800

# Windows PowerShell
$env:HORDE_MODEL_REFERENCE_REPLICATE_MODE="PRIMARY"
$env:HORDE_MODEL_REFERENCE_MAKE_FOLDERS="true"
$env:HORDE_MODEL_REFERENCE_CANONICAL_FORMAT="legacy"
$env:HORDE_MODEL_REFERENCE_CANONICAL_FORMAT="LEGACY"
fastapi dev src/horde_model_reference/service/app.py --port 19800
```

Expand Down Expand Up @@ -220,8 +220,8 @@ See `.env.example` for all available options, or `.env.primary.example` for PRIM
| `HORDE_MODEL_REFERENCE_REPLICATE_MODE` | `REPLICA` | Set to `PRIMARY` for server mode |
| `HORDE_MODEL_REFERENCE_MAKE_FOLDERS` | `false` | Auto-create directories |
| `HORDE_MODEL_REFERENCE_CANONICAL_FORMAT` | `legacy` | Use legacy format (pre-v2 transition) |
| `HORDE_MODEL_REFERENCE_REDIS_USE_REDIS` | `false` | Enable Redis (multi-worker) |
| `HORDE_MODEL_REFERENCE_REDIS_URL` | `redis://localhost:6379/0` | Redis connection |
| `HORDE_MODEL_REFERENCE_REDIS__USE_REDIS` | `false` | Enable Redis (multi-worker) |
| `HORDE_MODEL_REFERENCE_REDIS__URL` | `redis://localhost:6379/0` | Redis connection |
| `HORDE_MODEL_REFERENCE_CACHE_TTL_SECONDS` | `60` | Cache lifetime |
| `HORDE_MODEL_REFERENCE_GITHUB_SEED_ENABLED` | `false` | Auto-seed on first start |

Expand Down Expand Up @@ -256,7 +256,7 @@ docker-compose -f docker-compose.redis.yml ps
**Performance issues:**

- Single-worker too slow? Switch to multi-worker with Redis
- Multi-worker not faster? Verify `HORDE_MODEL_REFERENCE_REDIS_USE_REDIS=true` is set
- Multi-worker not faster? Verify `HORDE_MODEL_REFERENCE_REDIS__USE_REDIS=true` is set
- Increase `HORDE_MODEL_REFERENCE_CACHE_TTL_SECONDS` for longer caching

---
Expand Down
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,9 @@ LABEL org.opencontainers.image.title="Horde Model Reference" \

# Install runtime dependencies
# Note: git is required for the GitHub sync service
# hadolint ignore=DL3008 -- curl is unpinned to avoid repeated CI breakage from Debian repo churn
RUN apt-get update && apt-get install -y --no-install-recommends \
curl=8.14.1-2 \
curl \
git=1:2.47.3-0+deb13u1 \
&& rm -rf /var/lib/apt/lists/*

Expand Down
Loading
Loading