thinking

package
v6.7.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 16, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package thinking provides unified thinking configuration processing.

Package thinking provides unified thinking configuration processing logic.

Package thinking provides unified thinking configuration processing.

Package thinking provides unified thinking configuration processing.

This file implements suffix parsing functionality for extracting thinking configuration from model names in the format model(value).

Package thinking provides unified thinking configuration processing.

This package offers a unified interface for parsing, validating, and applying thinking configurations across various AI providers (Claude, Gemini, OpenAI, iFlow).

Package thinking provides unified thinking configuration processing logic.

Index

Constants

View Source
const (
	// ThresholdMinimal is the upper bound for "minimal" level (1-512)
	ThresholdMinimal = 512
	// ThresholdLow is the upper bound for "low" level (513-1024)
	ThresholdLow = 1024
	// ThresholdMedium is the upper bound for "medium" level (1025-8192)
	ThresholdMedium = 8192
	// ThresholdHigh is the upper bound for "high" level (8193-24576)
	ThresholdHigh = 24576
)

BudgetThreshold constants define the upper bounds for each thinking level. These are used by ConvertBudgetToLevel for range-based mapping.

Variables

This section is empty.

Functions

func ApplyThinking

func ApplyThinking(body []byte, model string, provider string) ([]byte, error)

ApplyThinking applies thinking configuration to a request body.

This is the unified entry point for all providers. It follows the processing order defined in FR25: route check → model capability query → config extraction → validation → application.

Suffix Priority: When the model name includes a thinking suffix (e.g., "gemini-2.5-pro(8192)"), the suffix configuration takes priority over any thinking parameters in the request body. This enables users to override thinking settings via the model name without modifying their request payload.

Parameters:

  • body: Original request body JSON
  • model: Model name, optionally with thinking suffix (e.g., "claude-sonnet-4-5(16384)")
  • provider: Provider name (gemini, gemini-cli, antigravity, claude, openai, codex, iflow)

Returns:

  • Modified request body JSON with thinking configuration applied
  • Error if validation fails (ThinkingError). On error, the original body is returned (not nil) to enable defensive programming patterns.

