- Introduced OpenRouter as a new provider option in settings and environment configuration.
- Updated README.md to include instructions for using OpenRouter.
- Enhanced the message converter to support reasoning content for OpenRouter.
- Added tests for OpenRouter provider functionality and message conversion.
- Updated dependencies to include OpenRouterProvider.
- Added request ID context to logging in FastAPI routes and NVIDIA NIM provider.
- Improved logging format to include context variables for better traceability.
- Updated message handling in Telegram and Claude handlers to log message previews.
- Enhanced error logging in NVIDIA NIM provider with request ID for easier debugging.
- Added logging for tree repository actions to track tree and node registrations.
- Added a step to fail the CI if any '# type: ignore' comments are found in Python files.
- Refactored tests to use mocking for better isolation and reliability.
- Updated type hints and casting in several files to improve type safety.
- Run ty check; fail CI if type errors
- Run ruff format --check; fail CI if not formatted
- Rename workflow to CI
Co-authored-by: Ali Khokhar <alishahryar2@gmail.com>
- License: use standard MIT yellow badge, link to opensource.org
- Python: update to 3.14 to match pyproject.toml
- uv: use official dynamic endpoint badge from astral-sh/uv
- Tests: replace static pytest 95% with GitHub Actions badge
- Ty: fix link to PyPI (pypi.org/project/ty/)
- Add .github/workflows/tests.yml for CI
Co-authored-by: Ali Khokhar <alishahryar2@gmail.com>
APIError is a ProviderError subclass, so it was caught by 'except ProviderError: raise'
and handled by provider_error_handler, bypassing the generic exception path that uses
getattr(e, 'status_code', 500). The test now uses RuntimeError with a dynamically-added
status_code attribute to actually test that fallback logic in routes.py.
Co-authored-by: Ali Khokhar <alishahryar2@gmail.com>
The drain/put approach used get_nowait() and put_nowait(). Each
put_nowait() increments _unfinished_tasks without a corresponding
task_done(), permanently inflating the counter on every invocation.
Revert to reading the internal deque directly (list(self._queue._queue))
which does not mutate any queue state. This matches the approach used
in remove_from_queue.
Co-authored-by: Ali Khokhar <alishahryar2@gmail.com>