Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ require (
mvdan.cc/sh/v3 v3.12.1-0.20250902163504-3cf4fd5717a5
)

require (
github.com/anthropics/anthropic-sdk-go v1.14.0 // indirect
google.golang.org/genai v1.32.0 // indirect
)

require (
cloud.google.com/go v0.116.0 // indirect
cloud.google.com/go/auth v0.17.0 // indirect
Expand All @@ -58,7 +63,6 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
github.com/andybalholm/cascadia v1.3.3 // indirect
github.com/anthropics/anthropic-sdk-go v1.14.0 // indirect
github.com/aws/aws-sdk-go-v2 v1.39.3 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 // indirect
github.com/aws/aws-sdk-go-v2/config v1.27.27 // indirect
Expand Down Expand Up @@ -158,7 +162,6 @@ require (
golang.org/x/text v0.30.0
golang.org/x/time v0.12.0 // indirect
google.golang.org/api v0.239.0 // indirect
google.golang.org/genai v1.32.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
google.golang.org/grpc v1.74.2 // indirect
google.golang.org/protobuf v1.36.10 // indirect
Expand Down
21 changes: 21 additions & 0 deletions internal/agent/coordinator.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ func getProviderOptions(model Model, providerCfg config.ProviderConfig) fantasy.
cfgOpts := []byte("{}")
providerCfgOpts := []byte("{}")
catwalkOpts := []byte("{}")
extraBodyOpts := []byte("{}")

if model.ModelCfg.ProviderOptions != nil {
data, err := json.Marshal(model.ModelCfg.ProviderOptions)
Expand All @@ -164,9 +165,29 @@ func getProviderOptions(model Model, providerCfg config.ProviderConfig) fantasy.
}
}

// Extract extra_fields from provider_options and apply via Fantasy's ExtraFields mechanism
// This is separate from extra_body (which applies at SDK level via WithJSONSet)
// Use provider_options.extra_fields for per-call customization (e.g., Z.AI GLM thinking mode)
if providerCfg.ProviderOptions != nil {
if extraFieldsRaw, hasExtraFields := providerCfg.ProviderOptions["extra_fields"]; hasExtraFields {
if extraFieldsMap, ok := extraFieldsRaw.(map[string]any); ok && len(extraFieldsMap) > 0 {
extraBodyData := map[string]any{
"extra_fields": extraFieldsMap,
}
data, err := json.Marshal(extraBodyData)
if err == nil {
extraBodyOpts = data
} else {
slog.Warn("Failed to marshal extra_fields from provider_options", "error", err)
}
}
}
}

readers := []io.Reader{
bytes.NewReader(catwalkOpts),
bytes.NewReader(providerCfgOpts),
bytes.NewReader(extraBodyOpts),
bytes.NewReader(cfgOpts),
}

Expand Down
35 changes: 34 additions & 1 deletion internal/config/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ func (c *Config) configureProviders(env env.Env, resolver VariableResolver, know
SystemPromptPrefix: config.SystemPromptPrefix,
ExtraHeaders: headers,
ExtraBody: config.ExtraBody,
ProviderOptions: config.ProviderOptions,
ExtraParams: make(map[string]string),
Models: p.Models,
}
Expand Down Expand Up @@ -500,6 +501,21 @@ func (c *Config) configureSelectedModels(knownProviders []catwalk.Provider) erro
large.ReasoningEffort = largeModelSelected.ReasoningEffort
}
large.Think = largeModelSelected.Think
if largeModelSelected.Temperature != nil {
large.Temperature = largeModelSelected.Temperature
}
if largeModelSelected.TopP != nil {
large.TopP = largeModelSelected.TopP
}
if largeModelSelected.TopK != nil {
large.TopK = largeModelSelected.TopK
}
if largeModelSelected.FrequencyPenalty != nil {
large.FrequencyPenalty = largeModelSelected.FrequencyPenalty
}
if largeModelSelected.PresencePenalty != nil {
large.PresencePenalty = largeModelSelected.PresencePenalty
}
}
}
smallModelSelected, smallModelConfigured := c.Models[SelectedModelTypeSmall]
Expand All @@ -525,7 +541,24 @@ func (c *Config) configureSelectedModels(knownProviders []catwalk.Provider) erro
} else {
small.MaxTokens = model.DefaultMaxTokens
}
small.ReasoningEffort = smallModelSelected.ReasoningEffort
if smallModelSelected.ReasoningEffort != "" {
small.ReasoningEffort = smallModelSelected.ReasoningEffort
}
if smallModelSelected.Temperature != nil {
small.Temperature = smallModelSelected.Temperature
}
if smallModelSelected.TopP != nil {
small.TopP = smallModelSelected.TopP
}
if smallModelSelected.TopK != nil {
small.TopK = smallModelSelected.TopK
}
if smallModelSelected.FrequencyPenalty != nil {
small.FrequencyPenalty = smallModelSelected.FrequencyPenalty
}
if smallModelSelected.PresencePenalty != nil {
small.PresencePenalty = smallModelSelected.PresencePenalty
}
small.Think = smallModelSelected.Think
}
}
Expand Down