Support selectable Aider providers
Some checks failed
CI / test (push) Has been cancelled

This commit is contained in:
2026-08-28 15:44:24 +02:00
parent 2d9e44f789
commit c8740a0374
4 changed files with 52 additions and 5 deletions

View File

@@ -111,15 +111,47 @@ die empfohlene Betriebsart.
## Modelle ## Modelle
Default: Das Modell wird ausschliesslich ueber `AGENT_MODEL` gewaehlt. Devstral ist der
Default und ein Coding-Agent, nicht das Chat-Modell der Laravel-Anwendung:
```dotenv ```dotenv
AGENT_MODEL=mistral/devstral-latest AGENT_MODEL=mistral/devstral-latest
MISTRAL_API_KEY=...
``` ```
Das Chat-Modell und Coding-Modell sind bewusst getrennt. Fuer Coding-Agenten sollte ein Codestral verwendet denselben Mistral-Zugang:
```dotenv
AGENT_MODEL=mistral/codestral-latest
MISTRAL_API_KEY=...
```
Qwen 3.5 27B ueber OpenRouter:
```dotenv
AGENT_MODEL=openrouter/qwen/qwen3.5-27b
OPENROUTER_API_KEY=...
```
Oder mit einem lokalen Ollama auf dem Docker-Host:
```dotenv
AGENT_MODEL=ollama_chat/qwen3.5:27b
OLLAMA_API_BASE=http://host.docker.internal:11434
```
Nach einer Aenderung wird der Worker neu erstellt, damit Compose die neue Umgebung
uebernimmt:
```bash
docker compose up -d --force-recreate automation
docker compose exec -T automation lai-agent check
```
Aider waehlt das passende Edit-Format anhand des Modells. Das Chat-Modell und
Coding-Modell sind bewusst getrennt. Fuer Coding-Agenten sollte ein
agentisch/coding-optimiertes Modell verwendet werden. Ein Wechsel zu OpenHands oder agentisch/coding-optimiertes Modell verwendet werden. Ein Wechsel zu OpenHands oder
einem anderen Backend erfordert nur einen neuen Adapter neben `AiderAgent`. einem anderen Backend erfordert einen neuen Adapter neben `AiderAgent`.
## Tests ## Tests

View File

@@ -20,6 +20,10 @@ services:
AGENT_COMMAND: ${AGENT_COMMAND:-aider} AGENT_COMMAND: ${AGENT_COMMAND:-aider}
AGENT_MODEL: ${AGENT_MODEL:-mistral/devstral-latest} AGENT_MODEL: ${AGENT_MODEL:-mistral/devstral-latest}
MISTRAL_API_KEY: ${MISTRAL_API_KEY:-} MISTRAL_API_KEY: ${MISTRAL_API_KEY:-}
OPENAI_API_KEY: ${OPENAI_API_KEY:-}
OPENAI_API_BASE: ${OPENAI_API_BASE:-}
OPENROUTER_API_KEY: ${OPENROUTER_API_KEY:-}
OLLAMA_API_BASE: ${OLLAMA_API_BASE:-}
POLL_SECONDS: ${POLL_SECONDS:-60} POLL_SECONDS: ${POLL_SECONDS:-60}
MAX_AGENT_ATTEMPTS: ${MAX_AGENT_ATTEMPTS:-2} MAX_AGENT_ATTEMPTS: ${MAX_AGENT_ATTEMPTS:-2}
STALE_CLAIM_MINUTES: ${STALE_CLAIM_MINUTES:-90} STALE_CLAIM_MINUTES: ${STALE_CLAIM_MINUTES:-90}

View File

@@ -36,7 +36,14 @@ class AiderAgent:
"HOME": coder.pw_dir, "HOME": coder.pw_dir,
"PATH": os.environ.get("PATH", "/usr/local/bin:/usr/bin:/bin"), "PATH": os.environ.get("PATH", "/usr/local/bin:/usr/bin:/bin"),
} }
for name in ("MISTRAL_API_KEY", "OPENAI_API_KEY", "ANTHROPIC_API_KEY"): for name in (
"MISTRAL_API_KEY",
"OPENAI_API_KEY",
"OPENAI_API_BASE",
"ANTHROPIC_API_KEY",
"OPENROUTER_API_KEY",
"OLLAMA_API_BASE",
):
if os.getenv(name): if os.getenv(name):
environment[name] = os.environ[name] environment[name] = os.environ[name]

View File

@@ -48,6 +48,8 @@ def test_aider_environment_does_not_include_database_credentials(tmp_path, monke
workspace = tmp_path / "repo" workspace = tmp_path / "repo"
(workspace / ".git").mkdir(parents=True) (workspace / ".git").mkdir(parents=True)
monkeypatch.setenv("TEST_DB_PASSWORD", "must-not-reach-aider") monkeypatch.setenv("TEST_DB_PASSWORD", "must-not-reach-aider")
monkeypatch.setenv("OPENROUTER_API_KEY", "qwen-provider-key")
monkeypatch.setenv("OLLAMA_API_BASE", "http://host.docker.internal:11434")
captured = {} captured = {}
def run(command, **kwargs): def run(command, **kwargs):
@@ -64,3 +66,5 @@ def test_aider_environment_does_not_include_database_credentials(tmp_path, monke
assert "TEST_DB_PASSWORD" not in captured assert "TEST_DB_PASSWORD" not in captured
assert "DB_PASSWORD" not in captured assert "DB_PASSWORD" not in captured
assert captured["OPENROUTER_API_KEY"] == "qwen-provider-key"
assert captured["OLLAMA_API_BASE"] == "http://host.docker.internal:11434"