feat(provider): add Kenari as OpenAI-compatible JSON provider - #32095
feat(provider): add Kenari as OpenAI-compatible JSON provider#32095doedja wants to merge 2 commits into
Conversation
Greptile SummaryThis PR adds Kenari as an OpenAI-compatible JSON-configured provider, following the same pattern established by the
Confidence Score: 5/5Safe to merge — all changes are additive JSON/enum additions with no effect on existing providers or request paths. The change touches only configuration files and a new test file. No production logic is modified; new providers are loaded lazily from the JSON registry at runtime. All tests are mock-based and pass locally. No files require special attention.
|
| Filename | Overview |
|---|---|
| litellm/llms/openai_like/providers.json | Adds kenari entry with all required fields (base_url, api_key_env, api_base_env, supported_endpoints); correctly omits param_mappings because the API accepts max_completion_tokens natively. |
| litellm/types/utils.py | Adds KENARI = "kenari" enum member to LlmProviders in the correct alphabetical neighbourhood; straightforward one-liner addition. |
| tests/test_litellm/llms/kenari/test_kenari.py | Four mock-only tests covering registry lookup, env-var override, prefix detection, and URL construction — no real network calls, follows the neosantara test pattern. |
| provider_endpoints_support.json | Adds the kenari block with all endpoint flags; the url field pointing to a yet-to-be-published docs page was flagged in a prior review thread. |
| litellm/provider_endpoints_support_backup.json | Mirror of the root provider_endpoints_support.json kept in sync; identical kenari block added. |
Reviews (4): Last reviewed commit: "feat(provider): add Kenari as OpenAI-com..." | Re-trigger Greptile
| }, | ||
| "kenari": { | ||
| "display_name": "Kenari (`kenari`)", | ||
| "url": "https://docs.litellm.ai/docs/providers/kenari", |
There was a problem hiding this comment.
The
url field points to https://docs.litellm.ai/docs/providers/kenari, which doesn't exist yet. Per the repo's custom rule, docs must live in the litellm-docs repo rather than here. Until that page is published, this link will 404 for anyone who clicks it from the UI or the JSON. Consider either creating the docs page in the litellm-docs repo before merging or temporarily using the base docs URL.
Rule Used: Prevent documentation from being added - needs to ... (source)
Greptile SummaryThis PR adds Kenari as a JSON-configured OpenAI-compatible provider, following the same pattern as the
Confidence Score: 4/5The Kenari-specific changes are correct and safe; the main risk before merging is the 50+ unrelated upstream files that need to be rebased out and the broken docs URL. The five files that actually implement the Kenari provider are clean, minimal, and follow the established JSON-provider pattern exactly. The concerns are the missing docs page behind the URL already committed to both endpoint-support JSON files, and an unexplained CI fork-count reduction that belongs in a separate change. The large number of unrelated files swept in from upstream does not introduce bugs in the Kenari path but makes the PR harder to reason about and could mask unreviewed changes.
|
| Filename | Overview |
|---|---|
| litellm/llms/openai_like/providers.json | Adds kenari JSON entry with correct base_url, api_key_env, and api_base_env; no param_mappings needed since the API natively accepts max_completion_tokens; no supported_endpoints key since only chat completions is supported |
| litellm/types/utils.py | Adds LlmProviders.KENARI = "kenari" enum value in the correct alphabetical position relative to NEOSANTARA |
| provider_endpoints_support.json | Adds kenari endpoint support entry with chat_completions: true and all others false; references a docs URL (https://docs.litellm.ai/docs/providers/kenari) that does not yet exist |
| litellm/provider_endpoints_support_backup.json | Same kenari entry as provider_endpoints_support.json; both files updated in sync; same broken docs URL concern |
| tests/test_litellm/llms/kenari/test_kenari.py | Four unit tests (registry lookup, env-var config, provider prefix detection, complete URL construction) using mocks only; correctly mirrors the neosantara pattern without the responses-API and param-mapping tests that neosantara needs but kenari does not |
| .circleci/config.yml | Reduces UI test maxForks from 8 to 6; this change is unrelated to the Kenari provider addition and has no explanation |
Reviews (2): Last reviewed commit: "feat(provider): add Kenari as OpenAI-com..." | Re-trigger Greptile
|
|
||
| CI=true npm run test -- --run \ | ||
| --pool forks --poolOptions.forks.maxForks=8 | ||
| --pool forks --poolOptions.forks.maxForks=6 |
There was a problem hiding this comment.
Unrelated CI change with no explanation
Reducing --poolOptions.forks.maxForks from 8 to 6 has nothing to do with adding the Kenari provider. If this was intentional (e.g. to fix flaky CI due to resource contention), it should be in its own PR with a rationale. As-is it will silently slow down the UI test job for every future PR.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| "rerank": false | ||
| } | ||
| }, | ||
| "kenari": { |
There was a problem hiding this comment.
Docs URL references a page that does not yet exist
The "url" field points to https://docs.litellm.ai/docs/providers/kenari, but no corresponding page has been added to the litellm-docs repo yet (documentation for this repo must live there per the project guidelines). Until that page is published, every UI element or tooling that renders this link will show a 404. Per the same guidelines, docs cannot be added in this repo. Please ensure the docs page is created and live before this PR is merged, or defer the url entry until it is.
Rule Used: Prevent documentation from being added - needs to ... (source)
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
| from litellm._uuid import uuid | ||
| from litellm.litellm_core_utils.safe_json_dumps import safe_dumps | ||
| from litellm.proxy._types import ObjectPermissionDict, SpecialMCPServerNames | ||
| from litellm.proxy._types import ObjectPermissionDict, SpecialMCPServerName, SpecialMCPServerNames |
| from litellm._uuid import uuid | ||
| from litellm.litellm_core_utils.safe_json_dumps import safe_dumps | ||
| from litellm.proxy._types import ObjectPermissionDict, SpecialMCPServerNames | ||
| from litellm.proxy._types import ObjectPermissionDict, SpecialMCPServerName, SpecialMCPServerNames |
| from litellm._uuid import uuid | ||
| from litellm.litellm_core_utils.safe_json_dumps import safe_dumps | ||
| from litellm.proxy._types import ObjectPermissionDict, SpecialMCPServerNames | ||
| from litellm.proxy._types import ObjectPermissionDict, SpecialMCPServerName, SpecialMCPServerNames |
| from litellm.proxy.management_helpers.object_permission_utils import ( | ||
| _set_object_permission, | ||
| enforce_all_proxy_mcp_servers_grant_is_admin_only, | ||
| handle_update_object_permission_common, |
|
|
||
| async def invalidate( | ||
| self, subject_token: str, server: ServerSpec, config: TokenExchangeConfig, *, tenant_id: str = "" | ||
| ) -> None: ... |
|
|
||
| async def exchange( | ||
| self, subject_token: str, server: ServerSpec, config: TokenExchangeConfig, *, tenant_id: str = "" | ||
| ) -> Result[OAuthToken, CredError]: ... |
| async def _resolve_v2_auth( | ||
| self, | ||
| *, | ||
| server: MCPServer, | ||
| spec: ServerSpec, | ||
| provider: UpstreamCredentialProvider, | ||
| subject_token: Optional[str], | ||
| user_api_key_auth: Optional[UserAPIKeyAuth], | ||
| extra_headers: Optional[dict[str, str]], | ||
| ) -> tuple[Optional[httpx.Auth], Optional[dict[str, str]]]: |
| from litellm.proxy.common_utils.encrypt_decrypt_utils import decrypt_value_helper | ||
| from litellm.proxy.common_utils.user_api_key_cache import get_management_object_ttl | ||
| from litellm.proxy.utils import ProxyLogging | ||
| from litellm.proxy.utils import ProxyLogging, get_server_root_path |
e6333fa to
4365d89
Compare
|
Addressed the review feedback:
|
Kenari (https://kenari.id) is an OpenAI-compatible LLM gateway with IDR-denominated billing, serving models from DeepSeek, GLM, Kimi, Qwen, Claude, GPT and others at https://kenari.id/v1. Follows the JSON-based provider pattern (same shape as neosantara): - providers.json entry (KENARI_API_KEY / KENARI_API_BASE) - LlmProviders.KENARI enum value - provider_endpoints_support entries - registry/config/prefix-detection/URL tests Kenari accepts max_completion_tokens natively, so no param mapping is needed. Verified live: litellm.completion on kenari/deepseek-v4-flash, streaming and non-streaming.
b3d5e2b to
94259f9
Compare
|
Rebased onto current Scope is unchanged: the If the JSON provider shape has moved since this was written, point me at a recent example and I will match it. Also happy to be told if there is a label or a reviewer this should go through, since I am not sure the earlier bot review ever completed. |
Relevant issues
N/A (new provider addition via the JSON-based provider path)
Type
🆕 New Feature
Changes
Adds Kenari as a JSON-configured OpenAI-compatible provider, following the same pattern as the
neosantaraaddition (#29646).Kenari is an LLM gateway with IDR (Indonesian Rupiah) billing, serving models from DeepSeek, GLM, Kimi, Qwen, Claude, GPT and others through one OpenAI-compatible endpoint at
https://kenari.id/v1.litellm/llms/openai_like/providers.json:kenarientry (KENARI_API_KEY,KENARI_API_BASEoverride). Noparam_mappingsneeded: the API acceptsmax_completion_tokensnatively.litellm/types/utils.py:LlmProviders.KENARIenum value.provider_endpoints_support.json+ backup: chat completions entry.tests/test_litellm/llms/kenari/test_kenari.py: registry, env-var config, prefix detection, complete-URL tests (mirrors the neosantara test file).Testing
Verified live against the production endpoint: