Skip to content

bug: Setup wizard stores endpoint URL without /v1 path, breaking OpenAI provider #98

Description

@CybotTM

Summary

The Setup Wizard stores the raw endpoint URL entered by the user (e.g., https://api.openai.com) without normalizing it to include the required /v1 API version path. This causes OpenAiProvider::testConnection() and all API calls to fail with "Invalid URL (GET /models)" because requests go to https://api.openai.com/models instead of https://api.openai.com/v1/models.

Root Cause

There is an inconsistency between how the Setup Wizard and the Provider classes handle the endpoint URL:

Setup Wizard (ModelDiscovery, ConfigurationGenerator) appends /v1/ itself when making API calls:

// ModelDiscovery.php:115
$request = $this->requestFactory->createRequest('GET', $endpoint . '/v1/models')

// ConfigurationGenerator.php:289
default => $provider->endpoint . '/v1/chat/completions',

OpenAiProvider (AbstractProvider::sendRequest) expects /v1 to already be part of baseUrl:

// AbstractProvider.php:200
$url = rtrim($this->baseUrl, '/') . '/' . ltrim($endpoint, '/');

// OpenAiProvider.php:52
return 'https://api.openai.com/v1';  // getDefaultBaseUrl includes /v1

SetupWizardController::saveAction stores the raw endpoint without normalization:

// SetupWizardController.php:280
$providerEndpoint = is_string($providerData['endpoint'] ?? null) ? $providerData['endpoint'] : '';
// ...
$provider->setEndpointUrl($providerEndpoint);  // stored as-is

So the wizard works fine (it appends /v1 itself), but the stored provider breaks because OpenAiProvider doesn't append /v1 — it expects it in the base URL.

Steps to Reproduce

  1. Open the LLM Setup Wizard
  2. Enter https://api.openai.com as the endpoint (without /v1)
  3. Complete the wizard — detection and model discovery work fine
  4. Go to Providers module → click "Test Connection"
  5. Result: Connection Failed — Invalid URL (GET /models)

Expected Behavior

The Setup Wizard should normalize the endpoint URL before storing it. For known providers, it should ensure the required API version path is included:

Provider User enters Should store
OpenAI https://api.openai.com https://api.openai.com/v1
OpenAI https://api.openai.com/v1 https://api.openai.com/v1
Anthropic https://api.anthropic.com https://api.anthropic.com
Ollama http://localhost:11434 http://localhost:11434

Suggested Fix

Option A (recommended): Normalize the endpoint URL in SetupWizardController::saveAction() or in ProviderDetector::normalizeEndpoint() based on detected adapter type — append /v1 for OpenAI-compatible providers if not already present.

Option B: Make OpenAiProvider append /v1 itself if the base URL doesn't already contain it (defensive, but shifts responsibility).

Workaround

Manually edit the provider record and change endpoint_url from https://api.openai.com to https://api.openai.com/v1.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions