Skip to content

feat(providers): add openrouter and azure env discovery#161

Merged
SantiagoDePolonia merged 6 commits intomainfrom
feat/discover-providers-based-on-env-variables-prefix
Mar 22, 2026
Merged

feat(providers): add openrouter and azure env discovery#161
SantiagoDePolonia merged 6 commits intomainfrom
feat/discover-providers-based-on-env-variables-prefix

Conversation

@SantiagoDePolonia
Copy link
Copy Markdown
Contributor

@SantiagoDePolonia SantiagoDePolonia commented Mar 21, 2026

Summary by CodeRabbit

  • New Features

    • Added support for OpenRouter and Azure OpenAI providers, provider discovery via environment variables, and per-provider API-version handling; unified OpenAI-compatible provider surface (chat, responses, embeddings, files, batches, passthrough) with request-mutator hooks.
  • Documentation

    • Updated docs, examples, and Docker quick-start to document new provider credentials, OpenRouter attribution header defaults/overrides, and Azure base URL/api-version rules (default 2024-10-21) and discovery requirements.
  • Tests

    • Added extensive tests for provider discovery, OpenRouter header behavior, Azure api-version/endpoints, and batch/file flows.

@SantiagoDePolonia SantiagoDePolonia self-assigned this Mar 21, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 21, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds OpenRouter and Azure OpenAI provider support: environment templates and docs, config example updates, provider APIVersion support and auto-discovery, a reusable OpenAI-compatible provider abstraction, concrete Azure and OpenRouter provider implementations (with API-version and attribution-header handling), factory APIVersion wiring, extensible file/batch request preparers, and extensive tests.

Changes

Cohort / File(s) Summary
Environment & Docs
\.env.template, GETTING_STARTED.md, README.md, docs/advanced/configuration.mdx
Added commented env vars for OPENROUTER_* and AZURE_*, documented defaults and gotchas (Azure requires key+base; default Azure api-version = 2024-10-21; OpenRouter attribution headers and overrides).
Config Examples & Tests
config/config.example.yaml, config/config_test.go
Added commented provider example for openrouter; renamed Azure example to azure with api_version; test helper clears new OpenRouter/Azure env keys.
Config Model & Discovery
config/config.go, internal/providers/config.go, internal/providers/config_test.go
Added APIVersion to provider config, extended env-driven discovery to handle per-provider defaults/requirements (openrouter default base, azure require base), normalize placeholders, and updated tests for discovery and placeholder handling.
Provider Factory & Registration
internal/providers/factory.go, cmd/gomodel/main.go, internal/providers/factory_test.go
Factory applies APIVersion to providers implementing SetAPIVersion; registered openrouter and azure and added factory test verifying APIVersion wiring.
OpenAI-Compatible Provider Core
internal/providers/openai/compatible_provider.go, internal/providers/openai/openai.go, internal/providers/openai/openai_test.go
Introduced CompatibleProvider abstraction (request mutator, unified surfaces: chat/responses/embeddings/files/batches/passthrough), refactored OpenAI provider to embed it, and added tests for nil-request errors and mutator propagation.
Azure Provider Implementation & Tests
internal/providers/azure/azure.go, internal/providers/azure/azure_test.go
Added Azure provider that mutates requests to set api-version query param, batch endpoints, SetAPIVersion, header handling (api-key, X-Client-Request-Id validation), and comprehensive HTTP-level tests.
OpenRouter Provider Implementation & Tests
internal/providers/openrouter/openrouter.go, internal/providers/openrouter/openrouter_test.go
Added OpenRouter provider with default base URL, request mutator to set HTTP-Referer and X-OpenRouter-Title when missing, env overrides (OPENROUTER_SITE_URL, OPENROUTER_APP_NAME), and tests validating attribution and passthrough behavior.
File/Batch Request Extensibility
internal/providers/file_adapter_openai_compat.go, internal/providers/batch_results_file_adapter.go, internal/providers/batch_results_file_adapter_test.go, internal/providers/batch_results_file_adapter_test.go
Added preparer hook for OpenAI-compatible file requests and batch-results fetching, new *WithPreparer variants, refactored shared logic, and tests asserting provider errors on nil responses.
Registry & Integration Tests
internal/providers/registry_test.go, other tests...
Updated registry tests to register openrouter type and added/updated unit and HTTP tests across provider packages to cover new behaviors and edge cases.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Client as Client
  participant Factory as ProviderFactory
  participant Provider as Provider (openrouter / azure)
  participant External as ExternalAPI

  Client->>Factory: Build ProviderConfig(type, api_key, base, api_version)
  Factory->>Provider: Create(config)
  alt cfg.APIVersion non-empty and provider supports it
    Factory->>Provider: SetAPIVersion(cfg.APIVersion)
  end
  Client->>Provider: ChatCompletion request
  Provider->>Provider: RequestMutator (inject headers, default base, api-version)
  Provider->>External: HTTP POST /chat/completions (with api-key, query/api-version, headers)
  External-->>Provider: HTTP response
  Provider-->>Client: Parsed ChatCompletion response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

