55from pydantic import BaseModel , ConfigDict
66
77
8- class ModelEntry (BaseModel ):
9- """One entry in an OpenAI-compat ``GET /v1/models`` response.
10-
11- Runtimes (vLLM, SGLang, NIM) typically include extra fields such as
12- ``created`` or ``owned_by``; ``extra="allow"`` keeps them on the
13- model so future additions don't break parsing.
8+ class _OpenAICompatModel (BaseModel ):
9+ """Base for OpenAI-compat response DTOs.
10+
11+ Runtimes (vLLM, SGLang, NIM, TGI) ship runtime-specific extras
12+ (``usage``, ``system_fingerprint``, ``tool_calls``,
13+ ``reasoning_content``, ``prompt_logprobs``, ``owned_by``, ...).
14+ ``extra="allow"`` keeps them on the model so ``model_dump_json``
15+ round-trips faithfully back to the CLI's stdout pretty-print.
1416 """
1517
1618 model_config = ConfigDict (extra = "allow" )
1719
20+
21+ class ModelEntry (_OpenAICompatModel ):
22+ """One entry in an OpenAI-compat ``GET /v1/models`` response."""
23+
1824 id : str
1925 object : str = "model"
2026
2127
22- class ListModelsResponse (BaseModel ):
28+ class ListModelsResponse (_OpenAICompatModel ):
2329 """Body of ``GET /v1/models`` on an OpenAI-compat endpoint."""
2430
25- model_config = ConfigDict (extra = "allow" )
26-
2731 object : str = "list"
2832 data : list [ModelEntry ]
2933
3034
31- class ChatCompletionResponseMessage (BaseModel ):
35+ class ChatCompletionResponseMessage (_OpenAICompatModel ):
3236 """The ``message`` payload inside one OpenAI-compat choice.
3337
3438 Only ``content`` is consumed by the CLI (for chat-history persistence);
35- ``extra="allow"`` keeps runtime-specific fields like ``tool_calls`` or
36- ``reasoning_content`` (DeepSeek-R1, Qwen-QwQ) on the model so they pass
37- through to the JSON pretty-printed output .
39+ runtime-specific fields like ``tool_calls`` or ``reasoning_content``
40+ (DeepSeek-R1, Qwen-QwQ) pass through to the JSON pretty-printed output
41+ via the inherited ``extra="allow"`` .
3842 """
3943
40- model_config = ConfigDict (extra = "allow" )
41-
4244 role : str | None = None
4345 content : str | None = None
4446
4547
46- class ChatCompletionResponseChoice (BaseModel ):
48+ class ChatCompletionResponseChoice (_OpenAICompatModel ):
4749 """One entry in ``choices[]`` on a non-streaming chat-completion response.
4850
4951 Streaming responses use ``delta`` instead of ``message``; this model
@@ -52,24 +54,20 @@ class ChatCompletionResponseChoice(BaseModel):
5254 ``ValidationError`` rather than corrupting persisted history.
5355 """
5456
55- model_config = ConfigDict (extra = "allow" )
56-
5757 message : ChatCompletionResponseMessage
5858
5959
60- class ChatCompletionResponse (BaseModel ):
60+ class ChatCompletionResponse (_OpenAICompatModel ):
6161 """Body of ``POST /v1/chat/completions`` (OpenAI-compatible).
6262
6363 Only the path used by chat-history bookkeeping
64- (``choices[0].message.content``) is typed here. The remaining
65- top-level fields (``id``, ``object``, ``created``, ``model``,
66- ``usage``, `` system_fingerprint``, runtime-specific extras ) ride
67- through via ``extra="allow"`` so they survive the round-trip back
64+ (``choices[0].message.content``) is typed here. Top-level extras
65+ (``id``, ``object``, ``created``, ``model``, ``usage ``,
66+ ``system_fingerprint``, runtime-specific fields ) ride through via
67+ the inherited ``extra="allow"`` so they survive the round-trip back
6868 to the user's stdout when the CLI pretty-prints the response.
6969 """
7070
71- model_config = ConfigDict (extra = "allow" )
72-
7371 choices : list [ChatCompletionResponseChoice ]
7472
7573 @property
0 commit comments