@@ -1,8 +1,11 @@
1package agent
1package agent
@@ -24,6 +27,7 @@ import (
24 "github.com/charmbracelet/fantasy/openai"
27 "github.com/charmbracelet/fantasy/openai"
25 "github.com/charmbracelet/fantasy/openaicompat"
28 "github.com/charmbracelet/fantasy/openaicompat"
26 "github.com/charmbracelet/fantasy/openrouter"
29 "github.com/charmbracelet/fantasy/openrouter"
30+ "github.com/qjebbs/go-jsons"
29type Coordinator interface {
33type Coordinator interface {
@@ -103,46 +107,79 @@ func (c *coordinator) Run(ctx context.Context, sessionID string, prompt string,
103 attachments = nil
107 attachments = nil
110+ mergedOptions, temp, topP, topK, freqPenalty, presPenalty := mergeCallOptions(model)
106 return c.currentAgent.Run(ctx, SessionAgentCall{
112 return c.currentAgent.Run(ctx, SessionAgentCall{
107 SessionID: sessionID,
113 SessionID: sessionID,
108 Prompt: prompt,
114 Prompt: prompt,
109 Attachments: attachments,
115 Attachments: attachments,
110 MaxOutputTokens: maxTokens,
116 MaxOutputTokens: maxTokens,
111− ProviderOptions: c.getProviderOptions(model),
117+ ProviderOptions: mergedOptions,
112− Temperature: model.ModelCfg.Temperature,
118+ Temperature: temp,
113− TopP: model.ModelCfg.TopP,
119+ TopP: topP,
114− TopK: model.ModelCfg.TopK,
120+ TopK: topK,
115− FrequencyPenalty: model.ModelCfg.FrequencyPenalty,
121+ FrequencyPenalty: freqPenalty,
116− PresencePenalty: model.ModelCfg.PresencePenalty,
122+ PresencePenalty: presPenalty,
120−func (c *coordinator) getProviderOptions(model Model) ai.ProviderOptions {
126+func getProviderOptions(model Model) ai.ProviderOptions {
121 options := ai.ProviderOptions{}
127 options := ai.ProviderOptions{}
132+ if model.ModelCfg.ProviderOptions != nil {
133+ data, err := json.Marshal(model.ModelCfg.ProviderOptions)
135+ cfgOpts = string(data)
139+ if model.CatwalkCfg.Options.ProviderOptions != nil {
140+ data, err := json.Marshal(model.CatwalkCfg.Options.ProviderOptions)
142+ catwalkOpts = string(data)
146+ got, err := jsons.Merge([]string{catwalkOpts, cfgOpts})
148+ slog.Error("Could not merge call config", "err", err)
152+ mergedOptions := make(map[string]any)
154+ err = json.Unmarshal([]byte(got), &mergedOptions)
156+ slog.Error("Could not create config for call", "err", err)
123 switch model.Model.Provider() {
160 switch model.Model.Provider() {
124 case openai.Name:
161 case openai.Name:
125− parsed, err := openai.ParseOptions(model.ModelCfg.ProviderOptions)
162+ parsed, err := openai.ParseOptions(mergedOptions)
126 if err == nil {
163 if err == nil {
127 options[openai.Name] = parsed
164 options[openai.Name] = parsed
129 case anthropic.Name:
166 case anthropic.Name:
130− parsed, err := anthropic.ParseOptions(model.ModelCfg.ProviderOptions)
167+ parsed, err := anthropic.ParseOptions(mergedOptions)
131 if err == nil {
168 if err == nil {
132 options[anthropic.Name] = parsed
169 options[anthropic.Name] = parsed
134 case openrouter.Name:
171 case openrouter.Name:
135− parsed, err := openrouter.ParseOptions(model.ModelCfg.ProviderOptions)
172+ parsed, err := openrouter.ParseOptions(mergedOptions)
136 if err == nil {
173 if err == nil {
137 options[openrouter.Name] = parsed
174 options[openrouter.Name] = parsed
139 case google.Name:
176 case google.Name:
140− parsed, err := google.ParseOptions(model.ModelCfg.ProviderOptions)
177+ parsed, err := google.ParseOptions(mergedOptions)
141 if err == nil {
178 if err == nil {
142 options[google.Name] = parsed
179 options[google.Name] = parsed
144 case openaicompat.Name:
181 case openaicompat.Name:
145− parsed, err := openaicompat.ParseOptions(model.ModelCfg.ProviderOptions)
182+ parsed, err := openaicompat.ParseOptions(mergedOptions)
146 if err == nil {
183 if err == nil {
147 options[openaicompat.Name] = parsed
184 options[openaicompat.Name] = parsed
@@ -151,6 +188,16 @@ func (c *coordinator) getProviderOptions(model Model) ai.ProviderOptions {
151 return options
188 return options
191+func mergeCallOptions(model Model) (ai.ProviderOptions, *float64, *float64, *int64, *float64, *float64) {
192+ modelOptions := getProviderOptions(model)
193+ temp := cmp.Or(model.ModelCfg.Temperature, model.CatwalkCfg.Options.Temperature)
194+ topP := cmp.Or(model.ModelCfg.TopP, model.CatwalkCfg.Options.TopP)
195+ topK := cmp.Or(model.ModelCfg.TopK, model.CatwalkCfg.Options.TopK)
196+ freqPenalty := cmp.Or(model.ModelCfg.FrequencyPenalty, model.CatwalkCfg.Options.FrequencyPenalty)
197+ presPenalty := cmp.Or(model.ModelCfg.PresencePenalty, model.CatwalkCfg.Options.PresencePenalty)
198+ return modelOptions, temp, topP, topK, freqPenalty, presPenalty
154func (c *coordinator) buildAgent(prompt *prompt.Prompt, agent config.Agent) (SessionAgent, error) {
201func (c *coordinator) buildAgent(prompt *prompt.Prompt, agent config.Agent) (SessionAgent, error) {
155 large, small, err := c.buildAgentModels()
202 large, small, err := c.buildAgentModels()
156 if err != nil {
203 if err != nil {