enhancement

Poem

🐰 I hopped through envs and headers bright,
OpenRouter, Azure tucked in tight.
Mutators set and versions pinned right,
Tests wagged tails under moonlight —
Hooray, these providers take their flight!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.48% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature added: support for environment variable discovery of two new LLM providers (OpenRouter and Azure) with auto-configuration capabilities.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/discover-providers-based-on-env-variables-prefix

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/providers/config.go`:
- Around line 106-108: The hardcoded name check (name == "azure") is fragile;
change the logic to consult provider metadata instead — replace the string
comparison with the provider's require-base flag or type field (e.g., use
p.RequireBase or p.Type) and the existing p.BaseURL check: for example, instead
of if name == "azure" && strings.TrimSpace(p.BaseURL) == "" { continue }, use a
metadata-driven condition like if !p.RequireBase && strings.TrimSpace(p.BaseURL)
== "" { continue } (or if p.Type == "azure" when type semantics are preferred)
so the filter works regardless of the provider instance name.
- Line 38: The config registers Azure as providerType "openai" which causes the
OpenAI client (see setHeaders in internal/providers/openai/openai.go and
SetBaseURL()) to use Bearer auth and fail for Azure OpenAI; change the
registration entry in internal/providers/config.go from type "openai" to a
distinct "azure" (or add a separate Azure provider record) and update the OpenAI
provider's setHeaders to detect provider type "azure" (or implement a new azure
provider) to send the required "api-key" header instead of the Bearer
Authorization header so Azure requests authenticate correctly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 43632a9b-765c-42e3-a210-e4c576f1c10d

📥 Commits

Reviewing files that changed from the base of the PR and between 980d755 and 7783d2b.

📒 Files selected for processing (8)
  • .env.template
  • GETTING_STARTED.md
  • README.md
  • config/config.example.yaml
  • config/config_test.go
  • docs/advanced/configuration.mdx
  • internal/providers/config.go
  • internal/providers/config_test.go

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
internal/providers/config.go (1)

113-115: ⚠️ Potential issue | 🟠 Major

Validate Azure's required base URL by provider type, not map key.

This guard only skips the provider named exactly azure. The docs in this PR still advertise custom provider names, so a block like my-azure: { type: azure } bypasses it, and ${AZURE_API_BASE} also slips through because it is non-empty. That leaves a broken Azure config in the resolved map and it only fails later at request time.

🛠️ Suggested fix
-		if name == "azure" && strings.TrimSpace(p.BaseURL) == "" {
+		if p.Type == "azure" && (strings.TrimSpace(p.BaseURL) == "" || strings.Contains(p.BaseURL, "${")) {
 			continue
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/providers/config.go` around lines 113 - 115, The guard is checking
the map key `name` instead of the provider's declared type, so providers named
anything other than the literal key "azure" (e.g., "my-azure") bypass the
BaseURL validation; change the conditional to check the provider type (e.g.,
`p.Type == "azure"` or case-insensitive equivalent) and keep the existing
strings.TrimSpace(p.BaseURL) check so any Azure-typed provider with an empty
BaseURL is skipped/handled. Locate the block that uses `name` and `p.BaseURL`
and update the condition to reference the provider type field (e.g., `p.Type`)
instead of `name`. Ensure behavior remains the same for non-Azure providers.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@config/config.example.yaml`:
- Around line 155-160: Update the example Azure config to use the environment
placeholder ${AZURE_API_BASE} for the azure.base_url field instead of a
hardcoded URL so it matches .env.template and the setup docs; modify the
commented block that defines the azure config (keys: azure, type, base_url,
api_key, api_version) to set base_url: "${AZURE_API_BASE}" while keeping the
rest of the fields unchanged.

In `@internal/providers/azure/azure.go`:
- Around line 21-45: The Azure Provider currently embeds
openai.CompatibleProvider (Provider) but inherits ListModels, CreateBatch,
GetBatch, ListBatches and CancelBatch which call /models and /batches; implement
overrides on Provider for ListModels, CreateBatch, GetBatch, ListBatches and
CancelBatch so they use the Azure REST paths prefixed with /openai/ (e.g.,
/openai/models, /openai/batches/...) instead of the default routes. In each
override, reuse the CompatibleProvider's request machinery (same auth/headers
from setHeaders and mutateRequest) but construct the HTTP path with the /openai/
prefix before delegating to the underlying request/HTTP client; add these
methods near New/NewWithHTTPClient so Provider consistently handles Azure route
differences.

In `@internal/providers/openai/compatible_provider.go`:
- Around line 86-116: The ChatCompletion and StreamChatCompletion methods (and
the other request-taking methods in this file around lines 131-172) currently
dereference req (via chatRequestBody(req), req.WithStreaming(), and reading
req.Model) and will panic on a nil request; add a nil check at the start of each
of these public entry points and return a typed core.GatewayError with category
"invalid_request_error" when req == nil (follow the same guard pattern used by
Passthrough). Ensure the early-return uses the core GatewayError
constructor/util your codebase uses so callers receive a proper provider-facing
invalid_request_error instead of a panic.

---

Duplicate comments:
In `@internal/providers/config.go`:
- Around line 113-115: The guard is checking the map key `name` instead of the
provider's declared type, so providers named anything other than the literal key
"azure" (e.g., "my-azure") bypass the BaseURL validation; change the conditional
to check the provider type (e.g., `p.Type == "azure"` or case-insensitive
equivalent) and keep the existing strings.TrimSpace(p.BaseURL) check so any
Azure-typed provider with an empty BaseURL is skipped/handled. Locate the block
that uses `name` and `p.BaseURL` and update the condition to reference the
provider type field (e.g., `p.Type`) instead of `name`. Ensure behavior remains
the same for non-Azure providers.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e198c176-b6dc-4fb6-a03a-db54620104d4

📥 Commits

Reviewing files that changed from the base of the PR and between 7783d2b and c47c1fa.

📒 Files selected for processing (16)
  • .env.template
  • GETTING_STARTED.md
  • README.md
  • cmd/gomodel/main.go
  • config/config.example.yaml
  • config/config.go
  • config/config_test.go
  • docs/advanced/configuration.mdx
  • internal/providers/azure/azure.go
  • internal/providers/azure/azure_test.go
  • internal/providers/config.go
  • internal/providers/config_test.go
  • internal/providers/factory.go
  • internal/providers/factory_test.go
  • internal/providers/openai/compatible_provider.go
  • internal/providers/openai/openai.go

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
internal/providers/config.go (1)

113-115: ⚠️ Potential issue | 🟠 Major

Filter Azure configs by type, not by the literal provider name.

name == "azure" only catches the auto-discovered/default entry. A YAML block like my-azure: { type: azure } with an empty base_url survives this filter and then runs against the placeholder default base. Use p.Type == "azure" or the same metadata used during discovery here instead.

Suggested change
-		if name == "azure" && strings.TrimSpace(p.BaseURL) == "" {
+		if p.Type == "azure" && strings.TrimSpace(p.BaseURL) == "" {
 			continue
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/providers/config.go` around lines 113 - 115, The filter currently
checks the literal provider name variable "name" to skip Azure entries with
empty BaseURL, which misses configs like "my-azure" that declare azure via the
p.Type field; update the condition to check the provider metadata/type (use
p.Type == "azure" or the same discovery metadata used elsewhere) instead of name
== "azure" so entries where p.Type is "azure" and strings.TrimSpace(p.BaseURL)
== "" are correctly skipped; adjust the conditional in the block around
p.BaseURL to reference p.Type (or the discovery marker) and leave the rest of
the logic unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/providers/azure/azure.go`:
- Around line 50-59: ListModels and the Azure batch methods are using the
deployment-scoped client base (so requests become
.../deployments/<deployment>/openai/...), but Azure expects resource-level
routes like /openai/models and /openai/batches; update Provider.ListModels and
all batch-related methods (the functions calling p.Do with endpoints
"/openai/models" and "/openai/batches...") to compute a resource-root base URL
(strip the "/deployments/<deployment>" segment from the current base or build
the URL from the Azure resource root stored in the provider) and use that
resource-root when calling p.Do so the final request path becomes
<resource-root>/openai/... instead of <deployment-base>/openai/.... Ensure the
change is applied consistently to ListModels and every batch operation
referenced in the file.

In `@internal/providers/config.go`:
- Around line 61-71: The loop over knownProviderEnvs skips processing when both
apiKey and baseURL are empty, which prevents an env-only AZURE_API_VERSION (from
kp.apiVersionEnv) from overriding YAML; change the logic in the loop that
references knownProviderEnvs and kp.apiVersionEnv so that if apiVersion
(os.Getenv(kp.apiVersionEnv)) is non-empty you do not continue early — instead
allow creation/update of the provider entry in the providers map (e.g.,
providers["azure"] / providers.Azure handling) and apply the apiVersion override
even when apiKey and baseURL are blank; ensure the subsequent code that merges
env values into the provider config still runs for the apiVersion case.

In `@internal/providers/openai/compatible_provider.go`:
- Around line 294-333: The helper-based file and batch-result methods
(GetBatchResults, CreateFile, ListFiles, GetFile, DeleteFile, GetFileContent)
currently call providers.* with p.client directly and therefore skip the
provider-specific requestMutator/prepareRequest; update these methods to run
prepareRequest (or otherwise apply requestMutator) before issuing the
request—e.g., build an llmclient.Request via p.prepareRequest or call a client
wrapper that applies the mutator and then pass that prepared request into the
providers.* functions (or modify the providers call site to accept a prepared
request) so Azure/OpenRouter-specific headers (like api-version and attribution)
are always applied.

---

Duplicate comments:
In `@internal/providers/config.go`:
- Around line 113-115: The filter currently checks the literal provider name
variable "name" to skip Azure entries with empty BaseURL, which misses configs
like "my-azure" that declare azure via the p.Type field; update the condition to
check the provider metadata/type (use p.Type == "azure" or the same discovery
metadata used elsewhere) instead of name == "azure" so entries where p.Type is
"azure" and strings.TrimSpace(p.BaseURL) == "" are correctly skipped; adjust the
conditional in the block around p.BaseURL to reference p.Type (or the discovery
marker) and leave the rest of the logic unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5d30b252-d37d-4e78-b506-f6ab56e8a59b

📥 Commits

Reviewing files that changed from the base of the PR and between c47c1fa and 0606096.

📒 Files selected for processing (15)
  • .env.template
  • GETTING_STARTED.md
  • cmd/gomodel/main.go
  • config/config.example.yaml
  • config/config_test.go
  • docs/advanced/configuration.mdx
  • internal/providers/azure/azure.go
  • internal/providers/azure/azure_test.go
  • internal/providers/config.go
  • internal/providers/config_test.go
  • internal/providers/openai/compatible_provider.go
  • internal/providers/openai/openai_test.go
  • internal/providers/openrouter/openrouter.go
  • internal/providers/openrouter/openrouter_test.go
  • internal/providers/registry_test.go

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
internal/providers/batch_results_file_adapter.go (1)

45-53: ⚠️ Potential issue | 🟠 Major

Guard the raw batch response before reading Body.

GetOpenAICompatibleFileContentWithPreparer already treats client.DoRaw(...) as nullable on a nil-error path, but this helper dereferences batchRaw.Body immediately. If the same nil-success path happens here, GetBatchResults panics instead of returning a typed provider error.

Suggested fix
 	batchRaw, err := client.DoRaw(ctx, prepareOpenAICompatibleRequest(prepare, llmclient.Request{
 		Method:   http.MethodGet,
 		Endpoint: "/batches/" + url.PathEscape(batchID),
 	}))
 	if err != nil {
 		return nil, err
 	}
+	if batchRaw == nil {
+		return nil, core.NewProviderError(providerName, http.StatusBadGateway, "provider returned empty batch metadata response", fmt.Errorf("nil response"))
+	}
 
 	outputFileID, status, endpoint := parseBatchFileMetadata(batchRaw.Body)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/providers/batch_results_file_adapter.go` around lines 45 - 53,
