File size: 4,181 Bytes
bf9e111
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// 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

import "github.com/router-for-me/CLIProxyAPI/v6/internal/registry"

// ThinkingMode represents the type of thinking configuration mode.
type ThinkingMode int

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
)

// String returns the string representation of ThinkingMode.
func (m ThinkingMode) String() string {
	switch m {
	case ModeBudget:
		return "budget"
	case ModeLevel:
		return "level"
	case ModeNone:
		return "none"
	case ModeAuto:
		return "auto"
	default:
		return "unknown"
	}
}

// ThinkingLevel represents a discrete thinking level.
type ThinkingLevel string

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"
)

// 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
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
}

// 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").
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
}

// 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
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)
}