Skip to content

Commit 2675a0b

Browse files
authored
feat: add base path field to custom provider configuration (#7614)
Signed-off-by: sheikhlimon <sheikhlimon404@gmail.com>
1 parent 5f48087 commit 2675a0b

3 files changed

Lines changed: 40 additions & 2 deletions

File tree

crates/goose-cli/src/commands/configure.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2015,6 +2015,17 @@ fn add_provider() -> anyhow::Result<()> {
20152015
.initial_value(true)
20162016
.interact()?;
20172017

2018+
let base_path_input: String = cliclack::input("API base path (optional, press Enter to skip):")
2019+
.placeholder("e.g., v1/chat/completions or project_id/v1")
2020+
.required(false)
2021+
.interact()?;
2022+
2023+
let base_path = if base_path_input.trim().is_empty() {
2024+
None
2025+
} else {
2026+
Some(base_path_input)
2027+
};
2028+
20182029
let headers = collect_custom_headers()?;
20192030

20202031
create_custom_provider(CreateCustomProviderParams {
@@ -2027,7 +2038,7 @@ fn add_provider() -> anyhow::Result<()> {
20272038
headers,
20282039
requires_auth,
20292040
catalog_provider_id: None,
2030-
base_path: None,
2041+
base_path,
20312042
})?;
20322043

20332044
cliclack::outro(format!("Custom provider added: {}", display_name))?;

ui/desktop/src/components/settings/providers/ProviderGrid.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ function ProviderCards({
236236
engine: editingProvider.config.engine,
237237
display_name: editingProvider.config.display_name,
238238
api_url: editingProvider.config.base_url,
239+
base_path: editingProvider.config.base_path ?? undefined,
239240
api_key: '',
240241
models: editingProvider.config.models.map((m) => m.name),
241242
supports_streaming: editingProvider.config.supports_streaming ?? true,

ui/desktop/src/components/settings/providers/modal/subcomponents/forms/CustomProviderForm.tsx

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export default function CustomProviderForm({
3030
const [engine, setEngine] = useState('openai_compatible');
3131
const [displayName, setDisplayName] = useState('');
3232
const [apiUrl, setApiUrl] = useState('');
33+
const [basePath, setBasePath] = useState('');
3334
const [apiKey, setApiKey] = useState('');
3435
const [models, setModels] = useState('');
3536
const [requiresAuth, setRequiresAuth] = useState(false);
@@ -59,6 +60,7 @@ export default function CustomProviderForm({
5960
setEngine(engineMap[initialData.engine] || 'openai_compatible');
6061
setDisplayName(initialData.display_name);
6162
setApiUrl(initialData.api_url);
63+
setBasePath(initialData.base_path ?? '');
6264
setModels(initialData.models.join(', '));
6365
setSupportsStreaming(initialData.supports_streaming ?? true);
6466
setRequiresAuth(initialData.requires_auth ?? true);
@@ -81,6 +83,7 @@ export default function CustomProviderForm({
8183
// Prefill fields from template
8284
setDisplayName(template.name);
8385
setApiUrl(template.api_url);
86+
setBasePath('');
8487
setSupportsStreaming(template.supports_streaming);
8588
setRequiresAuth(true);
8689

@@ -101,6 +104,7 @@ export default function CustomProviderForm({
101104
setSelectedTemplate(null);
102105
setDisplayName('');
103106
setApiUrl('');
107+
setBasePath('');
104108
setModels('');
105109
setEngine('openai_compatible');
106110
setSupportsStreaming(true);
@@ -233,6 +237,7 @@ export default function CustomProviderForm({
233237
requires_auth: requiresAuth,
234238
headers: headersObject,
235239
catalog_provider_id: selectedTemplate?.id ?? initialData?.catalog_provider_id ?? undefined,
240+
base_path: basePath || undefined,
236241
});
237242
};
238243

@@ -438,7 +443,7 @@ export default function CustomProviderForm({
438443
id="api-url"
439444
value={apiUrl}
440445
onChange={(e) => setApiUrl(e.target.value)}
441-
placeholder="https://api.example.com/v1"
446+
placeholder="https://api.example.com"
442447
aria-invalid={!!validationErrors.apiUrl}
443448
aria-describedby={validationErrors.apiUrl ? 'api-url-error' : undefined}
444449
className={validationErrors.apiUrl ? 'border-red-500' : ''}
@@ -451,6 +456,27 @@ export default function CustomProviderForm({
451456
</div>
452457
)}
453458

459+
{/* Base Path */}
460+
{isEditable && (
461+
<div>
462+
<label
463+
htmlFor="base-path"
464+
className="flex items-center text-sm font-medium text-text-primary mb-2"
465+
>
466+
API Base Path (optional)
467+
</label>
468+
<Input
469+
id="base-path"
470+
value={basePath}
471+
onChange={(e) => setBasePath(e.target.value)}
472+
placeholder="e.g., v1/chat/completions or project_id/v1"
473+
/>
474+
<p className="text-xs text-textSubtle mt-1">
475+
Override the default API path. Leave blank to use the provider's default path.
476+
</p>
477+
</div>
478+
)}
479+
454480
{/* Authentication */}
455481
<div>
456482
<label className="block text-sm font-medium text-text-primary mb-2">Authentication</label>

0 commit comments

Comments
 (0)