Passthrough behavior (returns original body without error):

  • Unknown provider (not in providerAppliers map)
  • modelInfo.Thinking is nil (model doesn't support thinking)

Note: Unknown models (modelInfo is nil) are treated as user-defined models: we skip validation and still apply the thinking config so the upstream can validate it.

Example:

// With suffix - suffix config takes priority
result, err := thinking.ApplyThinking(body, "gemini-2.5-pro(8192)", "gemini")

// Without suffix - uses body config
result, err := thinking.ApplyThinking(body, "gemini-2.5-pro", "gemini")

func ClampBudget

func ClampBudget(value int, modelInfo *registry.ModelInfo, provider string) int

ClampBudget clamps a budget value to the model's supported range.

Logging:

  • Warn when value=0 but ZeroAllowed=false
  • Debug when value is clamped to min/max

Fields: provider, model, original_value, clamped_to, min, max

func ConvertBudgetToLevel

func ConvertBudgetToLevel(budget int) (string, bool)

ConvertBudgetToLevel converts a budget value to the nearest thinking level.

This is a semantic conversion that maps numeric budgets to discrete levels. Uses threshold-based mapping for range conversion.

Budget → Level thresholds:

  • -1 → auto
  • 0 → none
  • 1-512 → minimal
  • 513-1024 → low
  • 1025-8192 → medium
  • 8193-24576 → high
  • 24577+ → xhigh

Returns:

  • level: The converted thinking level string
  • ok: true if budget is valid, false for invalid negatives (< -1)

func ConvertLevelToBudget

func ConvertLevelToBudget(level string) (int, bool)

ConvertLevelToBudget converts a thinking level to a budget value.

This is a semantic conversion that maps discrete levels to numeric budgets. Level matching is case-insensitive.

Level → Budget mapping:

  • none → 0
  • auto → -1
  • minimal → 512
  • low → 1024
  • medium → 8192
  • high → 24576
  • xhigh → 32768

Returns:

  • budget: The converted budget value
  • ok: true if level is valid, false otherwise

func GetThinkingText

func GetThinkingText(part gjson.Result) string

GetThinkingText extracts the thinking text from a content part. Handles various formats: - Simple string: { "thinking": "text" } or { "text": "text" } - Wrapped object: { "thinking": { "text": "text", "cache_control": {...} } } - Gemini-style: { "thought": true, "text": "text" } Returns the extracted text string.

func IsUserDefinedModel

func IsUserDefinedModel(modelInfo *registry.ModelInfo) bool

IsUserDefinedModel reports whether the model is a user-defined model that should have thinking configuration passed through without validation.

User-defined models are configured via config file's models[] array (e.g., openai-compatibility.*.models[], *-api-key.models[]). These models are marked with UserDefined=true at registration time.

User-defined models should have their thinking configuration applied directly, letting the upstream service validate the configuration.

func ParseNumericSuffix

func ParseNumericSuffix(rawSuffix string) (budget int, ok bool)

ParseNumericSuffix attempts to parse a raw suffix as a numeric budget value.

This function parses the raw suffix content (from ParseSuffix.RawSuffix) as an integer. Only non-negative integers are considered valid numeric suffixes.

Platform note: The budget value uses Go's int type, which is 32-bit on 32-bit systems and 64-bit on 64-bit systems. Values exceeding the platform's int range will return ok=false.

Leading zeros are accepted: "08192" parses as 8192.

Examples:

  • "8192" -> budget=8192, ok=true
  • "0" -> budget=0, ok=true (represents ModeNone)
  • "08192" -> budget=8192, ok=true (leading zeros accepted)
  • "-1" -> budget=0, ok=false (negative numbers are not valid numeric suffixes)
  • "high" -> budget=0, ok=false (not a number)
  • "9223372036854775808" -> budget=0, ok=false (overflow on 64-bit systems)

For special handling of -1 as auto mode, use ParseSpecialSuffix instead.

func RegisterProvider

func RegisterProvider(name string, applier ProviderApplier)

RegisterProvider registers a provider applier by name.

func StripThinkingConfig

func StripThinkingConfig(body []byte, provider string) []byte

StripThinkingConfig removes thinking configuration fields from request body.

This function is used when a model doesn't support thinking but the request contains thinking configuration. The configuration is silently removed to prevent upstream API errors.

Parameters:

  • body: Original request body JSON
  • provider: Provider name (determines which fields to strip)

Returns:

  • Modified request body JSON with thinking configuration removed
  • Original body is returned unchanged if:
  • body is empty or invalid JSON
  • provider is unknown
  • no thinking configuration found

Types

type ErrorCode

type ErrorCode string

ErrorCode represents the type of thinking configuration error.

const (
	// ErrInvalidSuffix indicates the suffix format cannot be parsed.
	// Example: "model(abc" (missing closing parenthesis)
	ErrInvalidSuffix ErrorCode = "INVALID_SUFFIX"

	// ErrUnknownLevel indicates the level value is not in the valid list.
	// Example: "model(ultra)" where "ultra" is not a valid level
	ErrUnknownLevel ErrorCode = "UNKNOWN_LEVEL"

	// ErrThinkingNotSupported indicates the model does not support thinking.
	// Example: claude-haiku-4-5 does not have thinking capability
	ErrThinkingNotSupported ErrorCode = "THINKING_NOT_SUPPORTED"

	// ErrLevelNotSupported indicates the model does not support level mode.
	// Example: using level with a budget-only model
	ErrLevelNotSupported ErrorCode = "LEVEL_NOT_SUPPORTED"

	// ErrProviderMismatch indicates the provider does not match the model.
	// Example: applying Claude format to a Gemini model
	ErrProviderMismatch ErrorCode = "PROVIDER_MISMATCH"
)

Error codes for thinking configuration processing.

type ModelCapability

type ModelCapability int

ModelCapability describes the thinking format support of a model.

const (
	// CapabilityUnknown indicates modelInfo is nil (passthrough behavior, internal use).
	CapabilityUnknown ModelCapability = iota - 1
	// CapabilityNone indicates model doesn't support thinking (Thinking is nil).
	CapabilityNone
	// CapabilityBudgetOnly indicates the model supports numeric budgets only.
	CapabilityBudgetOnly
	// CapabilityLevelOnly indicates the model supports discrete levels only.
	CapabilityLevelOnly
	// CapabilityHybrid indicates the model supports both budgets and levels.
	CapabilityHybrid
)

type ProviderApplier

type ProviderApplier interface {
	// Apply applies the thinking configuration to the request body.
	//
	// Parameters:
	//   - body: Original request body JSON
	//   - config: Unified thinking configuration
	//   - modelInfo: Model registry information containing ThinkingSupport properties
	//
	// Returns:
	//   - Modified request body JSON
	//   - ThinkingError if the configuration is invalid or unsupported
	Apply(body []byte, config ThinkingConfig, modelInfo *registry.ModelInfo) ([]byte, error)
}

ProviderApplier defines the interface for provider-specific thinking configuration application.

Types implementing this interface are responsible for converting a unified ThinkingConfig into provider-specific format and applying it to the request body.

Implementation requirements:

  • Apply method must be idempotent
  • Must not modify the input config or modelInfo
  • Returns a modified copy of the request body
  • Returns appropriate ThinkingError for unsupported configurations

func GetProviderApplier

func GetProviderApplier(provider string) ProviderApplier

GetProviderApplier returns the ProviderApplier for the given provider name. Returns nil if the provider is not registered.

type SuffixResult

type SuffixResult struct {
	// ModelName is the model name with the suffix removed.
	// If no suffix was found, this equals the original input.
	ModelName string

	// HasSuffix indicates whether a valid suffix was found.
	HasSuffix bool

	// RawSuffix is the content inside the parentheses, without the parentheses.
	// Empty string if HasSuffix is false.
	RawSuffix string
}

SuffixResult represents the result of parsing a model name for thinking suffix.

A thinking suffix is specified in the format model-name(value), where value can be a numeric budget (e.g., "16384") or a level name (e.g., "high").

func ParseSuffix

func ParseSuffix(model string) SuffixResult

ParseSuffix extracts thinking suffix from a model name.

The suffix format is: model-name(value) Examples:

  • "claude-sonnet-4-5(16384)" -> ModelName="claude-sonnet-4-5", RawSuffix="16384"
  • "gpt-5.2(high)" -> ModelName="gpt-5.2", RawSuffix="high"
  • "gemini-2.5-pro" -> ModelName="gemini-2.5-pro", HasSuffix=false

This function only extracts the suffix; it does not validate or interpret the suffix content. Use ParseNumericSuffix, ParseLevelSuffix, etc. for content interpretation.

type ThinkingConfig

type ThinkingConfig struct {
	// Mode specifies the configuration mode
	Mode ThinkingMode
	// Budget is the thinking budget (token count), only effective when Mode is ModeBudget.
	// Special values: 0 means disabled, -1 means automatic
	Budget int
	// Level is the thinking level, only effective when Mode is ModeLevel
	Level ThinkingLevel
}

ThinkingConfig represents a unified thinking configuration.

This struct is used to pass thinking configuration information between components. Depending on Mode, either Budget or Level field is effective:

  • ModeNone: Budget=0, Level is ignored
  • ModeAuto: Budget=-1, Level is ignored
  • ModeBudget: Budget is a positive integer, Level is ignored
  • ModeLevel: Budget is ignored, Level is a valid level

func ValidateConfig

func ValidateConfig(config ThinkingConfig, modelInfo *registry.ModelInfo, provider string) (*ThinkingConfig, error)

ValidateConfig validates a thinking configuration against model capabilities.

This function performs comprehensive validation:

  • Checks if the model supports thinking
  • Auto-converts between Budget and Level formats based on model capability
  • Validates that requested level is in the model's supported levels list
  • Clamps budget values to model's allowed range

Parameters:

  • config: The thinking configuration to validate
  • support: Model's ThinkingSupport properties (nil means no thinking support)

Returns:

  • Normalized ThinkingConfig with clamped values
  • ThinkingError if validation fails (ErrThinkingNotSupported, ErrLevelNotSupported, etc.)

Auto-conversion behavior:

  • Budget-only model + Level config → Level converted to Budget
  • Level-only model + Budget config → Budget converted to Level
  • Hybrid model → preserve original format

type ThinkingError

type ThinkingError struct {
	// Code is the machine-readable error code
	Code ErrorCode
	// Message is the human-readable error description.
	// Should be lowercase, no trailing period, with context if applicable.
	Message string
	// Model is the model name related to this error (optional)
	Model string
	// Details contains additional context information (optional)
	Details map[string]interface{}
}

ThinkingError represents an error that occurred during thinking configuration processing.

This error type provides structured information about the error, including:

  • Code: A machine-readable error code for programmatic handling
  • Message: A human-readable description of the error
  • Model: The model name related to the error (optional)
  • Details: Additional context information (optional)

func NewThinkingError

func NewThinkingError(code ErrorCode, message string) *ThinkingError

NewThinkingError creates a new ThinkingError with the given code and message.

func NewThinkingErrorWithModel

func NewThinkingErrorWithModel(code ErrorCode, message, model string) *ThinkingError

NewThinkingErrorWithModel creates a new ThinkingError with model context.

func (*ThinkingError) Error

func (e *ThinkingError) Error() string

Error implements the error interface. Returns the message directly without code prefix. Use Code field for programmatic error handling.

func (*ThinkingError) StatusCode

func (e *ThinkingError) StatusCode() int

StatusCode implements a portable status code interface for HTTP handlers.

type ThinkingLevel

type ThinkingLevel string

ThinkingLevel represents a discrete thinking level.

const (
	// LevelNone disables thinking
	LevelNone ThinkingLevel = "none"
	// LevelAuto enables automatic/dynamic thinking
	LevelAuto ThinkingLevel = "auto"
	// LevelMinimal sets minimal thinking effort
	LevelMinimal ThinkingLevel = "minimal"
	// LevelLow sets low thinking effort
	LevelLow ThinkingLevel = "low"
	// LevelMedium sets medium thinking effort
	LevelMedium ThinkingLevel = "medium"
	// LevelHigh sets high thinking effort
	LevelHigh ThinkingLevel = "high"
	// LevelXHigh sets extra-high thinking effort
	LevelXHigh ThinkingLevel = "xhigh"
)

func ParseLevelSuffix

func ParseLevelSuffix(rawSuffix string) (level ThinkingLevel, ok bool)

ParseLevelSuffix attempts to parse a raw suffix as a discrete thinking level.

This function parses the raw suffix content (from ParseSuffix.RawSuffix) as a level. Only discrete effort levels are valid: minimal, low, medium, high, xhigh. Level matching is case-insensitive.

Special values (none, auto) are NOT handled by this function; use ParseSpecialSuffix instead. This separation allows callers to prioritize special value handling.

Examples:

  • "high" -> level=LevelHigh, ok=true
  • "HIGH" -> level=LevelHigh, ok=true (case insensitive)
  • "medium" -> level=LevelMedium, ok=true
  • "none" -> level="", ok=false (special value, use ParseSpecialSuffix)
  • "auto" -> level="", ok=false (special value, use ParseSpecialSuffix)
  • "8192" -> level="", ok=false (numeric, use ParseNumericSuffix)
  • "ultra" -> level="", ok=false (unknown level)

type ThinkingMode

type ThinkingMode int

ThinkingMode represents the type of thinking configuration mode.

const (
	// ModeBudget indicates using a numeric budget (corresponds to suffix "(1000)" etc.)
	ModeBudget ThinkingMode = iota
	// ModeLevel indicates using a discrete level (corresponds to suffix "(high)" etc.)
	ModeLevel
	// ModeNone indicates thinking is disabled (corresponds to suffix "(none)" or budget=0)
	ModeNone
	// ModeAuto indicates automatic/dynamic thinking (corresponds to suffix "(auto)" or budget=-1)
	ModeAuto
)

func ParseSpecialSuffix

func ParseSpecialSuffix(rawSuffix string) (mode ThinkingMode, ok bool)

ParseSpecialSuffix attempts to parse a raw suffix as a special thinking mode value.

This function handles special strings that represent a change in thinking mode:

  • "none" -> ModeNone (disables thinking)
  • "auto" -> ModeAuto (automatic/dynamic thinking)
  • "-1" -> ModeAuto (numeric representation of auto mode)

String values are case-insensitive.

func (ThinkingMode) String

func (m ThinkingMode) String() string

String returns the string representation of ThinkingMode.

Directories

Path Synopsis
provider
antigravity
Package antigravity implements thinking configuration for Antigravity API format.
Package antigravity implements thinking configuration for Antigravity API format.
claude
Package claude implements thinking configuration scaffolding for Claude models.
Package claude implements thinking configuration scaffolding for Claude models.
codex
Package codex implements thinking configuration for Codex (OpenAI Responses API) models.
Package codex implements thinking configuration for Codex (OpenAI Responses API) models.
gemini
Package gemini implements thinking configuration for Gemini models.
Package gemini implements thinking configuration for Gemini models.
geminicli
Package geminicli implements thinking configuration for Gemini CLI API format.
Package geminicli implements thinking configuration for Gemini CLI API format.
iflow
Package iflow implements thinking configuration for iFlow models (GLM, MiniMax).
Package iflow implements thinking configuration for iFlow models (GLM, MiniMax).
openai
Package openai implements thinking configuration for OpenAI/Codex models.
Package openai implements thinking configuration for OpenAI/Codex models.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL