diff --git a/server/cloud_proxy.go b/server/cloud_proxy.go index f08b6a456..ca9a10da4 100644 --- a/server/cloud_proxy.go +++ b/server/cloud_proxy.go @@ -20,13 +20,15 @@ import ( "github.com/ollama/ollama/auth" "github.com/ollama/ollama/envconfig" internalcloud "github.com/ollama/ollama/internal/cloud" + "github.com/ollama/ollama/version" ) const ( - defaultCloudProxyBaseURL = "https://ollama.com:443" - defaultCloudProxySigningHost = "ollama.com" - cloudProxyBaseURLEnv = "OLLAMA_CLOUD_BASE_URL" - legacyCloudAnthropicKey = "legacy_cloud_anthropic_web_search" + defaultCloudProxyBaseURL = "https://ollama.com:443" + defaultCloudProxySigningHost = "ollama.com" + cloudProxyBaseURLEnv = "OLLAMA_CLOUD_BASE_URL" + legacyCloudAnthropicKey = "legacy_cloud_anthropic_web_search" + cloudProxyClientVersionHeader = "X-Ollama-Client-Version" ) var ( @@ -181,6 +183,9 @@ func proxyCloudRequestWithPath(c *gin.Context, body []byte, path string, disable } copyProxyRequestHeaders(outReq.Header, c.Request.Header) + if clientVersion := strings.TrimSpace(version.Version); clientVersion != "" { + outReq.Header.Set(cloudProxyClientVersionHeader, clientVersion) + } if outReq.Header.Get("Content-Type") == "" && len(body) > 0 { outReq.Header.Set("Content-Type", "application/json") } diff --git a/server/routes_cloud_test.go b/server/routes_cloud_test.go index d6311582c..8bbc52e08 100644 --- a/server/routes_cloud_test.go +++ b/server/routes_cloud_test.go @@ -17,6 +17,7 @@ import ( "github.com/ollama/ollama/api" internalcloud "github.com/ollama/ollama/internal/cloud" "github.com/ollama/ollama/middleware" + "github.com/ollama/ollama/version" ) func TestStatusHandler(t *testing.T) { @@ -207,6 +208,9 @@ func TestExplicitCloudPassthroughAPIAndV1(t *testing.T) { if got := capture.header.Get("X-Test-Header"); got != "api-header" { t.Fatalf("expected forwarded X-Test-Header=api-header, got %q", got) } + if got := capture.header.Get(cloudProxyClientVersionHeader); got != version.Version { + t.Fatalf("expected %s=%q, got %q", cloudProxyClientVersionHeader, version.Version, got) + } }) t.Run("api chat", func(t *testing.T) { diff --git a/server/routes_web_experimental_test.go b/server/routes_web_experimental_test.go index 81d721914..60be5f385 100644 --- a/server/routes_web_experimental_test.go +++ b/server/routes_web_experimental_test.go @@ -12,6 +12,7 @@ import ( "github.com/gin-gonic/gin" internalcloud "github.com/ollama/ollama/internal/cloud" + "github.com/ollama/ollama/version" ) type webExperimentalUpstreamCapture struct { @@ -92,6 +93,7 @@ func TestExperimentalWebEndpointsPassthrough(t *testing.T) { req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer should-forward") req.Header.Set("X-Test-Header", "web-experimental") + req.Header.Set(cloudProxyClientVersionHeader, "should-be-overwritten") resp, err := local.Client().Do(req) if err != nil { @@ -115,6 +117,9 @@ func TestExperimentalWebEndpointsPassthrough(t *testing.T) { if got := capture.header.Get("X-Test-Header"); got != "web-experimental" { t.Fatalf("expected forwarded X-Test-Header=web-experimental, got %q", got) } + if got := capture.header.Get(cloudProxyClientVersionHeader); got != version.Version { + t.Fatalf("expected %s=%q, got %q", cloudProxyClientVersionHeader, version.Version, got) + } }) } }