xai-review 0.34.0__tar.gz → 0.36.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {xai_review-0.34.0/xai_review.egg-info → xai_review-0.36.0}/PKG-INFO +2 -2
- {xai_review-0.34.0 → xai_review-0.36.0}/README.md +1 -1
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/claude/client.py +1 -1
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/claude/schema.py +2 -2
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gemini/client.py +2 -1
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gemini/schema.py +2 -2
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/ollama/client.py +1 -1
- {xai_review-0.34.0/ai_review/clients/openai → xai_review-0.36.0/ai_review/clients/openai/v1}/client.py +9 -9
- {xai_review-0.34.0/ai_review/clients/openai → xai_review-0.36.0/ai_review/clients/openai/v1}/schema.py +2 -2
- xai_review-0.36.0/ai_review/clients/openai/v1/types.py +8 -0
- xai_review-0.36.0/ai_review/clients/openai/v2/client.py +46 -0
- xai_review-0.36.0/ai_review/clients/openai/v2/schema.py +47 -0
- xai_review-0.36.0/ai_review/clients/openai/v2/types.py +11 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/openrouter/client.py +1 -1
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/openrouter/schema.py +2 -2
- xai_review-0.36.0/ai_review/libs/config/llm/meta.py +7 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/config/llm/openai.py +4 -0
- xai_review-0.36.0/ai_review/resources/pricing.yaml +93 -0
- xai_review-0.36.0/ai_review/services/llm/openai/client.py +56 -0
- xai_review-0.36.0/ai_review/tests/fixtures/clients/openai.py +141 -0
- xai_review-0.36.0/ai_review/tests/suites/clients/openai/v1/test_client.py +12 -0
- {xai_review-0.34.0/ai_review/tests/suites/clients/openai → xai_review-0.36.0/ai_review/tests/suites/clients/openai/v1}/test_schema.py +1 -1
- xai_review-0.36.0/ai_review/tests/suites/clients/openai/v2/test_client.py +12 -0
- xai_review-0.36.0/ai_review/tests/suites/clients/openai/v2/test_schema.py +80 -0
- xai_review-0.36.0/ai_review/tests/suites/libs/config/llm/test_openai.py +28 -0
- xai_review-0.36.0/ai_review/tests/suites/services/llm/openai/test_client.py +39 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/llm/test_factory.py +1 -1
- xai_review-0.36.0/ai_review/tests/suites/services/vcs/__init__.py +0 -0
- xai_review-0.36.0/ai_review/tests/suites/services/vcs/bitbucket/__init__.py +0 -0
- xai_review-0.36.0/ai_review/tests/suites/services/vcs/gitea/__init__.py +0 -0
- xai_review-0.36.0/ai_review/tests/suites/services/vcs/github/__init__.py +0 -0
- xai_review-0.36.0/ai_review/tests/suites/services/vcs/gitlab/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/pyproject.toml +1 -1
- {xai_review-0.34.0 → xai_review-0.36.0/xai_review.egg-info}/PKG-INFO +2 -2
- {xai_review-0.34.0 → xai_review-0.36.0}/xai_review.egg-info/SOURCES.txt +16 -5
- xai_review-0.34.0/ai_review/clients/openai/types.py +0 -8
- xai_review-0.34.0/ai_review/libs/config/llm/meta.py +0 -7
- xai_review-0.34.0/ai_review/resources/pricing.yaml +0 -55
- xai_review-0.34.0/ai_review/services/llm/openai/client.py +0 -28
- xai_review-0.34.0/ai_review/tests/fixtures/clients/openai.py +0 -69
- xai_review-0.34.0/ai_review/tests/suites/clients/openai/test_client.py +0 -12
- xai_review-0.34.0/ai_review/tests/suites/services/llm/openai/test_client.py +0 -22
- {xai_review-0.34.0 → xai_review-0.36.0}/LICENSE +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/cli/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/cli/commands/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/cli/commands/run_context_review.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/cli/commands/run_inline_reply_review.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/cli/commands/run_inline_review.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/cli/commands/run_review.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/cli/commands/run_summary_reply_review.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/cli/commands/run_summary_review.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/cli/main.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/bitbucket/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/bitbucket/client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/bitbucket/pr/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/bitbucket/pr/client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/bitbucket/pr/schema/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/bitbucket/pr/schema/comments.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/bitbucket/pr/schema/files.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/bitbucket/pr/schema/pull_request.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/bitbucket/pr/schema/user.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/bitbucket/pr/types.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/bitbucket/tools.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/claude/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/claude/types.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gemini/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gemini/types.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitea/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitea/client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitea/pr/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitea/pr/client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitea/pr/schema/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitea/pr/schema/comments.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitea/pr/schema/files.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitea/pr/schema/pull_request.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitea/pr/schema/user.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitea/pr/types.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitea/tools.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/github/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/github/client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/github/pr/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/github/pr/client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/github/pr/schema/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/github/pr/schema/comments.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/github/pr/schema/files.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/github/pr/schema/pull_request.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/github/pr/schema/reviews.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/github/pr/schema/user.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/github/pr/types.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/github/tools.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitlab/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitlab/client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitlab/mr/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitlab/mr/client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitlab/mr/schema/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitlab/mr/schema/changes.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitlab/mr/schema/discussions.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitlab/mr/schema/notes.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitlab/mr/schema/position.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitlab/mr/schema/user.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitlab/mr/types.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/gitlab/tools.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/ollama/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/ollama/schema.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/ollama/types.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/openai/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/clients/openrouter → xai_review-0.36.0/ai_review/clients/openai/v1}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/libs → xai_review-0.36.0/ai_review/clients/openai/v2}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/libs/asynchronous → xai_review-0.36.0/ai_review/clients/openrouter}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/clients/openrouter/types.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/config.py +0 -0
- {xai_review-0.34.0/ai_review/libs/config → xai_review-0.36.0/ai_review/libs}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/libs/config/llm → xai_review-0.36.0/ai_review/libs/asynchronous}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/asynchronous/gather.py +0 -0
- {xai_review-0.34.0/ai_review/libs/config/vcs → xai_review-0.36.0/ai_review/libs/config}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/config/artifacts.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/config/base.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/config/core.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/config/http.py +0 -0
- {xai_review-0.34.0/ai_review/libs/constants → xai_review-0.36.0/ai_review/libs/config/llm}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/config/llm/base.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/config/llm/claude.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/config/llm/gemini.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/config/llm/ollama.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/config/llm/openrouter.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/config/logger.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/config/prompt.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/config/review.py +0 -0
- {xai_review-0.34.0/ai_review/libs/diff → xai_review-0.36.0/ai_review/libs/config/vcs}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/config/vcs/base.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/config/vcs/bitbucket.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/config/vcs/gitea.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/config/vcs/github.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/config/vcs/gitlab.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/config/vcs/pagination.py +0 -0
- {xai_review-0.34.0/ai_review/libs/http → xai_review-0.36.0/ai_review/libs/constants}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/constants/llm_provider.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/constants/vcs_provider.py +0 -0
- {xai_review-0.34.0/ai_review/libs/http/event_hooks → xai_review-0.36.0/ai_review/libs/diff}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/diff/models.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/diff/parser.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/diff/tools.py +0 -0
- {xai_review-0.34.0/ai_review/libs/http/transports → xai_review-0.36.0/ai_review/libs/http}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/http/client.py +0 -0
- {xai_review-0.34.0/ai_review/libs/llm → xai_review-0.36.0/ai_review/libs/http/event_hooks}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/http/event_hooks/base.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/http/event_hooks/logger.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/http/handlers.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/http/paginate.py +0 -0
- {xai_review-0.34.0/ai_review/libs/template → xai_review-0.36.0/ai_review/libs/http/transports}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/http/transports/retry.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/json.py +0 -0
- {xai_review-0.34.0/ai_review/prompts → xai_review-0.36.0/ai_review/libs/llm}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/llm/output_json_parser.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/logger.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/resources.py +0 -0
- {xai_review-0.34.0/ai_review/resources → xai_review-0.36.0/ai_review/libs/template}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/libs/template/render.py +0 -0
- {xai_review-0.34.0/ai_review/services → xai_review-0.36.0/ai_review/prompts}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/prompts/default_context.md +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/prompts/default_inline.md +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/prompts/default_inline_reply.md +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/prompts/default_summary.md +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/prompts/default_summary_reply.md +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/prompts/default_system_context.md +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/prompts/default_system_inline.md +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/prompts/default_system_inline_reply.md +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/prompts/default_system_summary.md +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/prompts/default_system_summary_reply.md +0 -0
- {xai_review-0.34.0/ai_review/services/artifacts → xai_review-0.36.0/ai_review/resources}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/services/cost → xai_review-0.36.0/ai_review/services}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/services/diff → xai_review-0.36.0/ai_review/services/artifacts}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/artifacts/schema.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/artifacts/service.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/artifacts/tools.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/artifacts/types.py +0 -0
- {xai_review-0.34.0/ai_review/services/git → xai_review-0.36.0/ai_review/services/cost}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/cost/schema.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/cost/service.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/cost/types.py +0 -0
- {xai_review-0.34.0/ai_review/services/llm → xai_review-0.36.0/ai_review/services/diff}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/diff/renderers.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/diff/schema.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/diff/service.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/diff/tools.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/diff/types.py +0 -0
- {xai_review-0.34.0/ai_review/services/llm/claude → xai_review-0.36.0/ai_review/services/git}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/git/service.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/git/types.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/hook/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/hook/constants.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/hook/service.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/hook/types.py +0 -0
- {xai_review-0.34.0/ai_review/services/llm/gemini → xai_review-0.36.0/ai_review/services/llm}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/services/llm/ollama → xai_review-0.36.0/ai_review/services/llm/claude}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/llm/claude/client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/llm/factory.py +0 -0
- {xai_review-0.34.0/ai_review/services/llm/openai → xai_review-0.36.0/ai_review/services/llm/gemini}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/llm/gemini/client.py +0 -0
- {xai_review-0.34.0/ai_review/services/llm/openrouter → xai_review-0.36.0/ai_review/services/llm/ollama}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/llm/ollama/client.py +0 -0
- {xai_review-0.34.0/ai_review/services/prompt → xai_review-0.36.0/ai_review/services/llm/openai}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/services/review → xai_review-0.36.0/ai_review/services/llm/openrouter}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/llm/openrouter/client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/llm/types.py +0 -0
- {xai_review-0.34.0/ai_review/services/review/gateway → xai_review-0.36.0/ai_review/services/prompt}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/prompt/adapter.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/prompt/schema.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/prompt/service.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/prompt/tools.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/prompt/types.py +0 -0
- {xai_review-0.34.0/ai_review/services/review/internal → xai_review-0.36.0/ai_review/services/review}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/services/review/internal/inline → xai_review-0.36.0/ai_review/services/review/gateway}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/gateway/review_comment_gateway.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/gateway/review_dry_run_comment_gateway.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/gateway/review_llm_gateway.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/gateway/types.py +0 -0
- {xai_review-0.34.0/ai_review/services/review/internal/inline_reply → xai_review-0.36.0/ai_review/services/review/internal}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/services/review/internal/policy → xai_review-0.36.0/ai_review/services/review/internal/inline}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/internal/inline/schema.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/internal/inline/service.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/internal/inline/types.py +0 -0
- {xai_review-0.34.0/ai_review/services/review/internal/summary → xai_review-0.36.0/ai_review/services/review/internal/inline_reply}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/internal/inline_reply/schema.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/internal/inline_reply/service.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/internal/inline_reply/types.py +0 -0
- {xai_review-0.34.0/ai_review/services/review/internal/summary_reply → xai_review-0.36.0/ai_review/services/review/internal/policy}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/internal/policy/service.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/internal/policy/types.py +0 -0
- {xai_review-0.34.0/ai_review/services/review/runner → xai_review-0.36.0/ai_review/services/review/internal/summary}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/internal/summary/schema.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/internal/summary/service.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/internal/summary/types.py +0 -0
- {xai_review-0.34.0/ai_review/services/vcs → xai_review-0.36.0/ai_review/services/review/internal/summary_reply}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/internal/summary_reply/schema.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/internal/summary_reply/service.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/internal/summary_reply/types.py +0 -0
- {xai_review-0.34.0/ai_review/services/vcs/bitbucket → xai_review-0.36.0/ai_review/services/review/runner}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/runner/context.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/runner/inline.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/runner/inline_reply.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/runner/summary.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/runner/summary_reply.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/runner/types.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/review/service.py +0 -0
- {xai_review-0.34.0/ai_review/services/vcs/gitea → xai_review-0.36.0/ai_review/services/vcs}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/services/vcs/github → xai_review-0.36.0/ai_review/services/vcs/bitbucket}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/vcs/bitbucket/adapter.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/vcs/bitbucket/client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/vcs/factory.py +0 -0
- {xai_review-0.34.0/ai_review/services/vcs/gitlab → xai_review-0.36.0/ai_review/services/vcs/gitea}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/vcs/gitea/adapter.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/vcs/gitea/client.py +0 -0
- {xai_review-0.34.0/ai_review/tests → xai_review-0.36.0/ai_review/services/vcs/github}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/vcs/github/adapter.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/vcs/github/client.py +0 -0
- {xai_review-0.34.0/ai_review/tests/fixtures → xai_review-0.36.0/ai_review/services/vcs/gitlab}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/vcs/gitlab/adapter.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/vcs/gitlab/client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/services/vcs/types.py +0 -0
- {xai_review-0.34.0/ai_review/tests/fixtures/clients → xai_review-0.36.0/ai_review/tests}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/tests/fixtures/libs → xai_review-0.36.0/ai_review/tests/fixtures}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/tests/fixtures/libs/llm → xai_review-0.36.0/ai_review/tests/fixtures/clients}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/clients/bitbucket.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/clients/claude.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/clients/gemini.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/clients/gitea.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/clients/github.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/clients/gitlab.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/clients/ollama.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/clients/openrouter.py +0 -0
- {xai_review-0.34.0/ai_review/tests/fixtures/services → xai_review-0.36.0/ai_review/tests/fixtures/libs}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/tests/fixtures/services/review → xai_review-0.36.0/ai_review/tests/fixtures/libs/llm}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/libs/llm/output_json_parser.py +0 -0
- {xai_review-0.34.0/ai_review/tests/fixtures/services/review/gateway → xai_review-0.36.0/ai_review/tests/fixtures/services}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/services/artifacts.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/services/cost.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/services/diff.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/services/git.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/services/hook.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/services/llm.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/services/prompt.py +0 -0
- {xai_review-0.34.0/ai_review/tests/fixtures/services/review/internal → xai_review-0.36.0/ai_review/tests/fixtures/services/review}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/services/review/base.py +0 -0
- {xai_review-0.34.0/ai_review/tests/fixtures/services/review/runner → xai_review-0.36.0/ai_review/tests/fixtures/services/review/gateway}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/services/review/gateway/review_comment_gateway.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/services/review/gateway/review_dry_run_comment_gateway.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/services/review/gateway/review_llm_gateway.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites → xai_review-0.36.0/ai_review/tests/fixtures/services/review/internal}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/services/review/internal/inline.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/services/review/internal/inline_reply.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/services/review/internal/policy.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/services/review/internal/summary.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/services/review/internal/summary_reply.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/cli → xai_review-0.36.0/ai_review/tests/fixtures/services/review/runner}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/services/review/runner/context.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/services/review/runner/inline.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/services/review/runner/inline_reply.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/services/review/runner/summary.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/services/review/runner/summary_reply.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/fixtures/services/vcs.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/clients → xai_review-0.36.0/ai_review/tests/suites}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/clients/bitbucket → xai_review-0.36.0/ai_review/tests/suites/cli}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/cli/test_main.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/clients/claude → xai_review-0.36.0/ai_review/tests/suites/clients}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/clients/gemini → xai_review-0.36.0/ai_review/tests/suites/clients/bitbucket}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/clients/bitbucket/test_client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/clients/bitbucket/test_tools.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/clients/gitea → xai_review-0.36.0/ai_review/tests/suites/clients/claude}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/clients/claude/test_client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/clients/claude/test_schema.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/clients/github → xai_review-0.36.0/ai_review/tests/suites/clients/gemini}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/clients/gemini/test_client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/clients/gemini/test_schema.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/clients/gitlab → xai_review-0.36.0/ai_review/tests/suites/clients/gitea}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/clients/gitea/test_client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/clients/gitea/test_tools.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/clients/ollama → xai_review-0.36.0/ai_review/tests/suites/clients/github}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/clients/github/test_client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/clients/github/test_tools.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/clients/openai → xai_review-0.36.0/ai_review/tests/suites/clients/gitlab}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/clients/gitlab/test_client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/clients/gitlab/test_tools.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/clients/openrouter → xai_review-0.36.0/ai_review/tests/suites/clients/ollama}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/clients/ollama/test_client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/clients/ollama/test_schema.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/libs → xai_review-0.36.0/ai_review/tests/suites/clients/openai}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/libs/asynchronous → xai_review-0.36.0/ai_review/tests/suites/clients/openai/v1}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/libs/config → xai_review-0.36.0/ai_review/tests/suites/clients/openai/v2}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/libs/diff → xai_review-0.36.0/ai_review/tests/suites/clients/openrouter}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/clients/openrouter/test_client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/clients/openrouter/test_schema.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/libs/http → xai_review-0.36.0/ai_review/tests/suites/libs}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/libs/llm → xai_review-0.36.0/ai_review/tests/suites/libs/asynchronous}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/libs/asynchronous/test_gather.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/libs/template → xai_review-0.36.0/ai_review/tests/suites/libs/config}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services → xai_review-0.36.0/ai_review/tests/suites/libs/config/llm}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/libs/config/test_prompt.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/artifacts → xai_review-0.36.0/ai_review/tests/suites/libs/diff}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/libs/diff/test_models.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/libs/diff/test_parser.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/libs/diff/test_tools.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/cost → xai_review-0.36.0/ai_review/tests/suites/libs/http}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/libs/http/test_paginate.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/diff → xai_review-0.36.0/ai_review/tests/suites/libs/llm}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/libs/llm/test_output_json_parser.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/hook → xai_review-0.36.0/ai_review/tests/suites/libs/template}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/libs/template/test_render.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/libs/test_json.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/llm → xai_review-0.36.0/ai_review/tests/suites/services}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/llm/claude → xai_review-0.36.0/ai_review/tests/suites/services/artifacts}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/artifacts/test_service.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/artifacts/test_tools.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/llm/gemini → xai_review-0.36.0/ai_review/tests/suites/services/cost}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/cost/test_schema.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/cost/test_service.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/llm/ollama → xai_review-0.36.0/ai_review/tests/suites/services/diff}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/diff/test_renderers.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/diff/test_service.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/diff/test_tools.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/llm/openai → xai_review-0.36.0/ai_review/tests/suites/services/hook}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/hook/test_service.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/llm/openrouter → xai_review-0.36.0/ai_review/tests/suites/services/llm}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/prompt → xai_review-0.36.0/ai_review/tests/suites/services/llm/claude}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/llm/claude/test_client.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/review → xai_review-0.36.0/ai_review/tests/suites/services/llm/gemini}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/llm/gemini/test_client.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/review/gateway → xai_review-0.36.0/ai_review/tests/suites/services/llm/ollama}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/llm/ollama/test_client.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/review/internal → xai_review-0.36.0/ai_review/tests/suites/services/llm/openai}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/review/internal/inline → xai_review-0.36.0/ai_review/tests/suites/services/llm/openrouter}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/llm/openrouter/test_client.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/review/internal/inline_reply → xai_review-0.36.0/ai_review/tests/suites/services/prompt}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/prompt/test_adapter.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/prompt/test_schema.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/prompt/test_service.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/prompt/test_tools.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/review/internal/policy → xai_review-0.36.0/ai_review/tests/suites/services/review}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/review/internal/summary → xai_review-0.36.0/ai_review/tests/suites/services/review/gateway}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/review/gateway/test_review_comment_gateway.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/review/gateway/test_review_dry_run_comment_gateway.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/review/gateway/test_review_llm_gateway.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/review/internal/summary_reply → xai_review-0.36.0/ai_review/tests/suites/services/review/internal}/__init__.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/review/runner → xai_review-0.36.0/ai_review/tests/suites/services/review/internal/inline}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/review/internal/inline/test_schema.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/review/internal/inline/test_service.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/vcs → xai_review-0.36.0/ai_review/tests/suites/services/review/internal/inline_reply}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/review/internal/inline_reply/test_schema.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/review/internal/inline_reply/test_service.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/vcs/bitbucket → xai_review-0.36.0/ai_review/tests/suites/services/review/internal/policy}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/review/internal/policy/test_service.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/vcs/gitea → xai_review-0.36.0/ai_review/tests/suites/services/review/internal/summary}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/review/internal/summary/test_schema.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/review/internal/summary/test_service.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/vcs/github → xai_review-0.36.0/ai_review/tests/suites/services/review/internal/summary_reply}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/review/internal/summary_reply/test_schema.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/review/internal/summary_reply/test_service.py +0 -0
- {xai_review-0.34.0/ai_review/tests/suites/services/vcs/gitlab → xai_review-0.36.0/ai_review/tests/suites/services/review/runner}/__init__.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/review/runner/test_context.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/review/runner/test_inline.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/review/runner/test_inline_reply.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/review/runner/test_summary.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/review/runner/test_summary_reply.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/review/test_service.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/vcs/bitbucket/test_adapter.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/vcs/bitbucket/test_client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/vcs/gitea/test_adapter.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/vcs/gitea/test_client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/vcs/github/test_adapter.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/vcs/github/test_client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/vcs/gitlab/test_adapter.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/vcs/gitlab/test_client.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/ai_review/tests/suites/services/vcs/test_factory.py +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/setup.cfg +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/xai_review.egg-info/dependency_links.txt +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/xai_review.egg-info/entry_points.txt +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/xai_review.egg-info/requires.txt +0 -0
- {xai_review-0.34.0 → xai_review-0.36.0}/xai_review.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xai-review
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.36.0
|
|
4
4
|
Summary: AI-powered code review tool for GitHub, GitLab, Bitbucket and Gitea — built with LLMs like OpenAI, Claude, Gemini, Ollama, and OpenRouter
|
|
5
5
|
Author-email: Nikita Filonov <nikita.filonov@example.com>
|
|
6
6
|
Maintainer-email: Nikita Filonov <nikita.filonov@example.com>
|
|
@@ -221,7 +221,7 @@ jobs:
|
|
|
221
221
|
with:
|
|
222
222
|
fetch-depth: 0
|
|
223
223
|
|
|
224
|
-
- uses: Nikita-Filonov/ai-review@v0.
|
|
224
|
+
- uses: Nikita-Filonov/ai-review@v0.36.0
|
|
225
225
|
with:
|
|
226
226
|
review-command: ${{ inputs.review-command }}
|
|
227
227
|
env:
|
|
@@ -17,7 +17,7 @@ class ClaudeHTTPClientError(HTTPClientError):
|
|
|
17
17
|
class ClaudeHTTPClient(HTTPClient, ClaudeHTTPClientProtocol):
|
|
18
18
|
@handle_http_error(client="ClaudeHTTPClient", exception=ClaudeHTTPClientError)
|
|
19
19
|
async def chat_api(self, request: ClaudeChatRequestSchema) -> Response:
|
|
20
|
-
return await self.post("/v1/messages", json=request.model_dump())
|
|
20
|
+
return await self.post("/v1/messages", json=request.model_dump(exclude_none=True))
|
|
21
21
|
|
|
22
22
|
async def chat(self, request: ClaudeChatRequestSchema) -> ClaudeChatResponseSchema:
|
|
23
23
|
response = await self.chat_api(request)
|
|
@@ -12,8 +12,8 @@ class ClaudeChatRequestSchema(BaseModel):
|
|
|
12
12
|
model: str
|
|
13
13
|
system: str | None = None
|
|
14
14
|
messages: list[ClaudeMessageSchema]
|
|
15
|
-
max_tokens: int
|
|
16
|
-
temperature: float
|
|
15
|
+
max_tokens: int | None = None
|
|
16
|
+
temperature: float | None = None
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class ClaudeContentSchema(BaseModel):
|
|
@@ -19,7 +19,8 @@ class GeminiHTTPClient(HTTPClient, GeminiHTTPClientProtocol):
|
|
|
19
19
|
async def chat_api(self, request: GeminiChatRequestSchema) -> Response:
|
|
20
20
|
meta = settings.llm.meta
|
|
21
21
|
return await self.post(
|
|
22
|
-
f"/v1beta/models/{meta.model}:generateContent",
|
|
22
|
+
f"/v1beta/models/{meta.model}:generateContent",
|
|
23
|
+
json=request.model_dump(exclude_none=True)
|
|
23
24
|
)
|
|
24
25
|
|
|
25
26
|
async def chat(self, request: GeminiChatRequestSchema) -> GeminiChatResponseSchema:
|
|
@@ -45,8 +45,8 @@ class GeminiCandidateSchema(BaseModel):
|
|
|
45
45
|
class GeminiGenerationConfigSchema(BaseModel):
|
|
46
46
|
model_config = ConfigDict(populate_by_name=True)
|
|
47
47
|
|
|
48
|
-
temperature: float
|
|
49
|
-
max_output_tokens: int = Field(alias="maxOutputTokens")
|
|
48
|
+
temperature: float | None = None
|
|
49
|
+
max_output_tokens: int | None = Field(alias="maxOutputTokens", default=None)
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
class GeminiChatRequestSchema(BaseModel):
|
|
@@ -17,7 +17,7 @@ class OllamaHTTPClientError(HTTPClientError):
|
|
|
17
17
|
class OllamaHTTPClient(HTTPClient, OllamaHTTPClientProtocol):
|
|
18
18
|
@handle_http_error(client="OllamaHTTPClient", exception=OllamaHTTPClientError)
|
|
19
19
|
async def chat_api(self, request: OllamaChatRequestSchema) -> Response:
|
|
20
|
-
return await self.post("/api/chat", json=request.model_dump())
|
|
20
|
+
return await self.post("/api/chat", json=request.model_dump(exclude_none=True))
|
|
21
21
|
|
|
22
22
|
async def chat(self, request: OllamaChatRequestSchema) -> OllamaChatResponseSchema:
|
|
23
23
|
response = await self.chat_api(request)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from httpx import Response, AsyncHTTPTransport, AsyncClient
|
|
2
2
|
|
|
3
|
-
from ai_review.clients.openai.schema import OpenAIChatRequestSchema, OpenAIChatResponseSchema
|
|
4
|
-
from ai_review.clients.openai.types import
|
|
3
|
+
from ai_review.clients.openai.v1.schema import OpenAIChatRequestSchema, OpenAIChatResponseSchema
|
|
4
|
+
from ai_review.clients.openai.v1.types import OpenAIV1HTTPClientProtocol
|
|
5
5
|
from ai_review.config import settings
|
|
6
6
|
from ai_review.libs.http.client import HTTPClient
|
|
7
7
|
from ai_review.libs.http.event_hooks.logger import LoggerEventHook
|
|
@@ -10,22 +10,22 @@ from ai_review.libs.http.transports.retry import RetryTransport
|
|
|
10
10
|
from ai_review.libs.logger import get_logger
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class
|
|
13
|
+
class OpenAIV1HTTPClientError(HTTPClientError):
|
|
14
14
|
pass
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
class
|
|
18
|
-
@handle_http_error(client='
|
|
17
|
+
class OpenAIV1HTTPClient(HTTPClient, OpenAIV1HTTPClientProtocol):
|
|
18
|
+
@handle_http_error(client='OpenAIV1HTTPClient', exception=OpenAIV1HTTPClientError)
|
|
19
19
|
async def chat_api(self, request: OpenAIChatRequestSchema) -> Response:
|
|
20
|
-
return await self.post("/chat/completions", json=request.model_dump())
|
|
20
|
+
return await self.post("/chat/completions", json=request.model_dump(exclude_none=True))
|
|
21
21
|
|
|
22
22
|
async def chat(self, request: OpenAIChatRequestSchema) -> OpenAIChatResponseSchema:
|
|
23
23
|
response = await self.chat_api(request)
|
|
24
24
|
return OpenAIChatResponseSchema.model_validate_json(response.text)
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
def
|
|
28
|
-
logger = get_logger("
|
|
27
|
+
def get_openai_v1_http_client() -> OpenAIV1HTTPClient:
|
|
28
|
+
logger = get_logger("OPENAI_V1_HTTP_CLIENT")
|
|
29
29
|
logger_event_hook = LoggerEventHook(logger=logger)
|
|
30
30
|
retry_transport = RetryTransport(logger=logger, transport=AsyncHTTPTransport())
|
|
31
31
|
|
|
@@ -40,4 +40,4 @@ def get_openai_http_client() -> OpenAIHTTPClient:
|
|
|
40
40
|
}
|
|
41
41
|
)
|
|
42
42
|
|
|
43
|
-
return
|
|
43
|
+
return OpenAIV1HTTPClient(client=client)
|
|
@@ -21,8 +21,8 @@ class OpenAIChoiceSchema(BaseModel):
|
|
|
21
21
|
class OpenAIChatRequestSchema(BaseModel):
|
|
22
22
|
model: str
|
|
23
23
|
messages: list[OpenAIMessageSchema]
|
|
24
|
-
max_tokens: int
|
|
25
|
-
temperature: float
|
|
24
|
+
max_tokens: int | None = None
|
|
25
|
+
temperature: float | None = None
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
class OpenAIChatResponseSchema(BaseModel):
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
from typing import Protocol
|
|
2
|
+
|
|
3
|
+
from ai_review.clients.openai.v1.schema import OpenAIChatRequestSchema, OpenAIChatResponseSchema
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class OpenAIV1HTTPClientProtocol(Protocol):
|
|
7
|
+
async def chat(self, request: OpenAIChatRequestSchema) -> OpenAIChatResponseSchema:
|
|
8
|
+
...
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from httpx import Response, AsyncClient, AsyncHTTPTransport
|
|
2
|
+
|
|
3
|
+
from ai_review.clients.openai.v2.schema import (
|
|
4
|
+
OpenAIResponsesRequestSchema,
|
|
5
|
+
OpenAIResponsesResponseSchema
|
|
6
|
+
)
|
|
7
|
+
from ai_review.clients.openai.v2.types import OpenAIV2HTTPClientProtocol
|
|
8
|
+
from ai_review.config import settings
|
|
9
|
+
from ai_review.libs.http.client import HTTPClient
|
|
10
|
+
from ai_review.libs.http.event_hooks.logger import LoggerEventHook
|
|
11
|
+
from ai_review.libs.http.handlers import HTTPClientError, handle_http_error
|
|
12
|
+
from ai_review.libs.http.transports.retry import RetryTransport
|
|
13
|
+
from ai_review.libs.logger import get_logger
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class OpenAIV2HTTPClientError(HTTPClientError):
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class OpenAIV2HTTPClient(HTTPClient, OpenAIV2HTTPClientProtocol):
|
|
21
|
+
@handle_http_error(client='OpenAIV2HTTPClient', exception=OpenAIV2HTTPClientError)
|
|
22
|
+
async def chat_api(self, request: OpenAIResponsesRequestSchema) -> Response:
|
|
23
|
+
return await self.post("/responses", json=request.model_dump(exclude_none=True))
|
|
24
|
+
|
|
25
|
+
async def chat(self, request: OpenAIResponsesRequestSchema) -> OpenAIResponsesResponseSchema:
|
|
26
|
+
response = await self.chat_api(request)
|
|
27
|
+
return OpenAIResponsesResponseSchema.model_validate_json(response.text)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def get_openai_v2_http_client() -> OpenAIV2HTTPClient:
|
|
31
|
+
logger = get_logger("OPENAI_V2_HTTP_CLIENT")
|
|
32
|
+
logger_event_hook = LoggerEventHook(logger=logger)
|
|
33
|
+
retry_transport = RetryTransport(logger=logger, transport=AsyncHTTPTransport())
|
|
34
|
+
|
|
35
|
+
client = AsyncClient(
|
|
36
|
+
timeout=settings.llm.http_client.timeout,
|
|
37
|
+
headers={"Authorization": f"Bearer {settings.llm.http_client.api_token_value}"},
|
|
38
|
+
base_url=settings.llm.http_client.api_url_value,
|
|
39
|
+
transport=retry_transport,
|
|
40
|
+
event_hooks={
|
|
41
|
+
'request': [logger_event_hook.request],
|
|
42
|
+
'response': [logger_event_hook.response]
|
|
43
|
+
}
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
return OpenAIV2HTTPClient(client=client)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from pydantic import BaseModel
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class OpenAIResponseUsageSchema(BaseModel):
|
|
5
|
+
total_tokens: int
|
|
6
|
+
input_tokens: int
|
|
7
|
+
output_tokens: int
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class OpenAIInputMessageSchema(BaseModel):
|
|
11
|
+
role: str
|
|
12
|
+
content: str
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class OpenAIResponseContentSchema(BaseModel):
|
|
16
|
+
type: str
|
|
17
|
+
text: str | None = None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class OpenAIResponseOutputSchema(BaseModel):
|
|
21
|
+
type: str
|
|
22
|
+
role: str | None = None
|
|
23
|
+
content: list[OpenAIResponseContentSchema] | None = None
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class OpenAIResponsesRequestSchema(BaseModel):
|
|
27
|
+
model: str
|
|
28
|
+
input: list[OpenAIInputMessageSchema]
|
|
29
|
+
temperature: float | None = None
|
|
30
|
+
instructions: str | None = None
|
|
31
|
+
max_output_tokens: int | None = None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class OpenAIResponsesResponseSchema(BaseModel):
|
|
35
|
+
usage: OpenAIResponseUsageSchema
|
|
36
|
+
output: list[OpenAIResponseOutputSchema]
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def first_text(self) -> str:
|
|
40
|
+
results: list[str] = []
|
|
41
|
+
for block in self.output:
|
|
42
|
+
if block.type == "message" and block.content:
|
|
43
|
+
for content in block.content:
|
|
44
|
+
if content.type == "output_text" and content.text:
|
|
45
|
+
results.append(content.text)
|
|
46
|
+
|
|
47
|
+
return "".join(results).strip()
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from typing import Protocol
|
|
2
|
+
|
|
3
|
+
from ai_review.clients.openai.v2.schema import (
|
|
4
|
+
OpenAIResponsesRequestSchema,
|
|
5
|
+
OpenAIResponsesResponseSchema
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class OpenAIV2HTTPClientProtocol(Protocol):
|
|
10
|
+
async def chat(self, request: OpenAIResponsesRequestSchema) -> OpenAIResponsesResponseSchema:
|
|
11
|
+
...
|
|
@@ -17,7 +17,7 @@ class OpenRouterHTTPClientError(HTTPClientError):
|
|
|
17
17
|
class OpenRouterHTTPClient(HTTPClient, OpenRouterHTTPClientProtocol):
|
|
18
18
|
@handle_http_error(client="OpenRouterHTTPClient", exception=OpenRouterHTTPClientError)
|
|
19
19
|
async def chat_api(self, request: OpenRouterChatRequestSchema) -> Response:
|
|
20
|
-
return await self.post("/chat/completions", json=request.model_dump())
|
|
20
|
+
return await self.post("/chat/completions", json=request.model_dump(exclude_none=True))
|
|
21
21
|
|
|
22
22
|
async def chat(self, request: OpenRouterChatRequestSchema) -> OpenRouterChatResponseSchema:
|
|
23
23
|
response = await self.chat_api(request)
|
|
@@ -21,8 +21,8 @@ class OpenRouterChoiceSchema(BaseModel):
|
|
|
21
21
|
class OpenRouterChatRequestSchema(BaseModel):
|
|
22
22
|
model: str
|
|
23
23
|
messages: list[OpenRouterMessageSchema]
|
|
24
|
-
max_tokens: int
|
|
25
|
-
temperature: float
|
|
24
|
+
max_tokens: int | None = None
|
|
25
|
+
temperature: float | None = None
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
class OpenRouterChatResponseSchema(BaseModel):
|
|
@@ -5,6 +5,10 @@ from ai_review.libs.config.llm.meta import LLMMetaConfig
|
|
|
5
5
|
class OpenAIMetaConfig(LLMMetaConfig):
|
|
6
6
|
model: str = "gpt-4o-mini"
|
|
7
7
|
|
|
8
|
+
@property
|
|
9
|
+
def is_v2_model(self) -> bool:
|
|
10
|
+
return any(self.model.startswith(model) for model in ("gpt-5", "gpt-4.1"))
|
|
11
|
+
|
|
8
12
|
|
|
9
13
|
class OpenAIHTTPClientConfig(HTTPClientWithTokenConfig):
|
|
10
14
|
pass
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# ===============================
|
|
2
|
+
# 📊 Pricing per 1 token (USD)
|
|
3
|
+
# ===============================
|
|
4
|
+
# NOTE:
|
|
5
|
+
# - Prices are per 1 token and can change over time.
|
|
6
|
+
# - For the latest OpenAI and Anthropic pricing, see:
|
|
7
|
+
# - https://openai.com/api/pricing
|
|
8
|
+
# - https://www.anthropic.com/pricing
|
|
9
|
+
# - For OpenRouter models, prices vary by provider: https://openrouter.ai
|
|
10
|
+
|
|
11
|
+
# --- OpenAI ---
|
|
12
|
+
gpt-4o-mini:
|
|
13
|
+
input: 0.15e-6
|
|
14
|
+
output: 0.60e-6
|
|
15
|
+
|
|
16
|
+
gpt-4o:
|
|
17
|
+
input: 5.00e-6
|
|
18
|
+
output: 15.00e-6
|
|
19
|
+
|
|
20
|
+
gpt-4.1-mini:
|
|
21
|
+
input: 0.15e-6
|
|
22
|
+
output: 0.60e-6
|
|
23
|
+
|
|
24
|
+
gpt-4.1:
|
|
25
|
+
input: 5.00e-6
|
|
26
|
+
output: 15.00e-6
|
|
27
|
+
|
|
28
|
+
gpt-5:
|
|
29
|
+
input: 10.00e-6
|
|
30
|
+
output: 30.00e-6
|
|
31
|
+
|
|
32
|
+
gpt-3.5-turbo:
|
|
33
|
+
input: 0.50e-6
|
|
34
|
+
output: 1.50e-6
|
|
35
|
+
|
|
36
|
+
# --- Google Gemini ---
|
|
37
|
+
gemini-2.5-flash-lite:
|
|
38
|
+
input: 0.10e-6
|
|
39
|
+
output: 0.40e-6
|
|
40
|
+
|
|
41
|
+
gemini-2.0-flash-lite:
|
|
42
|
+
input: 0.019e-6
|
|
43
|
+
output: 0.10e-6
|
|
44
|
+
|
|
45
|
+
gemini-2.0-pro:
|
|
46
|
+
input: 0.125e-6
|
|
47
|
+
output: 0.375e-6
|
|
48
|
+
|
|
49
|
+
gemini-2.5-pro:
|
|
50
|
+
input: 1.25e-6
|
|
51
|
+
output: 10.00e-6
|
|
52
|
+
|
|
53
|
+
gemini-2.5-pro-long-context:
|
|
54
|
+
input: 2.50e-6
|
|
55
|
+
output: 15.00e-6
|
|
56
|
+
|
|
57
|
+
# --- Anthropic Claude ---
|
|
58
|
+
claude-3.5-sonnet:
|
|
59
|
+
input: 3.00e-6
|
|
60
|
+
output: 15.00e-6
|
|
61
|
+
|
|
62
|
+
claude-3-opus:
|
|
63
|
+
input: 15.00e-6
|
|
64
|
+
output: 75.00e-6
|
|
65
|
+
|
|
66
|
+
claude-3-sonnet:
|
|
67
|
+
input: 3.00e-6
|
|
68
|
+
output: 15.00e-6
|
|
69
|
+
|
|
70
|
+
claude-3-haiku:
|
|
71
|
+
input: 0.25e-6
|
|
72
|
+
output: 1.25e-6
|
|
73
|
+
|
|
74
|
+
# --- OpenRouter ---
|
|
75
|
+
o3-mini:
|
|
76
|
+
input: 1.10e-6
|
|
77
|
+
output: 4.40e-6
|
|
78
|
+
|
|
79
|
+
openai/chatgpt-4o-latest:
|
|
80
|
+
input: 5.00e-6
|
|
81
|
+
output: 15.00e-6
|
|
82
|
+
|
|
83
|
+
mistralai/mixtral-8x7b:
|
|
84
|
+
input: 0.24e-6
|
|
85
|
+
output: 0.48e-6
|
|
86
|
+
|
|
87
|
+
meta-llama/llama-3-8b-instruct:
|
|
88
|
+
input: 0.20e-6
|
|
89
|
+
output: 0.40e-6
|
|
90
|
+
|
|
91
|
+
meta-llama/llama-3-70b-instruct:
|
|
92
|
+
input: 0.80e-6
|
|
93
|
+
output: 1.60e-6
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from ai_review.clients.openai.v1.client import get_openai_v1_http_client
|
|
2
|
+
from ai_review.clients.openai.v1.schema import OpenAIChatRequestSchema, OpenAIMessageSchema
|
|
3
|
+
from ai_review.clients.openai.v2.client import get_openai_v2_http_client
|
|
4
|
+
from ai_review.clients.openai.v2.schema import OpenAIInputMessageSchema, OpenAIResponsesRequestSchema
|
|
5
|
+
from ai_review.config import settings
|
|
6
|
+
from ai_review.services.llm.types import LLMClientProtocol, ChatResultSchema
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class OpenAILLMClient(LLMClientProtocol):
|
|
10
|
+
def __init__(self):
|
|
11
|
+
self.meta = settings.llm.meta
|
|
12
|
+
|
|
13
|
+
self.http_client_v1 = get_openai_v1_http_client()
|
|
14
|
+
self.http_client_v2 = get_openai_v2_http_client()
|
|
15
|
+
|
|
16
|
+
async def chat_v1(self, prompt: str, prompt_system: str) -> ChatResultSchema:
|
|
17
|
+
request = OpenAIChatRequestSchema(
|
|
18
|
+
model=self.meta.model,
|
|
19
|
+
messages=[
|
|
20
|
+
OpenAIMessageSchema(role="system", content=prompt_system),
|
|
21
|
+
OpenAIMessageSchema(role="user", content=prompt),
|
|
22
|
+
],
|
|
23
|
+
max_tokens=self.meta.max_tokens,
|
|
24
|
+
temperature=self.meta.temperature,
|
|
25
|
+
)
|
|
26
|
+
response = await self.http_client_v1.chat(request)
|
|
27
|
+
return ChatResultSchema(
|
|
28
|
+
text=response.first_text,
|
|
29
|
+
total_tokens=response.usage.total_tokens,
|
|
30
|
+
prompt_tokens=response.usage.prompt_tokens,
|
|
31
|
+
completion_tokens=response.usage.completion_tokens,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
async def chat_v2(self, prompt: str, prompt_system: str) -> ChatResultSchema:
|
|
35
|
+
request = OpenAIResponsesRequestSchema(
|
|
36
|
+
model=self.meta.model,
|
|
37
|
+
input=[
|
|
38
|
+
OpenAIInputMessageSchema(role="system", content=prompt_system),
|
|
39
|
+
OpenAIInputMessageSchema(role="user", content=prompt),
|
|
40
|
+
],
|
|
41
|
+
temperature=self.meta.temperature,
|
|
42
|
+
max_output_tokens=self.meta.max_tokens,
|
|
43
|
+
)
|
|
44
|
+
response = await self.http_client_v2.chat(request)
|
|
45
|
+
return ChatResultSchema(
|
|
46
|
+
text=response.first_text,
|
|
47
|
+
total_tokens=response.usage.total_tokens,
|
|
48
|
+
prompt_tokens=response.usage.input_tokens,
|
|
49
|
+
completion_tokens=response.usage.output_tokens,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
async def chat(self, prompt: str, prompt_system: str) -> ChatResultSchema:
|
|
53
|
+
if self.meta.is_v2_model:
|
|
54
|
+
return await self.chat_v2(prompt, prompt_system)
|
|
55
|
+
|
|
56
|
+
return await self.chat_v1(prompt, prompt_system)
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from pydantic import HttpUrl, SecretStr
|
|
5
|
+
|
|
6
|
+
from ai_review.clients.openai.v1.schema import (
|
|
7
|
+
OpenAIUsageSchema,
|
|
8
|
+
OpenAIChoiceSchema,
|
|
9
|
+
OpenAIMessageSchema,
|
|
10
|
+
OpenAIChatRequestSchema,
|
|
11
|
+
OpenAIChatResponseSchema,
|
|
12
|
+
)
|
|
13
|
+
from ai_review.clients.openai.v1.types import OpenAIV1HTTPClientProtocol
|
|
14
|
+
from ai_review.clients.openai.v2.schema import (
|
|
15
|
+
OpenAIResponsesRequestSchema,
|
|
16
|
+
OpenAIResponsesResponseSchema,
|
|
17
|
+
OpenAIResponseUsageSchema,
|
|
18
|
+
OpenAIResponseOutputSchema,
|
|
19
|
+
OpenAIResponseContentSchema,
|
|
20
|
+
)
|
|
21
|
+
from ai_review.clients.openai.v2.types import OpenAIV2HTTPClientProtocol
|
|
22
|
+
from ai_review.config import settings
|
|
23
|
+
from ai_review.libs.config.llm.base import OpenAILLMConfig
|
|
24
|
+
from ai_review.libs.config.llm.openai import OpenAIMetaConfig, OpenAIHTTPClientConfig
|
|
25
|
+
from ai_review.libs.constants.llm_provider import LLMProvider
|
|
26
|
+
from ai_review.services.llm.openai.client import OpenAILLMClient
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class FakeOpenAIV1HTTPClient(OpenAIV1HTTPClientProtocol):
|
|
30
|
+
def __init__(self, responses: dict[str, Any] | None = None) -> None:
|
|
31
|
+
self.calls: list[tuple[str, dict]] = []
|
|
32
|
+
self.responses = responses or {}
|
|
33
|
+
|
|
34
|
+
async def chat(self, request: OpenAIChatRequestSchema) -> OpenAIChatResponseSchema:
|
|
35
|
+
self.calls.append(("chat", {"request": request}))
|
|
36
|
+
return self.responses.get(
|
|
37
|
+
"chat",
|
|
38
|
+
OpenAIChatResponseSchema(
|
|
39
|
+
usage=OpenAIUsageSchema(total_tokens=12, prompt_tokens=5, completion_tokens=7),
|
|
40
|
+
choices=[
|
|
41
|
+
OpenAIChoiceSchema(
|
|
42
|
+
message=OpenAIMessageSchema(
|
|
43
|
+
role="assistant",
|
|
44
|
+
content="FAKE_OPENAI_V1_RESPONSE"
|
|
45
|
+
)
|
|
46
|
+
)
|
|
47
|
+
],
|
|
48
|
+
),
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class FakeOpenAIV2HTTPClient(OpenAIV2HTTPClientProtocol):
|
|
53
|
+
def __init__(self, responses: dict[str, Any] | None = None) -> None:
|
|
54
|
+
self.calls: list[tuple[str, dict]] = []
|
|
55
|
+
self.responses = responses or {}
|
|
56
|
+
|
|
57
|
+
async def chat(self, request: OpenAIResponsesRequestSchema) -> OpenAIResponsesResponseSchema:
|
|
58
|
+
self.calls.append(("chat", {"request": request}))
|
|
59
|
+
return self.responses.get(
|
|
60
|
+
"chat",
|
|
61
|
+
OpenAIResponsesResponseSchema(
|
|
62
|
+
usage=OpenAIResponseUsageSchema(
|
|
63
|
+
total_tokens=20, input_tokens=10, output_tokens=10
|
|
64
|
+
),
|
|
65
|
+
output=[
|
|
66
|
+
OpenAIResponseOutputSchema(
|
|
67
|
+
type="message",
|
|
68
|
+
role="assistant",
|
|
69
|
+
content=[
|
|
70
|
+
OpenAIResponseContentSchema(
|
|
71
|
+
type="output_text",
|
|
72
|
+
text="FAKE_OPENAI_V2_RESPONSE"
|
|
73
|
+
)
|
|
74
|
+
],
|
|
75
|
+
)
|
|
76
|
+
],
|
|
77
|
+
),
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@pytest.fixture
|
|
82
|
+
def fake_openai_v1_http_client() -> FakeOpenAIV1HTTPClient:
|
|
83
|
+
return FakeOpenAIV1HTTPClient()
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@pytest.fixture
|
|
87
|
+
def fake_openai_v2_http_client() -> FakeOpenAIV2HTTPClient:
|
|
88
|
+
return FakeOpenAIV2HTTPClient()
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@pytest.fixture
|
|
92
|
+
def openai_llm_client(
|
|
93
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
94
|
+
fake_openai_v1_http_client: FakeOpenAIV1HTTPClient,
|
|
95
|
+
fake_openai_v2_http_client: FakeOpenAIV2HTTPClient,
|
|
96
|
+
) -> OpenAILLMClient:
|
|
97
|
+
monkeypatch.setattr(
|
|
98
|
+
"ai_review.services.llm.openai.client.get_openai_v1_http_client",
|
|
99
|
+
lambda: fake_openai_v1_http_client,
|
|
100
|
+
)
|
|
101
|
+
monkeypatch.setattr(
|
|
102
|
+
"ai_review.services.llm.openai.client.get_openai_v2_http_client",
|
|
103
|
+
lambda: fake_openai_v2_http_client,
|
|
104
|
+
)
|
|
105
|
+
return OpenAILLMClient()
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@pytest.fixture
|
|
109
|
+
def openai_v1_http_client_config(monkeypatch: pytest.MonkeyPatch):
|
|
110
|
+
fake_config = OpenAILLMConfig(
|
|
111
|
+
meta=OpenAIMetaConfig(
|
|
112
|
+
model="gpt-4o-mini",
|
|
113
|
+
max_tokens=1200,
|
|
114
|
+
temperature=0.3
|
|
115
|
+
),
|
|
116
|
+
provider=LLMProvider.OPENAI,
|
|
117
|
+
http_client=OpenAIHTTPClientConfig(
|
|
118
|
+
timeout=10,
|
|
119
|
+
api_url=HttpUrl("https://api.openai.com/v1"),
|
|
120
|
+
api_token=SecretStr("fake-token"),
|
|
121
|
+
),
|
|
122
|
+
)
|
|
123
|
+
monkeypatch.setattr(settings, "llm", fake_config)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@pytest.fixture
|
|
127
|
+
def openai_v2_http_client_config(monkeypatch: pytest.MonkeyPatch):
|
|
128
|
+
fake_config = OpenAILLMConfig(
|
|
129
|
+
meta=OpenAIMetaConfig(
|
|
130
|
+
model="gpt-5",
|
|
131
|
+
max_tokens=2000,
|
|
132
|
+
temperature=0.2
|
|
133
|
+
),
|
|
134
|
+
provider=LLMProvider.OPENAI,
|
|
135
|
+
http_client=OpenAIHTTPClientConfig(
|
|
136
|
+
timeout=10,
|
|
137
|
+
api_url=HttpUrl("https://api.openai.com/v1"),
|
|
138
|
+
api_token=SecretStr("fake-token"),
|
|
139
|
+
),
|
|
140
|
+
)
|
|
141
|
+
monkeypatch.setattr(settings, "llm", fake_config)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from httpx import AsyncClient
|
|
3
|
+
|
|
4
|
+
from ai_review.clients.openai.v1.client import get_openai_v1_http_client, OpenAIV1HTTPClient
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@pytest.mark.usefixtures('openai_v1_http_client_config')
|
|
8
|
+
def test_get_openai_v1_http_client_builds_ok():
|
|
9
|
+
openai_http_client = get_openai_v1_http_client()
|
|
10
|
+
|
|
11
|
+
assert isinstance(openai_http_client, OpenAIV1HTTPClient)
|
|
12
|
+
assert isinstance(openai_http_client.client, AsyncClient)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from httpx import AsyncClient
|
|
3
|
+
|
|
4
|
+
from ai_review.clients.openai.v2.client import get_openai_v2_http_client, OpenAIV2HTTPClient
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@pytest.mark.usefixtures('openai_v2_http_client_config')
|
|
8
|
+
def test_get_openai_v2_http_client_builds_ok():
|
|
9
|
+
openai_http_client = get_openai_v2_http_client()
|
|
10
|
+
|
|
11
|
+
assert isinstance(openai_http_client, OpenAIV2HTTPClient)
|
|
12
|
+
assert isinstance(openai_http_client.client, AsyncClient)
|