mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
e7e21df354
* fix(agent): honor explicit thinking off * fix(agent): address thinking off lint failures * Clarify unset thinking level display * fix ci
130 lines
3.4 KiB
Go
130 lines
3.4 KiB
Go
package agent
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/sipeed/picoclaw/pkg/config"
|
|
"github.com/sipeed/picoclaw/pkg/logger"
|
|
"github.com/sipeed/picoclaw/pkg/providers"
|
|
)
|
|
|
|
// ThinkingLevel controls how the provider sends thinking parameters.
|
|
//
|
|
// - "adaptive": sends {thinking: {type: "adaptive"}} + output_config.effort (Claude 4.6+)
|
|
// - "low"/"medium"/"high"/"xhigh": sends {thinking: {type: "enabled", budget_tokens: N}} (all models)
|
|
// - "off": disables thinking
|
|
type ThinkingLevel string
|
|
|
|
const (
|
|
ThinkingOff ThinkingLevel = "off"
|
|
ThinkingLow ThinkingLevel = "low"
|
|
ThinkingMedium ThinkingLevel = "medium"
|
|
ThinkingHigh ThinkingLevel = "high"
|
|
ThinkingXHigh ThinkingLevel = "xhigh"
|
|
ThinkingAdaptive ThinkingLevel = "adaptive"
|
|
)
|
|
|
|
// parseThinkingLevel normalizes a config string to a ThinkingLevel.
|
|
// Case-insensitive and whitespace-tolerant for user-facing config values.
|
|
// Returns ThinkingOff for unknown or empty values.
|
|
func parseThinkingLevel(level string) ThinkingLevel {
|
|
switch strings.ToLower(strings.TrimSpace(level)) {
|
|
case "adaptive":
|
|
return ThinkingAdaptive
|
|
case "low":
|
|
return ThinkingLow
|
|
case "medium":
|
|
return ThinkingMedium
|
|
case "high":
|
|
return ThinkingHigh
|
|
case "xhigh":
|
|
return ThinkingXHigh
|
|
default:
|
|
return ThinkingOff
|
|
}
|
|
}
|
|
|
|
func isConfiguredThinkingLevel(level string) bool {
|
|
switch strings.ToLower(strings.TrimSpace(level)) {
|
|
case "off", "low", "medium", "high", "xhigh", "adaptive":
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
type thinkingSettings struct {
|
|
level ThinkingLevel
|
|
configured bool
|
|
}
|
|
|
|
func thinkingSettingsFromModelConfig(mc *config.ModelConfig) thinkingSettings {
|
|
if mc == nil || !isConfiguredThinkingLevel(mc.ThinkingLevel) {
|
|
return thinkingSettings{}
|
|
}
|
|
return thinkingSettings{
|
|
level: parseThinkingLevel(mc.ThinkingLevel),
|
|
configured: true,
|
|
}
|
|
}
|
|
|
|
func activeThinkingSettings(agent *AgentInstance, modelCfg *config.ModelConfig) thinkingSettings {
|
|
if settings := thinkingSettingsFromModelConfig(modelCfg); settings.configured {
|
|
return settings
|
|
}
|
|
if modelCfg == nil && agent != nil {
|
|
return thinkingSettings{
|
|
level: agent.ThinkingLevel,
|
|
configured: agent.ThinkingLevelConfigured,
|
|
}
|
|
}
|
|
return thinkingSettings{}
|
|
}
|
|
|
|
func applyThinkingOption(
|
|
opts map[string]any,
|
|
provider providers.LLMProvider,
|
|
settings thinkingSettings,
|
|
warnUnsupported bool,
|
|
agentID string,
|
|
) {
|
|
if opts == nil || !settings.configured {
|
|
return
|
|
}
|
|
if settings.level == ThinkingOff {
|
|
opts["thinking_level"] = string(settings.level)
|
|
return
|
|
}
|
|
if tc, ok := provider.(providers.ThinkingCapable); ok && tc.SupportsThinking() {
|
|
opts["thinking_level"] = string(settings.level)
|
|
return
|
|
}
|
|
if warnUnsupported {
|
|
logger.WarnCF("agent", "thinking_level is set but current provider does not support it, ignoring",
|
|
map[string]any{"agent_id": agentID, "thinking_level": string(settings.level)})
|
|
}
|
|
}
|
|
|
|
func applyTurnThinkingOptions(
|
|
exec *turnExecution,
|
|
agent *AgentInstance,
|
|
provider providers.LLMProvider,
|
|
warnUnsupported bool,
|
|
) {
|
|
if exec == nil || exec.llmOpts == nil {
|
|
return
|
|
}
|
|
delete(exec.llmOpts, "thinking_level")
|
|
settings := activeThinkingSettings(agent, exec.activeModelConfig)
|
|
agentID := ""
|
|
if agent != nil {
|
|
agentID = agent.ID
|
|
}
|
|
applyThinkingOption(exec.llmOpts, provider, settings, warnUnsupported, agentID)
|
|
exec.suppressReasoning = shouldSuppressReasoningFor(settings)
|
|
}
|
|
|
|
func shouldSuppressReasoningFor(settings thinkingSettings) bool {
|
|
return settings.configured && settings.level == ThinkingOff
|
|
}
|