From 9e46e25825fb6b6d5c800d6f8dfb8925d6507a9a Mon Sep 17 00:00:00 2001 From: Henrik Bakke Dukefoss Date: Sat, 5 Sep 2026 15:14:09 +0200 Subject: [PATCH 1/3] feat(providers): add Standard Compute chat completions --- litellm/llms/openai_like/providers.json | 7 + .../test_standardcompute_provider.py | 158 ++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 tests/test_litellm/llms/openai_like/test_standardcompute_provider.py diff --git a/litellm/llms/openai_like/providers.json b/litellm/llms/openai_like/providers.json index a458a209ea9..92d712a133e 100644 --- a/litellm/llms/openai_like/providers.json +++ b/litellm/llms/openai_like/providers.json @@ -200,5 +200,12 @@ "temperature_max": 1.99 }, "supported_endpoints": ["/v1/chat/completions"] + }, + "standardcompute": { + "base_url": "https://api.stdcmpt.com/v1", + "api_key_env": "STANDARDCOMPUTE_API_KEY", + "param_mappings": { + "max_completion_tokens": "max_tokens" + } } } diff --git a/tests/test_litellm/llms/openai_like/test_standardcompute_provider.py b/tests/test_litellm/llms/openai_like/test_standardcompute_provider.py new file mode 100644 index 00000000000..3f4ae3e4bcc --- /dev/null +++ b/tests/test_litellm/llms/openai_like/test_standardcompute_provider.py @@ -0,0 +1,158 @@ +import json + +import httpx +import pytest +import respx + +import litellm + + +@pytest.fixture(autouse=True) +def httpx_transport(monkeypatch): + monkeypatch.setenv("DISABLE_AIOHTTP_TRANSPORT", "True") + + +@pytest.mark.asyncio +async def test_standardcompute_completion_preserves_tools_and_maps_token_limit(): + tools = [ + { + "type": "function", + "function": { + "name": "read_file", + "parameters": { + "type": "object", + "properties": {"path": {"type": "string"}}, + "required": ["path"], + }, + }, + } + ] + response = { + "id": "chatcmpl-test", + "object": "chat.completion", + "created": 1, + "model": "standardcompute", + "choices": [ + { + "index": 0, + "finish_reason": "tool_calls", + "message": { + "role": "assistant", + "content": None, + "tool_calls": [ + { + "id": "call-read", + "type": "function", + "function": { + "name": "read_file", + "arguments": '{"path":"README.md"}', + }, + } + ], + }, + } + ], + } + with respx.mock as transport: + request = transport.post("https://api.stdcmpt.com/v1/chat/completions").mock( + return_value=httpx.Response(200, json=response) + ) + result = await litellm.acompletion( + model="standardcompute/standardcompute", + api_key="test-key", + messages=[{"role": "user", "content": "Read README.md"}], + tools=tools, + max_completion_tokens=64, + ) + sent = json.loads(request.calls.last.request.content) + assert sent["model"] == "standardcompute" + assert sent["tools"] == tools + assert sent["max_tokens"] == 64 + assert "max_completion_tokens" not in sent + assert request.calls.last.request.headers["authorization"] == "Bearer test-key" + assert result.choices[0].message.tool_calls[0].function.name == "read_file" + + +@pytest.mark.asyncio +async def test_standardcompute_environment_key_and_api_base_override(monkeypatch): + monkeypatch.setenv("STANDARDCOMPUTE_API_KEY", "environment-test-key") + response = { + "id": "chatcmpl-test", + "object": "chat.completion", + "created": 1, + "model": "standardcompute", + "choices": [ + { + "index": 0, + "finish_reason": "stop", + "message": {"role": "assistant", "content": "Connected"}, + } + ], + } + with respx.mock as transport: + request = transport.post("https://example.test/v1/chat/completions").mock( + return_value=httpx.Response(200, json=response) + ) + result = await litellm.acompletion( + model="standardcompute/standardcompute", + api_base="https://example.test/v1", + messages=[{"role": "user", "content": "Connection check"}], + ) + assert ( + request.calls.last.request.headers["authorization"] + == "Bearer environment-test-key" + ) + assert result.choices[0].message.content == "Connected" + + +@pytest.mark.asyncio +async def test_standardcompute_stream_consumes_chat_completion_events(): + chunks = [ + { + "id": "chatcmpl-test", + "object": "chat.completion.chunk", + "created": 1, + "model": "standardcompute", + "choices": [ + { + "index": 0, + "delta": {"role": "assistant", "content": "Connected"}, + "finish_reason": None, + } + ], + }, + { + "id": "chatcmpl-test", + "object": "chat.completion.chunk", + "created": 1, + "model": "standardcompute", + "choices": [{"index": 0, "delta": {}, "finish_reason": "stop"}], + }, + ] + events = ( + "".join("data: " + json.dumps(chunk) + "\n\n" for chunk in chunks) + + "data: [DONE]\n\n" + ) + with respx.mock as transport: + request = transport.post("https://api.stdcmpt.com/v1/chat/completions").mock( + return_value=httpx.Response( + 200, text=events, headers={"content-type": "text/event-stream"} + ) + ) + stream = await litellm.acompletion( + model="standardcompute/standardcompute", + api_key="test-key", + messages=[{"role": "user", "content": "Connection check"}], + stream=True, + ) + received = [chunk async for chunk in stream] + assert json.loads(request.calls.last.request.content)["stream"] is True + assert ( + "".join( + chunk.choices[0].delta.content or "" for chunk in received if chunk.choices + ) + == "Connected" + ) + assert any( + chunk.choices and chunk.choices[0].finish_reason == "stop" for chunk in received + ) From 8c11b2a3138f5abff8a92b0c0291c2223245d835 Mon Sep 17 00:00:00 2001 From: Henrik Bakke Dukefoss Date: Sat, 5 Sep 2026 15:21:15 +0200 Subject: [PATCH 2/3] style(tests): align provider tests with Ruff formatting --- .../test_standardcompute_provider.py | 25 ++++--------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/tests/test_litellm/llms/openai_like/test_standardcompute_provider.py b/tests/test_litellm/llms/openai_like/test_standardcompute_provider.py index 3f4ae3e4bcc..388c020a032 100644 --- a/tests/test_litellm/llms/openai_like/test_standardcompute_provider.py +++ b/tests/test_litellm/llms/openai_like/test_standardcompute_provider.py @@ -98,10 +98,7 @@ async def test_standardcompute_environment_key_and_api_base_override(monkeypatch api_base="https://example.test/v1", messages=[{"role": "user", "content": "Connection check"}], ) - assert ( - request.calls.last.request.headers["authorization"] - == "Bearer environment-test-key" - ) + assert request.calls.last.request.headers["authorization"] == "Bearer environment-test-key" assert result.choices[0].message.content == "Connected" @@ -129,15 +126,10 @@ async def test_standardcompute_stream_consumes_chat_completion_events(): "choices": [{"index": 0, "delta": {}, "finish_reason": "stop"}], }, ] - events = ( - "".join("data: " + json.dumps(chunk) + "\n\n" for chunk in chunks) - + "data: [DONE]\n\n" - ) + events = "".join("data: " + json.dumps(chunk) + "\n\n" for chunk in chunks) + "data: [DONE]\n\n" with respx.mock as transport: request = transport.post("https://api.stdcmpt.com/v1/chat/completions").mock( - return_value=httpx.Response( - 200, text=events, headers={"content-type": "text/event-stream"} - ) + return_value=httpx.Response(200, text=events, headers={"content-type": "text/event-stream"}) ) stream = await litellm.acompletion( model="standardcompute/standardcompute", @@ -147,12 +139,5 @@ async def test_standardcompute_stream_consumes_chat_completion_events(): ) received = [chunk async for chunk in stream] assert json.loads(request.calls.last.request.content)["stream"] is True - assert ( - "".join( - chunk.choices[0].delta.content or "" for chunk in received if chunk.choices - ) - == "Connected" - ) - assert any( - chunk.choices and chunk.choices[0].finish_reason == "stop" for chunk in received - ) + assert "".join(chunk.choices[0].delta.content or "" for chunk in received if chunk.choices) == "Connected" + assert any(chunk.choices and chunk.choices[0].finish_reason == "stop" for chunk in received) From b810e92c2a14780cdd68c35116c98b470984837e Mon Sep 17 00:00:00 2001 From: Henrik Bakke Dukefoss Date: Sat, 5 Sep 2026 15:51:03 +0200 Subject: [PATCH 3/3] docs(providers): document Standard Compute endpoint support --- litellm/provider_endpoints_support_backup.json | 17 +++++++++++++++++ provider_endpoints_support.json | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/litellm/provider_endpoints_support_backup.json b/litellm/provider_endpoints_support_backup.json index 9d6b1e18f59..5395eb3861c 100644 --- a/litellm/provider_endpoints_support_backup.json +++ b/litellm/provider_endpoints_support_backup.json @@ -2099,6 +2099,23 @@ "interactions": true } }, + "standardcompute": { + "display_name": "Standard Compute (`standardcompute`)", + "url": "https://standardcompute.com/integrations", + "endpoints": { + "chat_completions": true, + "messages": false, + "responses": false, + "embeddings": false, + "image_generations": false, + "audio_transcriptions": false, + "audio_speech": false, + "moderations": false, + "batches": false, + "rerank": false, + "a2a": false + } + }, "synthetic": { "display_name": "Synthetic (`synthetic`)", "endpoints": { diff --git a/provider_endpoints_support.json b/provider_endpoints_support.json index 41ed8e1d975..becc10cdcc8 100644 --- a/provider_endpoints_support.json +++ b/provider_endpoints_support.json @@ -2349,6 +2349,23 @@ "rerank": false } }, + "standardcompute": { + "display_name": "Standard Compute (`standardcompute`)", + "url": "https://standardcompute.com/integrations", + "endpoints": { + "chat_completions": true, + "messages": false, + "responses": false, + "embeddings": false, + "image_generations": false, + "audio_transcriptions": false, + "audio_speech": false, + "moderations": false, + "batches": false, + "rerank": false, + "a2a": false + } + }, "synthetic": { "display_name": "Synthetic (`synthetic`)", "endpoints": {