Add configurable path_suffix for OpenAI-compat endpoints#2558
Add configurable path_suffix for OpenAI-compat endpoints#2558RefuseOdd wants to merge 2 commits into
Conversation
Adds an optional path_suffix field that lets users override the API path for OpenAI-compatible endpoints. When set, the suffix replaces the default /v1/<path> pattern, enabling use with endpoints that don't accept /v1/ prefixes (e.g. /chat/completions instead of /v1/chat/completions). Changes: - ProviderConfigToml (config crate): path_suffix field - ProviderConfig (tui crate): path_suffix field - merge_provider_config: propagates path_suffix - merge_project_provider_config: propagates path_suffix - api_url: delegates to new api_url_with_suffix function - api_url_with_suffix: uses suffix when present, skips /v1 versioning - DeepSeekClient: reads path_suffix from config, passes to URL builder - config.example.toml: documents the new option - Tests for the new URL building behavior Closes Hmbown#2089
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
|
Thanks for tackling I am not harvesting this revision into v0.8.50 yet because the current plumbing applies the suffix too broadly. The fix should be narrow:
Once those pass, this is the kind of small provider-compatibility feature that should be harvestable. |
|
Hey @RefuseOdd — this is a solid feature! Several third-party OpenAI-compatible endpoints do need a custom path, and a config field is the right place for it. Two small things before this is harvest-ready:
Fix those two and this is good to go! Happy to review the update. 🐋 |
|
@Hmbown pushed the requested fixes in
I also added focused tests for chat suffix stripping, model listing ignoring suffix, and beta paths ignoring suffix. |
Summary
Adds an optional
path_suffixfield to provider config that lets users override the API path for OpenAI-compatible endpoints. Some third-party endpoints reject/v1/chat/completionsand only accept/chat/completions. This change allows users to setpath_suffix = "/chat/completions"in their provider config to bypass the default/v1versioning.Changes
ProviderConfigToml(config crate): addedpath_suffix: Option<String>ProviderConfig(tui crate): addedpath_suffix: Option<String>merge_provider_config: propagates the new fieldmerge_project_provider_config: propagates the new fieldapi_url: delegates to newapi_url_with_suffixapi_url_with_suffix: when suffix is set, uses base URL directly with the suffix path (skips /v1)DeepSeekClient::new: readspath_suffixfrom configDeepSeekClientmethods: all URL-building calls useapi_url_with_suffixconfig.example.toml: documents the new optionCloses #2089
Greptile Summary
Adds an optional
path_suffixfield to provider config so users can override the API path for OpenAI-compatible endpoints that reject the default/v1/chat/completionsroute (e.g. providers that only accept/chat/completions).api_url_with_suffixcorrectly usesunversioned_base_urlto strip the version segment before appending the suffix, and the suffix guard is scoped topath == \"chat/completions\"only —models, health probes, andbeta/FIM paths are all unaffected.path_suffixis wired throughDeepSeekClient, both chat call sites inchat.rs, and all three config merge paths; tests cover the main URL-building cases including the no-suffix default, version stripping, and path isolation.Confidence Score: 4/5
Safe to merge with one design decision worth revisiting before shipping.
The core URL-building logic is correct and well-tested. The one open question is whether
path_suffixshould be settable from untrusted project-level config: themerge_project_provider_confighelper is explicitly documented to exclude endpoint fields, yetpath_suffix— which redirects chat API calls to an arbitrary path on the provider — was added to it. This doesn't cross a host boundary, so exploitation is limited, but it contradicts the function's stated security policy and may deserve a second look before the feature is released.crates/config/src/lib.rs — specifically whether
path_suffixbelongs inmerge_project_provider_configgiven that function's documented exclusion of endpoint overrides.Important Files Changed
api_url_with_suffixthat correctly strips the version segment viaunversioned_base_urland only applies the suffix for thechat/completionspath;path_suffixfield added toDeepSeekClientand read from provider config on construction.api_urltoapi_url_with_suffixwithself.path_suffix.as_deref(); straightforward mechanical change.path_suffixadded toProviderConfigTomland propagated inmerge_project_provider_config, but that helper is explicitly documented to exclude endpoint-related fields from untrusted project config.path_suffixfield added toProviderConfigandmerge_provider_config; all changes are consistent with the existing field pattern.path_suffixexample under the custom provider block with a clear description.Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A["api_url_with_suffix(base_url, path, suffix)"] --> B{path starts with 'beta/'?} B -- yes --> C["format: unversioned_base_url(base_url) / path"] B -- no --> D{path == 'chat/completions' AND suffix set?} D -- yes --> E["format: unversioned_base_url(base_url) / suffix.trim_start_matches('/')"] D -- no --> F["versioned = versioned_base_url(base_url)"] F --> G{versioned ends with 'beta'?} G -- yes --> H["versioned = unversioned_base_url / v1"] G -- no --> I["use versioned as-is"] H --> J["format: versioned / path"] I --> J subgraph Call Sites K["chat.rs streaming"] -->|path_suffix| A L["chat.rs non-streaming"] -->|path_suffix| A M["client.rs translate"] -->|path_suffix| A N["client.rs FIM beta/completions"] -->|None| A O["client.rs list_models"] -->|api_url wraps with None| A P["client.rs health probe"] -->|api_url wraps with None| A endReviews (2): Last reviewed commit: "Limit path suffix to chat completions" | Re-trigger Greptile