fix: migrate the openai sdk to our internal fork

Andrey Nering created

The OpenAI SDK has a bug on dealing with SSE events. This was affected
OpenRouter, but we made a workaround for it. See:

* https://github.com/charmbracelet/fantasy/pull/166
* https://github.com/charmbracelet/fantasy/pull/169

We made a fix for the SDK, but it wasn't merged yet:

* https://github.com/openai/openai-go/pull/621

In the meantime, an user reported that Avian has the same issue, but it's
impossible for us to workaround it. Because of this, we had to fork the
SDK. We're pinning the `fantasy` branch from our fork:

* https://github.com/charmbracelet/openai-go/tree/fantasy

Change summary

go.mod                                         | 2 +-
go.sum                                         | 4 ++--
providers/azure/azure.go                       | 4 ++--
providers/openai/call_useragent.go             | 2 +-
providers/openai/error.go                      | 2 +-
providers/openai/language_model.go             | 6 +++---
providers/openai/language_model_hooks.go       | 6 +++---
providers/openai/openai.go                     | 4 ++--
providers/openai/openai_test.go                | 2 +-
providers/openai/provider_options.go           | 2 +-
providers/openai/responses_language_model.go   | 8 ++++----
providers/openaicompat/language_model_hooks.go | 6 +++---
providers/openaicompat/openaicompat.go         | 2 +-
providers/openrouter/language_model_hooks.go   | 4 ++--
providers/openrouter/openrouter.go             | 2 +-
providers/vercel/language_model_hooks.go       | 4 ++--
providers/vercel/vercel.go                     | 2 +-
17 files changed, 31 insertions(+), 31 deletions(-)

Detailed changes

go.mod 🔗

