@@ -361,11 +361,39 @@ func getProviderOptions(model Model, providerCfg config.ProviderConfig) fantasy.
361361 if err == nil {
362362 options[google.Name] = parsed
363363 }
364− case openaicompat.Name:
364+ case openaicompat.Name, hyper.Name:
365365 _, hasReasoningEffort := mergedOptions["reasoning_effort"]
366366 if !hasReasoningEffort && model.ModelCfg.ReasoningEffort != "" {
367367 mergedOptions["reasoning_effort"] = model.ModelCfg.ReasoningEffort
368368 }
369+
370+ extraBody := make(map[string]any)
371+
372+ // "reasoning effort" is a standard OpenAI field, but "thinking" is not.
373+ // Setting it in the right way for each provider.
374+ // TODO: Abstract this in Fantasy somehow?
375+ // TODO: Allow custom providers to specify how to set this?
376+ switch providerCfg.ID {
377+ case hyper.Name:
378+ extraBody["thinking"] = model.ModelCfg.Think
379+ case string(catwalk.InferenceProviderIoNet):
380+ extraBody["chat_template_kwargs"] = map[string]any{
381+ "thinking": model.ModelCfg.Think,
382+ }
383+ case string(catwalk.InferenceProviderZAI):
384+ if model.ModelCfg.Think {
385+ extraBody["thinking"] = map[string]any{
386+ "type": "enabled",
387+ }
388+ } else {
389+ extraBody["thinking"] = map[string]any{
390+ "type": "disabled",
391+ }
392+ }
393+ }
394+
395+ mergedOptions["extra_body"] = extraBody
396+
369397 parsed, err := openaicompat.ParseOptions(mergedOptions)
370398 if err == nil {
371399 options[openaicompat.Name] = parsed