feat: add capability-aware reasoning effort controls (#593)

* feat(reasoning): add capability-aware effort resolution

- resolve requested reasoning levels against exact model capabilities

- persist requested effort on agents and expose effective effort in traces

- add backend tests for provider models, agent store, and resolution logic

Refs #591

* feat(ui): gate reasoning controls by model capabilities

- only show supported reasoning levels when provider model metadata is available

- preserve expert reasoning selections during async model loading

- surface effective reasoning details in trace dialogs and localized copy

Refs #591

* docs(api): document capability-aware reasoning controls

- describe exact-match capability lookup and downgrade behavior

- update provider model metadata and trace response documentation

- refresh the generated OpenAPI spec for the new reasoning fields

Refs #591

* feat: add provider-first reasoning controls

* docs: refresh PR 593 UI evidence callouts

* refactor: deduplicate reasoning normalize functions and remove PR evidence

- Export NormalizeReasoningEffort/NormalizeReasoningFallback from providers
  package; store package now delegates instead of duplicating
- Store reasoning fallback constants alias providers canonical definitions
- Export deriveLegacyThinkingLevel from types/provider.ts; remove local
  copies from agent-advanced-dialog and provider-overview
- Remove unused _providerType param from useProviderModels hook
- Fix reasoning debug log to fire for all cases with a reason (not just
  non-off efforts)
- Remove docs/pr-593-evidence/ binary screenshots from repo

---------

Co-authored-by: viettranx <viettranx@gmail.com>
This commit is contained in:
Kai (Tam Nhu) Tranandviettranx authored and GitHub committed 2026-03-31 07:56:01 +07:00
1 parent 1dee22aeb7
commit 3ca3bb2062
41 files changed
+2354 -213

No files matched your search

+82 -1
View File
@@ -185,6 +185,55 @@ Provider-level defaults example:
}
```
### Provider reasoning defaults in `settings`
Providers can store the reusable default reasoning policy in `settings.reasoning_defaults`.
```json
{
"name": "openai-codex",
"provider_type": "chatgpt_oauth",
"settings": {
"reasoning_defaults": {
"effort": "high",
"fallback": "provider_default"
}
}
}
```
Rules:
- these defaults are provider-owned and apply to any agent that inherits reasoning from this provider
- the final runtime effort is still normalized against the agent's selected model capabilities
- if no provider default is saved, inherit mode resolves to reasoning `off`
### Agent reasoning policy in `other_config`
Agents can now store capability-aware GPT-5/Codex reasoning intent under `other_config.reasoning`.
```json
{
"provider": "openai-codex",
"model": "gpt-5.4",
"other_config": {
"reasoning": {
"override_mode": "inherit"
}
}
}
```
Rules:
- `reasoning.override_mode` supports `inherit|custom`
- `override_mode: "inherit"` tells the agent to follow `settings.reasoning_defaults`
- `override_mode: "custom"` stores an agent-local override; the dashboard also writes a derived `thinking_level` shim for rollback safety
- `thinking_level` remains the coarse compatibility shim: `off|low|medium|high`
- `reasoning.effort` supports `off|auto|none|minimal|low|medium|high|xhigh`
- `reasoning.fallback` supports `downgrade|off|provider_default`
- existing `reasoning` payloads without `override_mode` continue to behave as custom overrides
- unset reasoning resolves to `off`
- the runtime may normalize unsupported efforts, and the actual decision is surfaced in trace span metadata
### Codex Pool Activity
| Method | Path | Description |
@@ -273,11 +322,43 @@ LLM provider management. API keys are encrypted with AES-256-GCM in the database
| Method | Path | Description |
|--------|------|-------------|
| `POST` | `/v1/providers/{id}/verify` | Test provider+model with minimal LLM call |
| `GET` | `/v1/providers/{id}/models` | Proxy to upstream provider model list |
| `GET` | `/v1/providers/{id}/models` | List models plus any known reasoning capability metadata |
| `GET` | `/v1/providers/claude-cli/auth-status` | Check Claude CLI login status |
**Supported types:** `anthropic_native`, `openai_compat`, `chatgpt_oauth`, `gemini_native`, `dashscope`, `bailian`, `minimax`, `claude_cli`, `acp`
Example response:
```json
{
"models": [
{
"id": "gpt-5.4",
"name": "GPT-5.4",
"reasoning": {
"levels": ["none", "low", "medium", "high", "xhigh"],
"default_effort": "none"
}
},
{
"id": "custom-model",
"name": "custom-model"
}
],
"reasoning_defaults": {
"effort": "high",
"fallback": "provider_default"
}
}
```
Notes:
- `chatgpt_oauth` providers return a backend-owned model list because OAuth tokens cannot rely on `/v1/models`
- `reasoning_defaults` is returned only when the provider has saved defaults and at least one returned model exposes reasoning capability metadata
- unknown models remain usable and simply omit the `reasoning` field
- the web UI uses this endpoint as the source of truth for provider-first reasoning controls
- when upstream model discovery fails, the endpoint returns an empty `models` array instead of a hard error
---
## 7. Sessions