GetBatchResults dereferences batchRaw.Body immediately after client.DoRaw; guard
against a nil batchRaw or nil Body and return a typed provider error instead of
panicking. Update the code after the client.DoRaw(...) call in GetBatchResults
to check that batchRaw != nil and batchRaw.Body != nil before calling
parseBatchFileMetadata, and if either is nil return the same provider error
shape used elsewhere in this package (match the typed provider error pattern
used by GetOpenAICompatibleFileContentWithPreparer or other helper functions) so
callers receive a proper error instead of a panic.
internal/providers/config.go (1)

74-87: ⚠️ Potential issue | 🟠 Major

Reject unresolved Azure base placeholders during filtering.

applyProviderEnvVars can update only APIKey and leave the YAML BaseURL untouched. With BaseURL: "${AZURE_API_BASE}" and a real API key from env, this code sees a non-empty base and keeps the provider, so resolution succeeds but every later request uses the literal placeholder as the base URL. Treat ${...} the same as missing here.

Suggested fix
-		if p.Type == "azure" && strings.TrimSpace(p.BaseURL) == "" {
+		trimmedBaseURL := strings.TrimSpace(p.BaseURL)
+		if p.Type == "azure" && (trimmedBaseURL == "" || strings.Contains(trimmedBaseURL, "${")) {
 			continue
 		}

Also applies to: 113-118

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/providers/config.go` around lines 74 - 87, In applyProviderEnvVars,
when deciding whether to keep or set existing.BaseURL treat unresolved
placeholders like "${...}" as empty: detect if existing.BaseURL (or
explicitBaseURL) matches the pattern ${...} and consider it absent so the branch
that preserves a non-empty BaseURL does not keep literal placeholders; if apiKey
exists and kp.defaultBase is available, set existing.BaseURL = kp.defaultBase.
Apply the same placeholder-check logic to the second similar block that updates
result at the later occurrence (the block around the other existing.BaseURL
handling).
♻️ Duplicate comments (1)
internal/providers/azure/azure.go (1)

24-27: ⚠️ Potential issue | 🟠 Major

Override Azure GetBatchResults as well.

This file moves Azure batch CRUD onto resourceProvider, but GetBatchResults is still inherited from the embedded CompatibleProvider. That path delegates to the generic helper that calls /batches/{id} and /files/{id}/content on the deployment-scoped client, so Azure batch result retrieval still misses the resource-level /openai/... routes. Add an Azure-specific override or parameterize the shared helper for Azure batch/file paths.

Also applies to: 63-147

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/providers/azure/azure.go` around lines 24 - 27, The Provider struct
now uses resourceProvider for Azure batch CRUD but still inherits
GetBatchResults from openai.CompatibleProvider which calls deployment-scoped
endpoints; add an Azure-specific override of GetBatchResults on the Provider
type (or update the shared helper to accept a base path) so it uses
resourceProvider and the resource-level /openai/... routes (match how
CreateBatch/CreateFile/etc. were moved). Specifically implement
Provider.GetBatchResults (method name) to call the same helper used by other
Azure resource-level batch/file operations but targeting resourceProvider (or
pass an azureBasePath flag) to ensure /openai/batches/{id} and
/openai/files/{id}/content are used.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@internal/providers/batch_results_file_adapter.go`:
- Around line 45-53: GetBatchResults dereferences batchRaw.Body immediately
after client.DoRaw; guard against a nil batchRaw or nil Body and return a typed
provider error instead of panicking. Update the code after the client.DoRaw(...)
call in GetBatchResults to check that batchRaw != nil and batchRaw.Body != nil
before calling parseBatchFileMetadata, and if either is nil return the same
provider error shape used elsewhere in this package (match the typed provider
error pattern used by GetOpenAICompatibleFileContentWithPreparer or other helper
functions) so callers receive a proper error instead of a panic.

In `@internal/providers/config.go`:
- Around line 74-87: In applyProviderEnvVars, when deciding whether to keep or
set existing.BaseURL treat unresolved placeholders like "${...}" as empty:
detect if existing.BaseURL (or explicitBaseURL) matches the pattern ${...} and
consider it absent so the branch that preserves a non-empty BaseURL does not
keep literal placeholders; if apiKey exists and kp.defaultBase is available, set
existing.BaseURL = kp.defaultBase. Apply the same placeholder-check logic to the
second similar block that updates result at the later occurrence (the block
around the other existing.BaseURL handling).

---

Duplicate comments:
In `@internal/providers/azure/azure.go`:
- Around line 24-27: The Provider struct now uses resourceProvider for Azure
batch CRUD but still inherits GetBatchResults from openai.CompatibleProvider
which calls deployment-scoped endpoints; add an Azure-specific override of
GetBatchResults on the Provider type (or update the shared helper to accept a
base path) so it uses resourceProvider and the resource-level /openai/... routes
(match how CreateBatch/CreateFile/etc. were moved). Specifically implement
Provider.GetBatchResults (method name) to call the same helper used by other
Azure resource-level batch/file operations but targeting resourceProvider (or
pass an azureBasePath flag) to ensure /openai/batches/{id} and
/openai/files/{id}/content are used.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 363a5bb0-494c-4e12-bcc8-7397f611da9f

📥 Commits

Reviewing files that changed from the base of the PR and between 0606096 and 697b12d.

📒 Files selected for processing (8)
  • internal/providers/azure/azure.go
  • internal/providers/azure/azure_test.go
  • internal/providers/batch_results_file_adapter.go
  • internal/providers/config.go
  • internal/providers/config_test.go
  • internal/providers/file_adapter_openai_compat.go
  • internal/providers/openai/compatible_provider.go
  • internal/providers/openai/openai_test.go

@SantiagoDePolonia SantiagoDePolonia merged commit 76d4993 into main Mar 22, 2026
15 checks passed
@SantiagoDePolonia SantiagoDePolonia deleted the feat/discover-providers-based-on-env-variables-prefix branch April 4, 2026 11:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant