feat(ai): send a per-entry reasoning effort to Local and gateway providers

Reasoning models on Ollama and similar servers think by default and can
spend the whole max_tokens budget before the visible answer starts, so
the call comes back empty or times out. The Local and OpenAI-compatible
chain entries now carry an optional reasoning setting: Default sends
nothing, Off sends reasoning_effort "none", Low / Medium / High send
their own value. It is stored on the entry in aiProviderChain, so a
chain can mix a thinking model with one that does not know the field.

- Every exported resolver binds the entry's value onto the client, the
  connection test included, keyed on the instance type so the operator
  provider, OpenAI, Anthropic and Codex never carry it.
- PATCH /api/user/ai-provider accepts localReasoningEffort and
  compatReasoningEffort and GET reports them. A provider absent from
  the chain holds its value on a disabled entry; restating Default on a
  chain that was never customised writes nothing.
- PUT /api/insights/provider-chain accepts reasoningEffort on local and
  openai-compatible entries, refuses it on any other, and keeps the
  stored value when the body leaves it out. Its schema is now shared
  with the OpenAPI registry.
- A Default request body is byte-identical to the one sent before.

Refs #1126
This commit is contained in:
Marc-André Bombeck committed 2026-10-04 10:42:59 +02:00
1 parent 808b2672cd
commit befac59576
18 files changed
+1350 -84

No files matched your search

+62 -1
View File
@@ -25855,6 +25855,28 @@ components:
minimum: 10
maximum: 600
- type: "null"
localReasoningEffort:
description: Reasoning setting of the Local provider entry, stored on that entry of the provider chain. `none` = Off,
`null` = Default (nothing sent). Omitted leaves it untouched.
anyOf:
- type: string
enum:
- none
- low
- medium
- high
- type: "null"
compatReasoningEffort:
description: Reasoning setting of the OpenAI-compatible gateway entry, stored on that entry of the provider chain.
`none` = Off, `null` = Default (nothing sent). Omitted leaves it untouched.
anyOf:
- type: string
enum:
- none
- low
- medium
- high
- type: "null"
description: "Partial update of the calling user's AI-provider configuration. An omitted key is left untouched; `null`
(or an empty string, on the string fields) clears the column. At least one recognised key must be present, or
the write is refused. Key material is write-only: it is encrypted on the way in and never returned. Unknown keys
@@ -27071,6 +27093,7 @@ components:
properties:
chain:
minItems: 1
maxItems: 7
type: array
items:
type: object
@@ -27096,15 +27119,30 @@ components:
maximum: 9007199254740991
enabled:
type: boolean
reasoningEffort:
description: Only on a `local` or `openai-compatible` entry; refused on any other. Omitted keeps the value already
stored for that provider, `null` restores Default, `none` / `low` / `medium` / `high` are sent as
`reasoning_effort`.
anyOf:
- type: string
enum:
- none
- low
- medium
- high
- type: "null"
required:
- providerType
- enabled
additionalProperties: false
description: The whole chain, in the order it should be walked. At least one entry and at most one per known provider
type; a repeated type is refused.
required:
- chain
additionalProperties: false
description: Replaces the account's provider chain wholesale. No credential is written or read here — only which
provider types exist, in what order, and which are enabled.
provider types exist, in what order, which are enabled, and the reasoning setting of the Local and
OpenAI-compatible entries.
InsightsFeedbackRequest:
type: object
properties:
@@ -48543,6 +48581,27 @@ components:
- type: "null"
description: v1.22 (#89) — per-user response timeout for AI generation, in seconds (10–600). Null = the built-in
comprehensive-briefing default (~120 s). Mainly for slow local/self-hosted backends.
localReasoningEffort:
anyOf:
- type: string
enum:
- none
- low
- medium
- high
- type: "null"
description: "#1126 — reasoning setting of the Local provider entry, sent as `reasoning_effort` (`none` = Off). Null =
Default: the key is not sent."
compatReasoningEffort:
anyOf:
- type: string
enum:
- none
- low
- medium
- high
- type: "null"
description: "#1126 — the same for the OpenAI-compatible gateway entry."
serverProviderHealth:
type: string
enum:
@@ -48587,6 +48646,8 @@ components:
- compatModel
- hasCompatKey
- responseTimeoutSeconds
- localReasoningEffort
- compatReasoningEffort
- serverProviderHealth
- serverProviderOffer
- serverProviderConsent