@@ -10,13 +10,13 @@ require (
 	github.com/aws/aws-sdk-go-v2/config v1.32.12
 	github.com/aws/smithy-go v1.24.2
 	github.com/charmbracelet/anthropic-sdk-go v0.0.0-20260223140439-63879b0b8dab
+	github.com/charmbracelet/openai-go v0.0.0-20260319145158-d0740cc34266
 	github.com/charmbracelet/x/exp/slice v0.0.0-20250904123553-b4e2667e5ad5
 	github.com/charmbracelet/x/json v0.2.0
 	github.com/go-viper/mapstructure/v2 v2.5.0
 	github.com/google/uuid v1.6.0
 	github.com/joho/godotenv v1.5.1
 	github.com/kaptinlin/jsonschema v0.7.5
-	github.com/openai/openai-go/v3 v3.28.0
 	github.com/stretchr/testify v1.11.1
 	golang.org/x/oauth2 v0.36.0
 	google.golang.org/genai v1.50.0

go.sum 🔗

@@ -90,6 +90,8 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
 github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/charmbracelet/anthropic-sdk-go v0.0.0-20260223140439-63879b0b8dab h1:J7XQLgl9sefgTnTGrmX3xqvp5o6MCiBzEjGv5igAlc4=
 github.com/charmbracelet/anthropic-sdk-go v0.0.0-20260223140439-63879b0b8dab/go.mod h1:hqlYqR7uPKOKfnNeicUbZp0Ps0GeYFlKYtwh5HGDCx8=
+github.com/charmbracelet/openai-go v0.0.0-20260319145158-d0740cc34266 h1:BW/sZtyd1JyYy0h5adMm3tzpNyL857LWjuTRET6OhpY=
+github.com/charmbracelet/openai-go v0.0.0-20260319145158-d0740cc34266/go.mod h1:1DahUaExbUZx/jD+FNT2PKP4L9rLE5+ZBRuI8mZjd/E=
 github.com/charmbracelet/x/exp/slice v0.0.0-20250904123553-b4e2667e5ad5 h1:DTSZxdV9qQagD4iGcAt9RgaRBZtJl01bfKgdLzUzUPI=
 github.com/charmbracelet/x/exp/slice v0.0.0-20250904123553-b4e2667e5ad5/go.mod h1:vI5nDVMWi6veaYH+0Fmvpbe/+cv/iJfMntdh+N0+Tms=
 github.com/charmbracelet/x/json v0.2.0 h1:DqB+ZGx2h+Z+1s98HOuOyli+i97wsFQIxP2ZQANTPrQ=
@@ -201,8 +203,6 @@ github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus
 github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8=
 github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y=
 github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=
-github.com/openai/openai-go/v3 v3.28.0 h1:2+FfrCVMdGXSQrBv1tLWtokm+BU7+3hJ/8rAHPQ63KM=
-github.com/openai/openai-go/v3 v3.28.0/go.mod h1:cdufnVK14cWcT9qA1rRtrXx4FTRsgbDPW7Ia7SS5cZo=
 github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
 github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=

providers/azure/azure.go 🔗

@@ -8,8 +8,8 @@ import (
 
 	"charm.land/fantasy"
 	"charm.land/fantasy/providers/openai"
-	"github.com/openai/openai-go/v3/azure"
-	"github.com/openai/openai-go/v3/option"
+	"github.com/charmbracelet/openai-go/azure"
+	"github.com/charmbracelet/openai-go/option"
 )
 
 type options struct {

providers/openai/call_useragent.go 🔗

@@ -3,7 +3,7 @@ package openai
 import (
 	"charm.land/fantasy"
 	"charm.land/fantasy/providers/internal/httpheaders"
-	"github.com/openai/openai-go/v3/option"
+	"github.com/charmbracelet/openai-go/option"
 )
 
 // callUARequestOptions returns per-request options that override the

providers/openai/error.go 🔗

@@ -10,7 +10,7 @@ import (
 	"strings"
 
 	"charm.land/fantasy"
-	"github.com/openai/openai-go/v3"
+	"github.com/charmbracelet/openai-go"
 )
 
 var openaiContextPattern = regexp.MustCompile(`maximum context length is (\d+) tokens.*?(?:resulted in|requested) (\d+) tokens`)

providers/openai/language_model.go 🔗

@@ -12,11 +12,11 @@ import (
 	"charm.land/fantasy"
 	"charm.land/fantasy/object"
 	"charm.land/fantasy/schema"
+	"github.com/charmbracelet/openai-go"
+	"github.com/charmbracelet/openai-go/packages/param"
+	"github.com/charmbracelet/openai-go/shared"
 	xjson "github.com/charmbracelet/x/json"
 	"github.com/google/uuid"
-	"github.com/openai/openai-go/v3"
-	"github.com/openai/openai-go/v3/packages/param"
-	"github.com/openai/openai-go/v3/shared"
 )
 
 type languageModel struct {

providers/openai/language_model_hooks.go 🔗

@@ -6,9 +6,9 @@ import (
 	"strings"
 
 	"charm.land/fantasy"
-	"github.com/openai/openai-go/v3"
-	"github.com/openai/openai-go/v3/packages/param"
-	"github.com/openai/openai-go/v3/shared"
+	"github.com/charmbracelet/openai-go"
+	"github.com/charmbracelet/openai-go/packages/param"
+	"github.com/charmbracelet/openai-go/shared"
 )
 
 // LanguageModelPrepareCallFunc is a function that prepares the call for the language model.

providers/openai/openai.go 🔗

@@ -8,8 +8,8 @@ import (
 
 	"charm.land/fantasy"
 	"charm.land/fantasy/providers/internal/httpheaders"
-	"github.com/openai/openai-go/v3"
-	"github.com/openai/openai-go/v3/option"
+	"github.com/charmbracelet/openai-go"
+	"github.com/charmbracelet/openai-go/option"
 )
 
 const (

providers/openai/openai_test.go 🔗

@@ -11,7 +11,7 @@ import (
 	"testing"
 
 	"charm.land/fantasy"
-	"github.com/openai/openai-go/v3/packages/param"
+	"github.com/charmbracelet/openai-go/packages/param"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 )

providers/openai/provider_options.go 🔗

@@ -5,7 +5,7 @@ import (
 	"encoding/json"
 
 	"charm.land/fantasy"
-	"github.com/openai/openai-go/v3"
+	"github.com/charmbracelet/openai-go"
 )
 
 // ReasoningEffort represents the reasoning effort level for OpenAI models.

providers/openai/responses_language_model.go 🔗

@@ -12,11 +12,11 @@ import (
 	"charm.land/fantasy"
 	"charm.land/fantasy/object"
 	"charm.land/fantasy/schema"
+	"github.com/charmbracelet/openai-go"
+	"github.com/charmbracelet/openai-go/packages/param"
+	"github.com/charmbracelet/openai-go/responses"
+	"github.com/charmbracelet/openai-go/shared"
 	"github.com/google/uuid"
-	"github.com/openai/openai-go/v3"
-	"github.com/openai/openai-go/v3/packages/param"
-	"github.com/openai/openai-go/v3/responses"
-	"github.com/openai/openai-go/v3/shared"
 )
 
 const topLogprobsMax = 20

providers/openaicompat/language_model_hooks.go 🔗

@@ -8,9 +8,9 @@ import (
 
 	"charm.land/fantasy"
 	"charm.land/fantasy/providers/openai"
-	openaisdk "github.com/openai/openai-go/v3"
-	"github.com/openai/openai-go/v3/packages/param"
-	"github.com/openai/openai-go/v3/shared"
+	openaisdk "github.com/charmbracelet/openai-go"
+	"github.com/charmbracelet/openai-go/packages/param"
+	"github.com/charmbracelet/openai-go/shared"
 )
 
 const reasoningStartedCtx = "reasoning_started"

providers/openaicompat/openaicompat.go 🔗

@@ -4,7 +4,7 @@ package openaicompat
 import (
 	"charm.land/fantasy"
 	"charm.land/fantasy/providers/openai"
-	"github.com/openai/openai-go/v3/option"
+	"github.com/charmbracelet/openai-go/option"
 )
 
 type options struct {

providers/openrouter/language_model_hooks.go 🔗

@@ -11,8 +11,8 @@ import (
 	"charm.land/fantasy/providers/anthropic"
 	"charm.land/fantasy/providers/google"
 	"charm.land/fantasy/providers/openai"
-	openaisdk "github.com/openai/openai-go/v3"
-	"github.com/openai/openai-go/v3/packages/param"
+	openaisdk "github.com/charmbracelet/openai-go"
+	"github.com/charmbracelet/openai-go/packages/param"
 )
 
 const reasoningStartedCtx = "reasoning_started"

providers/openrouter/openrouter.go 🔗

@@ -6,7 +6,7 @@ import (
 
 	"charm.land/fantasy"
 	"charm.land/fantasy/providers/openai"
-	"github.com/openai/openai-go/v3/option"
+	"github.com/charmbracelet/openai-go/option"
 )
 
 type options struct {

providers/vercel/language_model_hooks.go 🔗

@@ -11,8 +11,8 @@ import (
 	"charm.land/fantasy/providers/anthropic"
 	"charm.land/fantasy/providers/google"
 	openaipkg "charm.land/fantasy/providers/openai"
-	openaisdk "github.com/openai/openai-go/v3"
-	"github.com/openai/openai-go/v3/packages/param"
+	openaisdk "github.com/charmbracelet/openai-go"
+	"github.com/charmbracelet/openai-go/packages/param"
 )
 
 const reasoningStartedCtx = "reasoning_started"

providers/vercel/vercel.go 🔗

@@ -4,7 +4,7 @@ package vercel
 import (
 	"charm.land/fantasy"
 	"charm.land/fantasy/providers/openai"
-	"github.com/openai/openai-go/v3/option"
+	"github.com/charmbracelet/openai-go/option"
 )
 
 type options struct {