free-claude-code/providers/nvidia_nim/client.py
Alishahryar1 f3a7528d49
Some checks are pending
CI / checks (push) Waiting to run
Major refactor: API, providers, messaging, and Anthropic protocol
Consolidates the incremental refactor work into a single change set: modular web tools (api/web_tools), native Anthropic request building and SSE block policy, OpenAI conversion and error handling, provider transports and rate limiting, messaging handler and tree queue, safe logging, smoke tests, and broad test coverage.
2026-04-26 03:01:14 -07:00

71 lines
2.4 KiB
Python

"""NVIDIA NIM provider implementation."""
import json
from typing import Any
import openai
from loguru import logger
from config.nim import NimSettings
from providers.base import ProviderConfig
from providers.defaults import NVIDIA_NIM_DEFAULT_BASE
from providers.openai_compat import OpenAIChatTransport
from .request import (
build_request_body,
clone_body_without_chat_template,
clone_body_without_reasoning_budget,
)
class NvidiaNimProvider(OpenAIChatTransport):
"""NVIDIA NIM provider using official OpenAI client."""
def __init__(self, config: ProviderConfig, *, nim_settings: NimSettings):
super().__init__(
config,
provider_name="NIM",
base_url=config.base_url or NVIDIA_NIM_DEFAULT_BASE,
api_key=config.api_key,
)
self._nim_settings = nim_settings
def _build_request_body(
self, request: Any, thinking_enabled: bool | None = None
) -> dict:
"""Internal helper for tests and shared building."""
return build_request_body(
request,
self._nim_settings,
thinking_enabled=self._is_thinking_enabled(request, thinking_enabled),
)
def _get_retry_request_body(self, error: Exception, body: dict) -> dict | None:
"""Retry once with a downgraded body when NIM rejects a known field."""
status_code = getattr(error, "status_code", None)
if not isinstance(error, openai.BadRequestError) and status_code != 400:
return None
error_text = str(error)
error_body = getattr(error, "body", None)
if error_body is not None:
error_text = f"{error_text} {json.dumps(error_body, default=str)}"
error_text = error_text.lower()
if "reasoning_budget" in error_text:
retry_body = clone_body_without_reasoning_budget(body)
if retry_body is None:
return None
logger.warning(
"NIM_STREAM: retrying without reasoning_budget after 400 error"
)
return retry_body
if "chat_template" in error_text:
retry_body = clone_body_without_chat_template(body)
if retry_body is None:
return None
logger.warning("NIM_STREAM: retrying without chat_template after 400 error")
return retry_body
return None