Commit Graph
6 Commits
Author SHA1 Message Date
Chris CoutinhoandClaude Opus 4.7 adcf13f082 refactor(providers): address PR #772 review round 3 — hermetic test, lazy logging, defensive-guard tests
- test_registry.py: stub `mistralai.client.Mistral` in
  `test_registry_mistral_wins_over_ollama`, mirroring the sibling
  picker test, so the test doesn't depend on the SDK accepting
  arbitrary keys.
- openai.py: convert remaining f-string `logger.info(...)` calls to
  lazy `%s` formatting, aligning with the pattern in mistral.py and
  the repo's logging convention.
- test_mistral.py: add four tests covering the defensive RuntimeError
  guards in `embed()` and `_embed_batch_request()` — empty
  response.data, single null embedding, batch null embedding, and
  count-mismatch.
- docs/configuration.md: add `AWS_ACCESS_KEY_ID` and
  `AWS_SECRET_ACCESS_KEY` rows to the env-var reference table; they
  were already mentioned in prose but missing from the table.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 18:28:04 +02:00
Chris CoutinhoandClaude Opus 4.7 20f1770794 refactor(providers): address PR #772 review round 2 — guard, naming, docs, tests
- _retry.py: replace `assert last_error is not None` with explicit
  `if last_error is None: raise RuntimeError(...)` so the original
  rate-limit error is preserved under `python -O`.
- openai.py: drop the `_retry_factory` alias chain; rename the bound
  decorator to `_retry_429` to match the pattern in mistral.py.
- mistral.py: comment the imports so future reviewers understand why
  `from mistralai.client import …` is the canonical path on 2.x (no
  top-level `__init__.py`; no `mistralai.models` subpackage either).
- docs/configuration.md: add `OPENAI_GENERATION_MODEL` and
  `OLLAMA_GENERATION_MODEL` rows to the env-var reference table.
- test_mistral.py: add direct unit test for the `_is_rate_limit`
  predicate (429 → True, 500 → False, missing-attr → False).
- test_registry.py: stub `mistralai.client.Mistral` in the registry
  picker test, mirroring the Ollama sibling, so the test doesn't
  depend on the SDK accepting arbitrary keys.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 18:11:57 +02:00
Chris CoutinhoandClaude Opus 4.7 e360a7782b refactor(providers): address PR #772 review — shared retry, cleaner imports, no-op close
Addresses the Claude Code review on PR #772 plus the SonarCloud S1192 finding:

- Extract `retry_on_rate_limit` into `nextcloud_mcp_server/providers/_retry.py`
  as a parametric decorator. OpenAI and Mistral now share the same backoff
  loop; future providers can reuse it without copy-paste.
- New `tests/unit/providers/test_retry.py` covers the decorator: 429 retry +
  success, non-429 immediate re-raise, MAX_RETRIES exhaustion, default
  predicate, and unrelated exception passthrough.
- Tighten Mistral SDK import to `from mistralai.client.errors import SDKError`
  (the canonical sub-path; the reviewer's `from mistralai.models import
  SDKError` does not exist in mistralai 2.4.5).
- Replace `MistralProvider.close()`'s direct `__aexit__` call with a no-op +
  comment — the Speakeasy-generated client has no public close hook and the
  underlying httpx client is closed by GC.
- Extract the duplicated "Embedding not supported" message to a module-level
  constant (SonarCloud S1192).
- Align `Settings.get_embedding_model_name()` Bedrock check with the registry
  by also considering `bedrock_generation_model`.
- Add the `mock_mistral_client` fixture to
  `test_mistral_no_embeddings_disabled` for parity with the rest of the file.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 17:46:32 +02:00
Chris CoutinhoandClaude Sonnet 4.5 3f06e2ee77 fix: resolve all type checking errors (8 errors fixed)
Fixed 8 type checker errors across the codebase:

- vector/scanner.py: Handle None scroll results with null-safe iteration
- search/{bm25_hybrid,semantic}.py: Add None checks for result.payload
- auth/{unified_verifier,webhook_routes}.py: Assert non-None auth credentials
- client/webdav.py: Add None checks before int() conversions
- providers/openai.py: Assert embedding_model is not None
- search/algorithms.py: Explicitly type doc_types set and cast values
- observability/logging_config.py: Match parent class signature (log_data)

Also fixed test_create_tag_creates_system_tag to match WebDAV implementation
(was testing OCS API endpoint, now tests correct WebDAV endpoint with
Content-Location header).

Type checker: 0 errors (down from 8), 20 warnings (ignored)
Tests: All 192 unit tests passing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-08 01:09:02 +01:00
Chris CoutinhoandClaude 92b97bda00 fix: Add rate limit retry logic to OpenAI provider
Add exponential backoff retry handling for OpenAI API rate limits
(429 errors). This is needed for GitHub Models API which has stricter
rate limits than standard OpenAI API.

- Add retry_on_rate_limit decorator with exponential backoff
- Max 5 retries with delays: 2s → 4s → 8s → 16s → 32s
- Apply to embed(), _embed_batch_request(), and generate() methods

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 17:24:48 +01:00
Chris CoutinhoandClaude 208365cd3d feat: Add OpenAI provider support for embeddings and generation
Adds OpenAI provider to the unified provider architecture (ADR-015),
supporting:
- OpenAI API (api.openai.com)
- GitHub Models API (models.github.ai/inference)
- OpenAI-compatible endpoints (Fireworks, Together, etc.)

Features:
- Embedding support with text-embedding-3-small/large models
- Text generation via chat completions API
- Automatic retry with exponential backoff for rate limits
- Provider auto-detection in registry (priority after Bedrock)

Environment variables:
- OPENAI_API_KEY: API key (required)
- OPENAI_BASE_URL: Base URL override (optional)
- OPENAI_EMBEDDING_MODEL: Embedding model (default: text-embedding-3-small)
- OPENAI_GENERATION_MODEL: Generation model (default: gpt-4o-mini)

Also adds:
- Integration tests for RAG pipeline with MCP sampling
- MCP client sampling support for integration tests
- Ground truth Q&A pairs for Nextcloud User Manual

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 00:33:32 +01:00