Skip to content

Commit cd1dad9

Browse files
feat: Add ExtraFields support via provider_options complementing extra_body
This change enables passing custom parameters to OpenAI-compatible API providers through Fantasy's ExtraFields mechanism, working alongside Kujtim's SDK-level extra_body support. Key changes: - Extract extra_fields from provider_options (not extra_body) - Apply via Fantasy's ExtraFields (per-call level) - Works alongside extra_body (SDK level) for complementary behavior - Merged with upstream/crush-fantasy parameter update fix This creates two complementary mechanisms: 1. extra_body: SDK-level defaults (Kujtim's approach) - provider-wide 2. provider_options.extra_fields: Fantasy-level per-call (this PR) Example config for Z.AI GLM thinking mode: { "providers": { "z.ai": { "provider_options": { "extra_fields": { "thinking": { "type": "enabled", "budget_tokens": 26214 } } } } } } The extra_fields are passed through Fantasy's ExtraFields to the OpenAI SDK's SetExtraFields() method, enabling per-call customization. Co-authored-by: Kujtim Hoxha <[email protected]>
1 parent 35c05ff commit cd1dad9

File tree

3 files changed

+59
-3
lines changed

3 files changed

+59
-3
lines changed

go.mod

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ require (
5050
mvdan.cc/sh/v3 v3.12.1-0.20250902163504-3cf4fd5717a5
5151
)
5252

53+
require (
54+
github.com/anthropics/anthropic-sdk-go v1.14.0 // indirect
55+
google.golang.org/genai v1.32.0 // indirect
56+
)
57+
5358
require (
5459
cloud.google.com/go v0.116.0 // indirect
5560
cloud.google.com/go/auth v0.17.0 // indirect
@@ -58,7 +63,6 @@ require (
5863
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 // indirect
5964
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
6065
github.com/andybalholm/cascadia v1.3.3 // indirect
61-
github.com/anthropics/anthropic-sdk-go v1.14.0 // indirect
6266
github.com/aws/aws-sdk-go-v2 v1.39.3 // indirect
6367
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 // indirect
6468
github.com/aws/aws-sdk-go-v2/config v1.27.27 // indirect
@@ -158,7 +162,6 @@ require (
158162
golang.org/x/text v0.30.0
159163
golang.org/x/time v0.12.0 // indirect
160164
google.golang.org/api v0.239.0 // indirect
161-
google.golang.org/genai v1.32.0 // indirect
162165
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
163166
google.golang.org/grpc v1.74.2 // indirect
164167
google.golang.org/protobuf v1.36.10 // indirect

internal/agent/coordinator.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ func getProviderOptions(model Model, providerCfg config.ProviderConfig) fantasy.
142142
cfgOpts := []byte("{}")
143143
providerCfgOpts := []byte("{}")
144144
catwalkOpts := []byte("{}")
145+
extraBodyOpts := []byte("{}")
145146

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

168+
// Extract extra_fields from provider_options and apply via Fantasy's ExtraFields mechanism
169+
// This is separate from extra_body (which applies at SDK level via WithJSONSet)
170+
// Use provider_options.extra_fields for per-call customization (e.g., Z.AI GLM thinking mode)
171+
if providerCfg.ProviderOptions != nil {
172+
if extraFieldsRaw, hasExtraFields := providerCfg.ProviderOptions["extra_fields"]; hasExtraFields {
173+
if extraFieldsMap, ok := extraFieldsRaw.(map[string]any); ok && len(extraFieldsMap) > 0 {
174+
extraBodyData := map[string]any{
175+
"extra_fields": extraFieldsMap,
176+
}
177+
data, err := json.Marshal(extraBodyData)
178+
if err == nil {
179+
extraBodyOpts = data
180+
} else {
181+
slog.Warn("Failed to marshal extra_fields from provider_options", "error", err)
182+
}
183+
}
184+
}
185+
}
186+
167187
readers := []io.Reader{
168188
bytes.NewReader(catwalkOpts),
169189
bytes.NewReader(providerCfgOpts),
190+
bytes.NewReader(extraBodyOpts),
170191
bytes.NewReader(cfgOpts),
171192
}
172193

internal/config/load.go

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,21 @@ func (c *Config) configureSelectedModels(knownProviders []catwalk.Provider) erro
500500
large.ReasoningEffort = largeModelSelected.ReasoningEffort
501501
}
502502
large.Think = largeModelSelected.Think
503+
if largeModelSelected.Temperature != nil {
504+
large.Temperature = largeModelSelected.Temperature
505+
}
506+
if largeModelSelected.TopP != nil {
507+
large.TopP = largeModelSelected.TopP
508+
}
509+
if largeModelSelected.TopK != nil {
510+
large.TopK = largeModelSelected.TopK
511+
}
512+
if largeModelSelected.FrequencyPenalty != nil {
513+
large.FrequencyPenalty = largeModelSelected.FrequencyPenalty
514+
}
515+
if largeModelSelected.PresencePenalty != nil {
516+
large.PresencePenalty = largeModelSelected.PresencePenalty
517+
}
503518
}
504519
}
505520
smallModelSelected, smallModelConfigured := c.Models[SelectedModelTypeSmall]
@@ -525,7 +540,24 @@ func (c *Config) configureSelectedModels(knownProviders []catwalk.Provider) erro
525540
} else {
526541
small.MaxTokens = model.DefaultMaxTokens
527542
}
528-
small.ReasoningEffort = smallModelSelected.ReasoningEffort
543+
if smallModelSelected.ReasoningEffort != "" {
544+
small.ReasoningEffort = smallModelSelected.ReasoningEffort
545+
}
546+
if smallModelSelected.Temperature != nil {
547+
small.Temperature = smallModelSelected.Temperature
548+
}
549+
if smallModelSelected.TopP != nil {
550+
small.TopP = smallModelSelected.TopP
551+
}
552+
if smallModelSelected.TopK != nil {
553+
small.TopK = smallModelSelected.TopK
554+
}
555+
if smallModelSelected.FrequencyPenalty != nil {
556+
small.FrequencyPenalty = smallModelSelected.FrequencyPenalty
557+
}
558+
if smallModelSelected.PresencePenalty != nil {
559+
small.PresencePenalty = smallModelSelected.PresencePenalty
560+
}
529561
small.Think = smallModelSelected.Think
530562
}
531563
}

0 commit comments

Comments
 (0)