feat(ai): enforce paid fallback cost guard

This commit is contained in:
ogt
2026-07-14 19:54:35 +08:00
parent ff8d917247
commit 63b241b71e
60 changed files with 6110 additions and 2190 deletions

View File

@@ -2,6 +2,7 @@ from __future__ import annotations
from types import SimpleNamespace
from typing import Any
from unittest.mock import AsyncMock, MagicMock
import httpx
import pytest
@@ -151,13 +152,23 @@ async def test_gemini_fallback_requires_explicit_flag(
"LOCAL_CODE_REVIEW_ALLOW_GEMINI_FALLBACK",
True,
)
monkeypatch.setattr(
review_module,
"resolve_ollama_order",
_fake_ollama_order,
)
service = LocalCodeReviewService()
client = _FakeClient(fail=True)
async def _get_http() -> _FakeClient:
return client
async def _gemini_result(*args: Any, **kwargs: Any) -> dict[str, Any]:
return {"review_text": "ok", "issues_count": 0, "model": "gemini", "provider": "gemini"}
monkeypatch.setattr(service, "_save_to_db", _noop_save)
monkeypatch.setattr(service, "_get_http", _get_http)
monkeypatch.setattr(service, "_review_with_gemini", _gemini_result)
result = await service.review_pr(
@@ -169,3 +180,38 @@ async def test_gemini_fallback_requires_explicit_flag(
assert result is not None
assert result["provider"] == "gemini"
assert client.posted_urls == [
"http://gcp-a:11434/api/generate",
"http://gcp-b:11434/api/generate",
"http://local-111:11434/api/generate",
]
@pytest.mark.asyncio
async def test_gemini_fallback_carries_allowlisted_receipt_correlation(
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setattr(
review_module.settings,
"LOCAL_CODE_REVIEW_ALLOW_GEMINI_FALLBACK",
True,
)
openclaw = MagicMock()
openclaw._call_gemini = AsyncMock(return_value=("ok", True, 1, 0.01))
monkeypatch.setattr("src.services.openclaw.get_openclaw", lambda: openclaw)
service = LocalCodeReviewService()
result = await service._review_with_gemini(
"pr-4",
"wooo/awoooi",
"receipt context",
"small diff",
)
assert result is not None
context = openclaw._call_gemini.await_args.kwargs["context"]
assert context == {
"trace_id": "code-review:wooo-awoooi-pr-4",
"run_id": "code-review-run:wooo-awoooi-pr-4",
"work_item_id": "code-review:wooo-awoooi-pr-4",
}