Files
goclaw/internal/providers/reasoning_observation.go
Kai (Tam Nhu) Tranandviettranx 3ca3bb2062 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>
2026-03-31 07:56:01 +07:00

36 lines
866 B
Go

package providers
import (
"context"
"encoding/json"
)
const ReasoningMetadataKey = "reasoning"
type reasoningDecisionKey struct{}
func WithReasoningDecision(ctx context.Context, decision ReasoningDecision) context.Context {
return context.WithValue(ctx, reasoningDecisionKey{}, &decision)
}
func ReasoningDecisionFromContext(ctx context.Context) *ReasoningDecision {
decision, _ := ctx.Value(reasoningDecisionKey{}).(*ReasoningDecision)
return decision
}
func MergeReasoningMetadata(existing json.RawMessage, decision ReasoningDecision) json.RawMessage {
if !decision.HasObservation() {
return existing
}
payload := map[string]any{}
if len(existing) > 0 {
_ = json.Unmarshal(existing, &payload)
}
payload[ReasoningMetadataKey] = decision
data, err := json.Marshal(payload)
if err != nil {
return existing
}
return json.RawMessage(data)
}