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
- func ApplyGeminiBudgetFormat(body []byte, config Config, budget int, prefix string) ([]byte, error)
- func ApplyGeminiCompatible(body []byte, config Config, levelFn func([]byte, Config) ([]byte, error), ...) ([]byte, error)
- func ApplyGeminiLevelFormat(body []byte, config Config, prefix string) ([]byte, error)
- func ApplyReasoningEffort(body []byte, config Config, modelInfo *registry.ModelInfo, fieldPath string) ([]byte, error)
- func ApplyThinking(body []byte, model string, fromFormat string, toFormat string, ...) ([]byte, error)
- func ConvertBudgetToLevel(budget int) (string, bool)
- func ConvertLevelToBudget(level string) (int, bool)
- func GetThinkingText(part gjson.Result) string
- func HasContext1MTag(model string) bool
- func HasLevel(levels []string, target string) bool
- func IsUserDefinedModel(modelInfo *registry.ModelInfo) bool
- func MapToClaudeEffort(level string, supportsMax bool) (string, bool)
- func PreserveRequestModelDecorations(resolved, requested string) string
- func RegisterProvider(name string, applier ProviderApplier)
- func ValidateGeminiPreconditions(body []byte, config Config) ([]byte, bool)
- type Config
- type Error
- type Level
- type ProviderApplier
- type SuffixResult
Constants ¶
const ( GeminiDirectPrefix = "generationConfig.thinkingConfig" GeminiCLIPrefix = "request.generationConfig.thinkingConfig" )
Gemini-family path prefixes for thinkingConfig.
const ( OpenAIEffortField = "reasoning_effort" CodexEffortField = "reasoning.effort" )
Reasoning effort field paths for OpenAI-family providers.
const ( // ModeBudget indicates using a numeric budget (corresponds to suffix "(1000)" etc.) ModeBudget mode = 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 )
Variables ¶
This section is empty.
Functions ¶
func ApplyGeminiBudgetFormat ¶
ApplyGeminiBudgetFormat applies budget-based thinking configuration using the given JSON path prefix. Used by gemini, gemini-cli, and antigravity providers which share identical logic but differ in JSON paths. The budget parameter allows callers to pre-process the budget (e.g., antigravity's Claude normalization).
func ApplyGeminiCompatible ¶
func ApplyGeminiCompatible( body []byte, config Config, levelFn func([]byte, Config) ([]byte, error), budgetFn func([]byte, Config) ([]byte, error), ) ([]byte, error)
ApplyGeminiCompatible applies thinking configuration for user-defined models using the given JSON path prefix and format applier functions. This handles the mode routing logic shared across gemini-family providers.
func ApplyGeminiLevelFormat ¶
ApplyGeminiLevelFormat applies level-based thinking configuration using the given JSON path prefix. Used by gemini, gemini-cli, and antigravity providers which share identical logic but differ in JSON paths.
func ApplyReasoningEffort ¶
func ApplyReasoningEffort(body []byte, config Config, modelInfo *registry.ModelInfo, fieldPath string) ([]byte, error)
ApplyReasoningEffort applies thinking configuration using the reasoning effort format. Used by openai and codex providers which share identical logic but differ in JSON field paths.
func ApplyThinking ¶
func ApplyThinking(body []byte, model string, fromFormat string, toFormat string, providerKey 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)")
- fromFormat: Source request format (e.g., openai, codex, gemini)
- toFormat: Target provider format for the request body (gemini, gemini-cli, antigravity, claude, openai, codex, iflow)
- providerKey: Provider identifier used for registry model lookups (may differ from toFormat, e.g., openrouter -> openai)
Returns:
- Modified request body JSON with thinking configuration applied
- Error if validation fails (Error). 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", "gemini", "gemini") // Without suffix - uses body config result, err := thinking.ApplyThinking(body, "gemini-2.5-pro", "gemini", "gemini", "gemini")
func ConvertBudgetToLevel ¶
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 ¶
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 ¶
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 HasContext1MTag ¶
func HasLevel ¶
HasLevel reports whether the given target level exists in the levels slice. Matching is case-insensitive with leading/trailing whitespace trimmed.
func IsUserDefinedModel ¶
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 MapToClaudeEffort ¶
MapToClaudeEffort maps a generic thinking level string to a Claude adaptive thinking effort value (low/medium/high/max).
supportsMax indicates whether the target model supports "max" effort. Returns the mapped effort and true if the level is valid, or ("", false) otherwise.
func RegisterProvider ¶
func RegisterProvider(name string, applier ProviderApplier)
RegisterProvider registers a provider applier by name.
Types ¶
type Config ¶
type Config struct {
// Mode specifies the configuration mode
Mode mode
// 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 Level
}
Config 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
type Error ¶
type Error 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]any
}
Error 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 (*Error) Error ¶
Error implements the error interface. Returns the message directly without code prefix. Use Code field for programmatic error handling.
func (*Error) StatusCode ¶
StatusCode implements a portable status code interface for HTTP handlers.
type Level ¶
type Level string
Level represents a discrete thinking level.
const ( // LevelNone disables thinking LevelNone Level = "none" // LevelAuto enables automatic/dynamic thinking LevelAuto Level = "auto" // LevelHigh sets high thinking effort LevelHigh Level = "high" // LevelXHigh sets extra-high thinking effort LevelXHigh Level = "xhigh" // LevelMax sets maximum thinking effort LevelMax Level = "max" )
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
// - Error if the configuration is invalid or unsupported
Apply(body []byte, config Config, 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 Config 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 Error for unsupported configurations
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.
Source Files
¶
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.
|
Package iflow implements thinking configuration for iFlow models. |
|
kimi
Package kimi implements thinking configuration for Kimi (Moonshot AI) models.
|
Package kimi implements thinking configuration for Kimi (Moonshot AI) models. |
|
openai
Package openai implements thinking configuration for OpenAI/Codex models.
|
Package openai implements thinking configuration for OpenAI/Codex models. |