fix(coding-agent): allow custom providers to use stored auth
closes #5953
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed `pi --resume` to load user package themes and resolve automatic light/dark theme settings.
|
- Fixed `pi --resume` to load user package themes and resolve automatic light/dark theme settings.
|
||||||
|
- Fixed `models.json` custom providers so stored credentials can satisfy auth without a redundant provider-level `apiKey` ([#5953](https://github.com/earendil-works/pi/issues/5953)).
|
||||||
|
|
||||||
## [0.79.10] - 2026-06-22
|
## [0.79.10] - 2026-06-22
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ For local models (Ollama, LM Studio, vLLM), only `id` is required per model:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The `apiKey` is required but Ollama ignores it, so any value works.
|
The `apiKey` value is a placeholder because Ollama ignores it. pi still treats models as requiring auth before they appear in `/model`, so keyless local servers should keep a dummy value, save a key for that provider with `/login`, or pass `--api-key` when selecting the model.
|
||||||
|
|
||||||
Some OpenAI-compatible servers do not understand the `developer` role used for reasoning-capable models. For those providers, set `compat.supportsDeveloperRole` to `false` so pi sends the system prompt as a `system` message instead. If the server also does not support `reasoning_effort`, set `compat.supportsReasoningEffort` to `false` too.
|
Some OpenAI-compatible servers do not understand the `developer` role used for reasoning-capable models. For those providers, set `compat.supportsDeveloperRole` to `false` so pi sends the system prompt as a `system` message instead. If the server also does not support `reasoning_effort`, set `compat.supportsReasoningEffort` to `false` too.
|
||||||
|
|
||||||
@@ -135,12 +135,14 @@ Set `api` at provider level (default for all models) or model level (override pe
|
|||||||
|-------|-------------|
|
|-------|-------------|
|
||||||
| `baseUrl` | API endpoint URL |
|
| `baseUrl` | API endpoint URL |
|
||||||
| `api` | API type (see above) |
|
| `api` | API type (see above) |
|
||||||
| `apiKey` | API key (see value resolution below) |
|
| `apiKey` | Optional API key config (see value resolution below). Omit it when auth is provided by `/login`/`auth.json` or CLI `--api-key`. |
|
||||||
| `headers` | Custom headers (see value resolution below) |
|
| `headers` | Custom headers (see value resolution below) |
|
||||||
| `authHeader` | Set `true` to add `Authorization: Bearer <apiKey>` automatically |
|
| `authHeader` | Set `true` to add `Authorization: Bearer <apiKey>` automatically |
|
||||||
| `models` | Array of model configurations |
|
| `models` | Array of model configurations |
|
||||||
| `modelOverrides` | Per-model overrides for built-in models on this provider |
|
| `modelOverrides` | Per-model overrides for built-in models on this provider |
|
||||||
|
|
||||||
|
For providers with `models`, non-built-in provider configs need `baseUrl` and an `api` value at either provider or model level. `apiKey` is not required to load the file: models become available when auth is configured through `/login`/`auth.json`, CLI `--api-key`, or provider `apiKey`. If no auth is configured, the models load but stay unavailable in `/model` and `--list-models`.
|
||||||
|
|
||||||
### Value Resolution
|
### Value Resolution
|
||||||
|
|
||||||
The `apiKey` and `headers` fields support command execution, environment interpolation, and literals:
|
The `apiKey` and `headers` fields support command execution, environment interpolation, and literals:
|
||||||
|
|||||||
@@ -546,13 +546,11 @@ export class ModelRegistry {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (!isBuiltIn) {
|
} else if (!isBuiltIn) {
|
||||||
// Non-built-in providers with custom models require endpoint + auth.
|
// Non-built-in providers with custom models require an endpoint.
|
||||||
|
// Auth can come from auth.json, --api-key, or provider request config.
|
||||||
if (!providerConfig.baseUrl) {
|
if (!providerConfig.baseUrl) {
|
||||||
throw new Error(`Provider ${providerName}: "baseUrl" is required when defining custom models.`);
|
throw new Error(`Provider ${providerName}: "baseUrl" is required when defining custom models.`);
|
||||||
}
|
}
|
||||||
if (!providerConfig.apiKey) {
|
|
||||||
throw new Error(`Provider ${providerName}: "apiKey" is required when defining custom models.`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Built-in providers with custom models: baseUrl/apiKey/api are optional,
|
// Built-in providers with custom models: baseUrl/apiKey/api are optional,
|
||||||
// inherited from built-in models. Auth comes from env vars / auth storage.
|
// inherited from built-in models. Auth comes from env vars / auth storage.
|
||||||
|
|||||||
@@ -246,9 +246,10 @@ describe("ModelRegistry", () => {
|
|||||||
expect(model?.baseUrl).toBe("https://openrouter.ai/api/v1");
|
expect(model?.baseUrl).toBe("https://openrouter.ai/api/v1");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("non-built-in provider custom models still require baseUrl and apiKey", () => {
|
test("non-built-in provider custom models still require baseUrl", () => {
|
||||||
writeRawModelsJson({
|
writeRawModelsJson({
|
||||||
"my-custom-provider": {
|
"my-custom-provider": {
|
||||||
|
apiKey: "test-key",
|
||||||
models: [
|
models: [
|
||||||
{
|
{
|
||||||
id: "my-model",
|
id: "my-model",
|
||||||
|
|||||||
Reference in New Issue
Block a user