Skip to content

Commit e50a159

Browse files
authored
feat(proxy): serve /chat/completions as an alias of /v1/chat/completions (#131)
Exposes llama-server extension /chat/completions. Fixes pi-llama-cpp.
1 parent a02944a commit e50a159

2 files changed

Lines changed: 21 additions & 1 deletion

File tree

src/forge/proxy/server.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,10 @@ async def _handle_connection(
190190
await self._handle_health(writer)
191191
elif method == "GET" and path == "/v1/models":
192192
await self._handle_models(writer)
193-
elif method == "POST" and path == "/v1/chat/completions":
193+
elif method == "POST" and path in ("/v1/chat/completions", "/chat/completions"):
194+
# llama.cpp serves the OpenAI chat endpoint on both spellings;
195+
# llama.cpp-native clients (pi-llama-cpp) POST the unprefixed
196+
# one, so a transparent front must accept it too.
194197
await self._handle_completions(
195198
writer, body_bytes, protocol="openai", headers=headers,
196199
)

tests/unit/test_proxy_server.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,23 @@ async def test_streaming_success_still_sse_200(self):
644644
await srv.stop()
645645

646646

647+
class TestChatCompletionsAlias:
648+
"""POST /chat/completions (no /v1 prefix) is served like the canonical
649+
route — llama.cpp serves both spellings and llama.cpp-native clients
650+
(pi-llama-cpp) POST the unprefixed one."""
651+
652+
@pytest.mark.asyncio
653+
async def test_unprefixed_chat_completions_routes(self, server_factory):
654+
srv, port = await server_factory(TextResponse(content="Hello!"))
655+
body = {"messages": [{"role": "user", "content": "hi"}]}
656+
status, response_body = await _http_request(
657+
port, "POST", "/chat/completions", body,
658+
)
659+
assert status == 200
660+
data = json.loads(response_body)
661+
assert data["choices"][0]["message"]["content"] == "Hello!"
662+
663+
647664
class TestCorsAllowsApiKey:
648665
@pytest.mark.asyncio
649666
async def test_preflight_allows_x_api_key(self):

0 commit comments

Comments
 (0)