diff --git a/openbot/agent-ag2/tests/test_main.py b/openbot/agent-ag2/tests/test_main.py index 93cf26a8c..992cbc6fb 100644 --- a/openbot/agent-ag2/tests/test_main.py +++ b/openbot/agent-ag2/tests/test_main.py @@ -185,12 +185,20 @@ def test_a_run_reaches_the_model_the_setup_screen_chose(monkeypatch, provider, c assert seen == [expected] +def _anthropic_key(headers): + # anthropic 2.x sends the key as a Bearer token; older SDKs send x-api-key. + bearer = headers.get("authorization", "") + if bearer.startswith("Bearer "): + return bearer.removeprefix("Bearer ") + return headers.get("x-api-key") + + def test_an_anthropic_key_uses_the_official_endpoint_when_compose_sets_a_blank_url(monkeypatch): seen = [] async def respond(transport, request): body = json.loads(request.content) - seen.append((str(request.url), request.headers.get("x-api-key"), body["model"])) + seen.append((str(request.url), _anthropic_key(request.headers), body["model"])) return httpx2.Response( 200, request=request, diff --git a/openbot/agent-langgraph-agui/tests/test_provider_boundaries.py b/openbot/agent-langgraph-agui/tests/test_provider_boundaries.py index a0a824f13..f0c27b044 100644 --- a/openbot/agent-langgraph-agui/tests/test_provider_boundaries.py +++ b/openbot/agent-langgraph-agui/tests/test_provider_boundaries.py @@ -1,5 +1,6 @@ import json import os +import re import shutil import subprocess import sys @@ -12,6 +13,7 @@ import httpx2 import pytest +from anthropic import Anthropic sys.path.insert(0, str(Path(__file__).resolve().parents[1])) @@ -337,8 +339,14 @@ async def test_anthropic_selection_reaches_anthropic_boundary_without_openai_key assert result["messages"][0].content == "anthropic proof" assert "OPENAI_API_KEY" not in os.environ assert captured[0]["url"] == "http://127.0.0.1:4311/v1/messages" - assert captured[0]["headers"]["x-api-key"] == "sk-ant-openbot-ci" - assert captured[0]["headers"]["anthropic-version"] == "2023-06-01" + # Anthropic 2.3 uses Bearer authentication; older SDKs send x-api-key. + headers = captured[0]["headers"] + assert ( + headers.get("x-api-key") == "sk-ant-openbot-ci" + or headers.get("authorization") == "Bearer sk-ant-openbot-ci" + ) + with Anthropic(api_key="sk-ant-openbot-ci") as sdk: + assert headers["anthropic-version"] == sdk.default_headers["anthropic-version"] assert captured[0]["body"]["model"] == request_model assert captured[0]["body"]["messages"] == [ {"role": "user", "content": "Say hello."} @@ -469,6 +477,11 @@ async def test_openai_keeps_a_skill_turn_beside_the_message_it_was_picked_for( ] + +def _without_api_version(path): + # google-genai 3.x calls the v1 API; older SDKs call v1beta. + return re.sub(r"^/v1(beta)?/", "/", path) + @pytest.mark.asyncio @pytest.mark.parametrize( ("provider", "model"), @@ -497,9 +510,12 @@ async def test_google_provider_reaches_google_genai_boundary( ) assert result["messages"][0].content == "google loopback proof" - assert captured == [ + assert [ + {**request, "path": _without_api_version(request["path"])} + for request in captured + ] == [ { - "path": "/v1beta/models/gemini-2.5-flash:generateContent", + "path": "/models/gemini-2.5-flash:generateContent", "x_goog_api_key_present": True, "body": { "contents": [ @@ -545,7 +561,10 @@ async def test_google_spec_model_reaches_google_request( assert result["messages"][0].content == "google loopback proof" assert len(captured) == 1 - assert captured[0]["path"] == "/v1beta/models/gemini-spec-model:generateContent" + assert ( + _without_api_version(captured[0]["path"]) + == "/models/gemini-spec-model:generateContent" + ) def _write_synthetic_chatgpt_store(path: Path): diff --git a/openbot/agent-microsoft/tests/test_main.py b/openbot/agent-microsoft/tests/test_main.py index 9063d0119..0bb769b0d 100644 --- a/openbot/agent-microsoft/tests/test_main.py +++ b/openbot/agent-microsoft/tests/test_main.py @@ -182,6 +182,14 @@ def test_a_run_reaches_the_model_the_setup_screen_chose(monkeypatch, provider, c assert seen == [expected] +def _anthropic_key(headers): + # anthropic 2.x sends the key as a Bearer token; older SDKs send x-api-key. + bearer = headers.get("authorization", "") + if bearer.startswith("Bearer "): + return bearer.removeprefix("Bearer ") + return headers.get("x-api-key") + + def test_an_anthropic_key_uses_the_official_endpoint_when_compose_sets_a_blank_url(monkeypatch): seen = [] provider_seen = [] @@ -189,7 +197,7 @@ def test_an_anthropic_key_uses_the_official_endpoint_when_compose_sets_a_blank_u async def respond(transport, request): seen.append( - (request.url.scheme, request.url.host, request.url.path, request.headers.get("x-api-key")) + (request.url.scheme, request.url.host, request.url.path, _anthropic_key(request.headers)) ) async with httpx2.ASGITransport(app=provider_app) as local_provider: return await local_provider.handle_async_request(request) diff --git a/openbot/app/tests/self-host-banner.test.tsx b/openbot/app/tests/self-host-banner.test.tsx index dff127726..b32e32d80 100644 --- a/openbot/app/tests/self-host-banner.test.tsx +++ b/openbot/app/tests/self-host-banner.test.tsx @@ -17,6 +17,7 @@ import { authKeys } from "@/lib/auth/queries"; import { deploymentKeys } from "@/lib/deployment/queries"; import { userPreferencesQueryOptions } from "@/lib/settings/message-list"; import type { UserPreferences } from "@openbot/shared/user-preferences"; +import { settleReactWork } from "./settle-react-work"; const originalFetch = globalThis.fetch; const clients: QueryClient[] = []; @@ -50,7 +51,10 @@ afterEach(() => { clients.length = 0; globalThis.fetch = originalFetch; }); -afterAll(() => GlobalRegistrator.unregister()); +afterAll(async () => { + await settleReactWork(); + GlobalRegistrator.unregister(); +}); const banner = { name: "Self-host OpenDuet" } as const; diff --git a/openbot/server/tests/channel-routes.test.ts b/openbot/server/tests/channel-routes.test.ts index 20d30b4be..e3c12515f 100644 --- a/openbot/server/tests/channel-routes.test.ts +++ b/openbot/server/tests/channel-routes.test.ts @@ -722,12 +722,11 @@ describe("the first day's date", () => { return { channel: channel(), claimed: true }; }, }); - const response = await post(store, { - agentId: "agent-1", - date: "2026-10-26", - }); + // The server drops a date more than a day from its own clock, so the date follows the clock. + const date = new Date().toISOString().slice(0, 10); + const response = await post(store, { agentId: "agent-1", date }); expect(response.status).toBe(200); - expect(calls).toEqual([[actor, "agent-1", undefined, "2026-10-26"]]); + expect(calls).toEqual([[actor, "agent-1", undefined, date]]); }); /*