Detailed changes
@@ -14,7 +14,9 @@ import (
"github.com/anthropics/anthropic-sdk-go"
"github.com/anthropics/anthropic-sdk-go/option"
"github.com/anthropics/anthropic-sdk-go/packages/param"
+ "github.com/anthropics/anthropic-sdk-go/vertex"
"github.com/charmbracelet/fantasy/ai"
+ "golang.org/x/oauth2/google"
)
const (
@@ -28,6 +30,10 @@ type options struct {
name string
headers map[string]string
client option.HTTPClient
+
+ vertexProject string
+ vertexLocation string
+ skipGoogleAuth bool
}
type provider struct {
@@ -61,6 +67,19 @@ func WithAPIKey(apiKey string) Option {
}
}
+func WithVertex(project, location string) Option {
+ return func(o *options) {
+ o.vertexProject = project
+ o.vertexLocation = location
+ }
+}
+
+func WithSkipGoogleAuth(skip bool) Option {
+ return func(o *options) {
+ o.skipGoogleAuth = skip
+ }
+}
+
func WithName(name string) Option {
return func(o *options) {
o.name = name
@@ -80,26 +99,46 @@ func WithHTTPClient(client option.HTTPClient) Option {
}
func (a *provider) LanguageModel(modelID string) (ai.LanguageModel, error) {
- anthropicClientOptions := []option.RequestOption{}
+ clientOptions := make([]option.RequestOption, 0, 5+len(a.options.headers))
if a.options.apiKey != "" {
- anthropicClientOptions = append(anthropicClientOptions, option.WithAPIKey(a.options.apiKey))
+ clientOptions = append(clientOptions, option.WithAPIKey(a.options.apiKey))
}
if a.options.baseURL != "" {
- anthropicClientOptions = append(anthropicClientOptions, option.WithBaseURL(a.options.baseURL))
+ clientOptions = append(clientOptions, option.WithBaseURL(a.options.baseURL))
}
-
for key, value := range a.options.headers {
- anthropicClientOptions = append(anthropicClientOptions, option.WithHeader(key, value))
+ clientOptions = append(clientOptions, option.WithHeader(key, value))
}
-
if a.options.client != nil {
- anthropicClientOptions = append(anthropicClientOptions, option.WithHTTPClient(a.options.client))
+ clientOptions = append(clientOptions, option.WithHTTPClient(a.options.client))
+ }
+ if a.options.vertexProject != "" && a.options.vertexLocation != "" {
+ var credentials *google.Credentials
+ if a.options.skipGoogleAuth {
+ credentials = &google.Credentials{TokenSource: &googleDummyTokenSource{}}
+ } else {
+ var err error
+ credentials, err = google.FindDefaultCredentials(context.Background())
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ clientOptions = append(
+ clientOptions,
+ vertex.WithCredentials(
+ context.Background(),
+ a.options.vertexLocation,
+ a.options.vertexProject,
+ credentials,
+ ),
+ )
}
return languageModel{
modelID: modelID,
provider: a.options.name,
options: a.options,
- client: anthropic.NewClient(anthropicClientOptions...),
+ client: anthropic.NewClient(clientOptions...),
}, nil
}
@@ -0,0 +1,11 @@
+package anthropic
+
+import (
+ "golang.org/x/oauth2"
+)
+
+type googleDummyTokenSource struct{}
+
+func (googleDummyTokenSource) Token() (*oauth2.Token, error) {
+ return &oauth2.Token{AccessToken: "dummy-token"}, nil
+}
@@ -3,6 +3,7 @@ module github.com/charmbracelet/fantasy
go 1.24.5
require (
+ cloud.google.com/go/auth v0.9.3
github.com/anthropics/anthropic-sdk-go v1.10.0
github.com/charmbracelet/x/exp/slice v0.0.0-20250904123553-b4e2667e5ad5
github.com/charmbracelet/x/json v0.2.0
@@ -12,17 +13,21 @@ require (
github.com/openai/openai-go/v2 v2.3.0
github.com/stretchr/testify v1.11.1
go.yaml.in/yaml/v4 v4.0.0-rc.2
+ golang.org/x/oauth2 v0.30.0
google.golang.org/genai v1.26.0
gopkg.in/dnaeon/go-vcr.v4 v4.0.6-0.20250923044825-7b4892dd3117
)
require (
cloud.google.com/go v0.116.0 // indirect
- cloud.google.com/go/auth v0.9.3 // indirect
+ cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect
cloud.google.com/go/compute/metadata v0.5.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/felixge/httpsnoop v1.0.4 // indirect
+ github.com/go-logr/logr v1.4.2 // indirect
+ github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/s2a-go v0.1.8 // indirect
@@ -34,12 +39,28 @@ require (
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/sjson v1.2.5 // indirect
go.opencensus.io v0.24.0 // indirect
+ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect
+ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect
+ go.opentelemetry.io/otel v1.29.0 // indirect
+ go.opentelemetry.io/otel/metric v1.29.0 // indirect
+ go.opentelemetry.io/otel/trace v1.29.0 // indirect
golang.org/x/crypto v0.40.0 // indirect
golang.org/x/net v0.41.0 // indirect
+ golang.org/x/sync v0.16.0 // indirect
golang.org/x/sys v0.34.0 // indirect
golang.org/x/text v0.27.0 // indirect
+ golang.org/x/time v0.6.0 // indirect
+ google.golang.org/api v0.197.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
google.golang.org/grpc v1.66.2 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
+
+// NOTE(@andreynering): Temporarily pinning @fantasy branch with fixes:
+// https://github.com/charmbracelet/anthropic-sdk-go/commits/fantasy/
+replace github.com/anthropics/anthropic-sdk-go => github.com/charmbracelet/anthropic-sdk-go v0.0.0-20251010172108-7b952cdeeb9d
+
+// NOTE(@andreynering): Temporarily pinning @fantasy branch with fixes:
+// https://github.com/charmbracelet/anthropic-sdk-go/commits/fantasy/
+replace google.golang.org/genai => github.com/charmbracelet/go-genai v0.0.0-20251009191514-c6fa9e37d847
@@ -3,6 +3,8 @@ cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE=
cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U=
cloud.google.com/go/auth v0.9.3 h1:VOEUIAADkkLtyfr3BLa3R8Ed/j6w1jTBmARx+wb5w5U=
cloud.google.com/go/auth v0.9.3/go.mod h1:7z6VY+7h3KUdRov5F1i8NDP5ZzWKYmEPO842BgCsmTk=
+cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY=
+cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc=
cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY=
cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ=
@@ -14,9 +16,11 @@ github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkY
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU=
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/anthropics/anthropic-sdk-go v1.10.0 h1:jDKQTfC0miIEj21eMmPrNSLKTNdNa3nHZOhd4wZz1cI=
-github.com/anthropics/anthropic-sdk-go v1.10.0/go.mod h1:WTz31rIUHUHqai2UslPpw5CwXrQP3geYBioRV4WOLvE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/charmbracelet/anthropic-sdk-go v0.0.0-20251010172108-7b952cdeeb9d h1:qP7F7r7aVY7AReYHHgkQ79weuUEZK7zXtDtSEydYb0w=
+github.com/charmbracelet/anthropic-sdk-go v0.0.0-20251010172108-7b952cdeeb9d/go.mod h1:WTz31rIUHUHqai2UslPpw5CwXrQP3geYBioRV4WOLvE=
+github.com/charmbracelet/go-genai v0.0.0-20251009191514-c6fa9e37d847 h1:Oyo6YZ59iygXWNUlRozIOFHO4WUG9cNFhiUYCTq4AnU=
+github.com/charmbracelet/go-genai v0.0.0-20251009191514-c6fa9e37d847/go.mod h1:7pAilaICJlQBonjKKJNhftDFv3SREhZcTe9F6nRcjbg=
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=
@@ -30,6 +34,13 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
+github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
+github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
@@ -48,6 +59,8 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@@ -102,6 +115,16 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 h1:r6I7RJCN86bpD/FQwedZ0vSixDpwuWREjW9oRMsmqDc=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8=
+go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw=
+go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8=
+go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc=
+go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8=
+go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4=
+go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ=
go.yaml.in/yaml/v4 v4.0.0-rc.2 h1:/FrI8D64VSr4HtGIlUtlFMGsm7H7pWTbj6vOLVZcA6s=
go.yaml.in/yaml/v4 v4.0.0-rc.2/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@@ -121,6 +144,8 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
+golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -136,16 +161,18 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
+golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
+golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/api v0.197.0 h1:x6CwqQLsFiA5JKAiGyGBjc2bNtHtLddhJCE2IKuhhcQ=
+google.golang.org/api v0.197.0/go.mod h1:AuOuo20GoQ331nq7DquGHlU6d+2wN2fZ8O0ta60nRNw=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
-google.golang.org/genai v1.26.0 h1:r4HGL54kFv/WCRMTAbZg05Ct+vXfhAbTRlXhFyBkEQo=
-google.golang.org/genai v1.26.0/go.mod h1:OClfdf+r5aaD+sCd4aUSkPzJItmg2wD/WON9lQnRPaY=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
@@ -0,0 +1,63 @@
+# Google Provider
+
+This document describes how to get an API keys for Google Gemini and Vertex.
+
+## Gemini
+
+Simply navigate to [this page](https://aistudio.google.com/apikey) in the
+Google AI Studio and create a new API key.
+
+## Vertex
+
+### Install `gcloud`
+
+Install the `gcloud` command line tool. Install via Homebrew, Nix, or download
+it from [here](https://cloud.google.com/sdk/docs/install).
+
+```bash
+# Homebrew
+brew install --cask google-cloud-sdk
+
+# Nix
+nix-env -iA nixpkgs.google-cloud-sdk
+```
+
+### Authenticate
+
+Then authenticate with your Google account:
+
+```bash
+gcloud auth login
+```
+
+### Create And Setup Project
+
+Navigate here to create a new project if you haven't already:
+https://console.cloud.google.com/projectcreate
+
+Alternatively, you can create a new project via the command line:
+
+```bash
+gcloud projects create {YOUR_PROJECT_ID} --name="{YOUR_PROJECT_NAME}"
+```
+
+Set the project on your machine:
+
+```bash
+gcloud config set project {YOUR_PROJECT_ID}
+```
+
+Enable the Vertex AI API:
+
+```bash
+gcloud services enable aiplatform.googleapis.com
+```
+
+### Setup Env
+
+Finally, you need to run this command to ensure that libraries will be able to
+find your credentials.
+
+```bash
+gcloud auth application-default login
+```
@@ -0,0 +1,13 @@
+package google
+
+import (
+ "context"
+
+ "cloud.google.com/go/auth"
+)
+
+type dummyTokenProvider struct{}
+
+func (dummyTokenProvider) Token(ctx context.Context) (*auth.Token, error) {
+ return &auth.Token{Value: "dummy-token"}, nil
+}
@@ -11,7 +11,9 @@ import (
"net/http"
"strings"
+ "cloud.google.com/go/auth"
"github.com/charmbracelet/fantasy/ai"
+ "github.com/charmbracelet/fantasy/anthropic"
"github.com/charmbracelet/x/exp/slice"
"github.com/google/uuid"
"google.golang.org/genai"
@@ -24,10 +26,14 @@ type provider struct {
}
type options struct {
- apiKey string
- name string
- headers map[string]string
- client *http.Client
+ apiKey string
+ name string
+ headers map[string]string
+ client *http.Client
+ backend genai.Backend
+ project string
+ location string
+ skipAuth bool
}
type Option = func(*options)
@@ -47,9 +53,30 @@ func New(opts ...Option) ai.Provider {
}
}
-func WithAPIKey(apiKey string) Option {
+func WithGeminiAPIKey(apiKey string) Option {
return func(o *options) {
+ o.backend = genai.BackendGeminiAPI
o.apiKey = apiKey
+ o.project = ""
+ o.location = ""
+ }
+}
+
+func WithVertex(project, location string) Option {
+ if project == "" || location == "" {
+ panic("project and location must be provided")
+ }
+ return func(o *options) {
+ o.backend = genai.BackendVertexAI
+ o.apiKey = ""
+ o.project = project
+ o.location = location
+ }
+}
+
+func WithSkipAuth(skipAuth bool) Option {
+ return func(o *options) {
+ o.skipAuth = skipAuth
}
}
@@ -92,10 +119,23 @@ type languageModel struct {
// LanguageModel implements ai.Provider.
func (g *provider) LanguageModel(modelID string) (ai.LanguageModel, error) {
+ if strings.Contains(modelID, "anthropic") || strings.Contains(modelID, "claude") {
+ return anthropic.New(
+ anthropic.WithVertex(g.options.project, g.options.location),
+ anthropic.WithHTTPClient(g.options.client),
+ anthropic.WithSkipGoogleAuth(g.options.skipAuth),
+ ).LanguageModel(modelID)
+ }
+
cc := &genai.ClientConfig{
- APIKey: g.options.apiKey,
- Backend: genai.BackendGeminiAPI,
HTTPClient: g.options.client,
+ Backend: g.options.backend,
+ APIKey: g.options.apiKey,
+ Project: g.options.project,
+ Location: g.options.location,
+ }
+ if g.options.skipAuth {
+ cc.Credentials = &auth.Credentials{TokenProvider: dummyTokenProvider{}}
}
client, err := genai.NewClient(context.Background(), cc)
if err != nil {
@@ -116,7 +156,7 @@ func (a languageModel) prepareParams(call ai.Call) (*genai.GenerateContentConfig
if v, ok := call.ProviderOptions[Name]; ok {
providerOptions, ok = v.(*ProviderOptions)
if !ok {
- return nil, nil, nil, ai.NewInvalidArgumentError("providerOptions", "anthropic provider options should be *anthropic.ProviderOptions", nil)
+ return nil, nil, nil, ai.NewInvalidArgumentError("providerOptions", "google provider options should be *google.ProviderOptions", nil)
}
}
@@ -386,6 +426,8 @@ func toGooglePrompt(prompt ai.Prompt) (*genai.Content, []*genai.Content, []ai.Ca
Parts: parts,
})
}
+ default:
+ panic("unsupported message role: " + msg.Role)
}
}
return systemInstructions, content, warnings
@@ -5,5 +5,7 @@ FANTASY_GEMINI_API_KEY=
FANTASY_GROQ_API_KEY=
FANTASY_OPENAI_API_KEY=
FANTASY_OPENROUTER_API_KEY=
+FANTASY_VERTEX_LOCATION=us-east5
+FANTASY_VERTEX_PROJECT=fantasy-playground-472418
FANTASY_XAI_API_KEY=
FANTASY_ZAI_API_KEY=
@@ -2,16 +2,25 @@ package providertests
import (
"context"
+ "os"
"strconv"
"strings"
"testing"
"github.com/charmbracelet/fantasy/ai"
- _ "github.com/joho/godotenv/autoload"
+ "github.com/joho/godotenv"
"github.com/stretchr/testify/require"
"gopkg.in/dnaeon/go-vcr.v4/pkg/recorder"
)
+func init() {
+ if _, err := os.Stat(".env"); err == nil {
+ godotenv.Load(".env")
+ } else {
+ godotenv.Load(".env.sample")
+ }
+}
+
type testModel struct {
name string
model string
@@ -94,7 +103,7 @@ func testTool(t *testing.T, pair builderPair) {
},
)
checkResult := func(t *testing.T, result *ai.AgentResult) {
- require.Len(t, result.Steps, 2)
+ require.GreaterOrEqual(t, len(result.Steps), 2)
var toolCalls []ai.ToolCallContent
for _, content := range result.Steps[0].Content {
@@ -155,10 +164,13 @@ func testTool(t *testing.T, pair builderPair) {
}
func testMultiTool(t *testing.T, pair builderPair) {
- // Apparently, Azure does not support multi-tools calls at all?
+ // Apparently, Azure and Vertex+Anthropic do not support multi-tools calls at all?
if strings.Contains(pair.name, "azure") {
t.Skip("skipping multi-tool tests for azure as it does not support parallel multi-tool calls")
}
+ if strings.Contains(pair.name, "vertex") && strings.Contains(pair.name, "claude") {
+ t.Skip("skipping multi-tool tests for vertex claude as it does not support parallel multi-tool calls")
+ }
type CalculatorInput struct {
A int `json:"a" description:"first number"`
@@ -12,15 +12,24 @@ import (
"gopkg.in/dnaeon/go-vcr.v4/pkg/recorder"
)
-var googleTestModels = []testModel{
+var geminiTestModels = []testModel{
{"gemini-2.5-flash", "gemini-2.5-flash", true},
{"gemini-2.5-pro", "gemini-2.5-pro", true},
}
+var vertexTestModels = []testModel{
+ {"vertex-gemini-2-5-flash", "gemini-2.5-flash", true},
+ {"vertex-gemini-2-5-pro", "gemini-2.5-pro", true},
+ {"vertex-claude-3-7-sonnet", "claude-3-7-sonnet@20250219", true},
+}
+
func TestGoogleCommon(t *testing.T) {
var pairs []builderPair
- for _, m := range googleTestModels {
- pairs = append(pairs, builderPair{m.name, googleBuilder(m.model), nil})
+ for _, m := range geminiTestModels {
+ pairs = append(pairs, builderPair{m.name, geminiBuilder(m.model), nil})
+ }
+ for _, m := range vertexTestModels {
+ pairs = append(pairs, builderPair{m.name, vertexBuilder(m.model), nil})
}
testCommon(t, pairs)
}
@@ -36,11 +45,11 @@ func TestGoogleThinking(t *testing.T) {
}
var pairs []builderPair
- for _, m := range googleTestModels {
+ for _, m := range geminiTestModels {
if !m.reasoning {
continue
}
- pairs = append(pairs, builderPair{m.name, googleBuilder(m.model), opts})
+ pairs = append(pairs, builderPair{m.name, geminiBuilder(m.model), opts})
}
testThinking(t, pairs, testGoogleThinking)
}
@@ -60,11 +69,22 @@ func testGoogleThinking(t *testing.T, result *ai.AgentResult) {
require.Greater(t, reasoningContentCount, 0)
}
-func googleBuilder(model string) builderFunc {
+func geminiBuilder(model string) builderFunc {
+ return func(r *recorder.Recorder) (ai.LanguageModel, error) {
+ provider := google.New(
+ google.WithGeminiAPIKey(cmp.Or(os.Getenv("FANTASY_GEMINI_API_KEY"), "(missing)")),
+ google.WithHTTPClient(&http.Client{Transport: r}),
+ )
+ return provider.LanguageModel(model)
+ }
+}
+
+func vertexBuilder(model string) builderFunc {
return func(r *recorder.Recorder) (ai.LanguageModel, error) {
provider := google.New(
- google.WithAPIKey(cmp.Or(os.Getenv("FANTASY_GEMINI_API_KEY"), "(missing)")),
+ google.WithVertex(os.Getenv("FANTASY_VERTEX_PROJECT"), os.Getenv("FANTASY_VERTEX_LOCATION")),
google.WithHTTPClient(&http.Client{Transport: r}),
+ google.WithSkipAuth(true),
)
return provider.LanguageModel(model)
}
@@ -0,0 +1,33 @@
+---
+version: 2
+interactions:
+- id: 0
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 210
+ host: ""
+ body: '{"max_tokens":4000,"messages":[{"content":[{"text":"Say hi in Portuguese","type":"text"}],"role":"user"}],"system":[{"text":"You are a helpful assistant","type":"text"}],"anthropic_version":"vertex-2023-10-16"}'
+ headers:
+ Accept:
+ - application/json
+ Content-Type:
+ - application/json
+ User-Agent:
+ - Anthropic/Go 1.13.0
+ url: https://us-east5-aiplatform.googleapis.com/v1/projects/fantasy-playground-472418/locations/us-east5/publishers/anthropic/models/claude-3-7-sonnet@20250219:rawPredict
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
+ uncompressed: true
+ body: '{"id":"msg_vrtx_01JoBtryoxdRxCJ4GfXam6Yu","type":"message","role":"assistant","model":"claude-3-7-sonnet-20250219","content":[{"type":"text","text":"Olรก! That''s \"hi\" in Portuguese. I can also say \"Oi\" which is a more casual greeting in Portuguese."}],"stop_reason":"end_turn","stop_sequence":null,"usage":{"input_tokens":16,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":33}}'
+ headers:
+ Content-Type:
+ - application/json
+ status: 200 OK
+ code: 200
+ duration: 1.987505375s
@@ -0,0 +1,102 @@
+---
+version: 2
+interactions:
+- id: 0
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 224
+ host: ""
+ body: '{"max_tokens":4000,"messages":[{"content":[{"text":"Say hi in Portuguese","type":"text"}],"role":"user"}],"system":[{"text":"You are a helpful assistant","type":"text"}],"stream":true,"anthropic_version":"vertex-2023-10-16"}'
+ headers:
+ Accept:
+ - application/json
+ Content-Type:
+ - application/json
+ User-Agent:
+ - Anthropic/Go 1.13.0
+ url: https://us-east5-aiplatform.googleapis.com/v1/projects/fantasy-playground-472418/locations/us-east5/publishers/anthropic/models/claude-3-7-sonnet@20250219:streamRawPredict
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
+ uncompressed: true
+ body: |+
+ event: message_start
+ data: {"type":"message_start","message":{"id":"msg_vrtx_01551jxgCbyerbL44qCuV9kn","type":"message","role":"assistant","model":"claude-3-7-sonnet-20250219","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":16,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":5}} }
+
+ event: ping
+ data: {"type": "ping"}
+
+ event: content_block_start
+ data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Olรก!"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"\n\n\""} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Olรก\" is"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" the"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Portuguese way"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" to say"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" \"hi"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"\" or \"hello.\""} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" It's a friendly"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" greeting"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" use"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"d in both"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Portugal"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" and Brazil,"}}
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" as"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" well as other"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Portuguese-speaking countries."} }
+
+ event: content_block_stop
+ data: {"type":"content_block_stop","index":0}
+
+ event: message_delta
+ data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"output_tokens":47} }
+
+ event: message_stop
+ data: {"type":"message_stop" }
+
+ headers:
+ Content-Type:
+ - text/event-stream; charset=utf-8
+ status: 200 OK
+ code: 200
+ duration: 1.902656792s
@@ -0,0 +1,63 @@
+---
+version: 2
+interactions:
+- id: 0
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 501
+ host: ""
+ body: '{"max_tokens":4000,"messages":[{"content":[{"text":"What''s the weather in Florence,Italy?","type":"text"}],"role":"user"}],"system":[{"text":"You are a helpful assistant","type":"text"}],"tool_choice":{"disable_parallel_tool_use":false,"type":"auto"},"tools":[{"input_schema":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location"}],"anthropic_version":"vertex-2023-10-16"}'
+ headers:
+ Accept:
+ - application/json
+ Content-Type:
+ - application/json
+ User-Agent:
+ - Anthropic/Go 1.13.0
+ url: https://us-east5-aiplatform.googleapis.com/v1/projects/fantasy-playground-472418/locations/us-east5/publishers/anthropic/models/claude-3-7-sonnet@20250219:rawPredict
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
+ uncompressed: true
+ body: '{"id":"msg_vrtx_012JnDNruXUPVCywN7jYpwZ8","type":"message","role":"assistant","model":"claude-3-7-sonnet-20250219","content":[{"type":"text","text":"I''ll check the current weather in Florence, Italy for you."},{"type":"tool_use","id":"toolu_vrtx_0129YeW9ohuKMKgnDRAStbvo","name":"weather","input":{"location":"Florence,Italy"}}],"stop_reason":"tool_use","stop_sequence":null,"usage":{"input_tokens":394,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":67}}'
+ headers:
+ Content-Type:
+ - application/json
+ status: 200 OK
+ code: 200
+ duration: 1.557585167s
+- id: 1
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 881
+ host: ""
+ body: '{"max_tokens":4000,"messages":[{"content":[{"text":"What''s the weather in Florence,Italy?","type":"text"}],"role":"user"},{"content":[{"text":"I''ll check the current weather in Florence, Italy for you.","type":"text"},{"id":"toolu_vrtx_0129YeW9ohuKMKgnDRAStbvo","input":{"location":"Florence,Italy"},"name":"weather","type":"tool_use"}],"role":"assistant"},{"content":[{"tool_use_id":"toolu_vrtx_0129YeW9ohuKMKgnDRAStbvo","content":[{"text":"40 C","type":"text"}],"type":"tool_result"}],"role":"user"}],"system":[{"text":"You are a helpful assistant","type":"text"}],"tool_choice":{"disable_parallel_tool_use":false,"type":"auto"},"tools":[{"input_schema":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location"}],"anthropic_version":"vertex-2023-10-16"}'
+ headers:
+ Accept:
+ - application/json
+ Content-Type:
+ - application/json
+ User-Agent:
+ - Anthropic/Go 1.13.0
+ url: https://us-east5-aiplatform.googleapis.com/v1/projects/fantasy-playground-472418/locations/us-east5/publishers/anthropic/models/claude-3-7-sonnet@20250219:rawPredict
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
+ uncompressed: true
+ body: '{"id":"msg_vrtx_015jg26txA4Uuayzue6Q8PP4","type":"message","role":"assistant","model":"claude-3-7-sonnet-20250219","content":[{"type":"text","text":"The current temperature in Florence, Italy is 40ยฐC (104ยฐF), which is extremely hot. If you''re in Florence or planning to visit soon, I''d recommend staying hydrated, seeking shade when possible, and perhaps planning indoor activities during the hottest parts of the day."}],"stop_reason":"end_turn","stop_sequence":null,"usage":{"input_tokens":475,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":63}}'
+ headers:
+ Content-Type:
+ - application/json
+ status: 200 OK
+ code: 200
+ duration: 1.644774333s
@@ -0,0 +1,186 @@
+---
+version: 2
+interactions:
+- id: 0
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 515
+ host: ""
+ body: '{"max_tokens":4000,"messages":[{"content":[{"text":"What''s the weather in Florence,Italy?","type":"text"}],"role":"user"}],"system":[{"text":"You are a helpful assistant","type":"text"}],"tool_choice":{"disable_parallel_tool_use":false,"type":"auto"},"tools":[{"input_schema":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location"}],"stream":true,"anthropic_version":"vertex-2023-10-16"}'
+ headers:
+ Accept:
+ - application/json
+ Content-Type:
+ - application/json
+ User-Agent:
+ - Anthropic/Go 1.13.0
+ url: https://us-east5-aiplatform.googleapis.com/v1/projects/fantasy-playground-472418/locations/us-east5/publishers/anthropic/models/claude-3-7-sonnet@20250219:streamRawPredict
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
+ uncompressed: true
+ body: |+
+ event: message_start
+ data: {"type":"message_start","message":{"id":"msg_vrtx_01MtpPXF7gH6SFEyKNTJLWEw","type":"message","role":"assistant","model":"claude-3-7-sonnet-20250219","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":394,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":3}} }
+
+ event: ping
+ data: {"type": "ping"}
+
+ event: content_block_start
+ data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"I'll check"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" the current weather in"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Florence, Italy for you"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"."} }
+
+ event: content_block_stop
+ data: {"type":"content_block_stop","index":0 }
+
+ event: content_block_start
+ data: {"type":"content_block_start","index":1,"content_block":{"type":"tool_use","id":"toolu_vrtx_01Tj3azsUbpPDwNvW3itTJ3L","name":"weather","input":{}} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":""} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"{\"locatio"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"n\": \"Fl"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"ore"}}
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"nce,Italy\"}"} }
+
+ event: content_block_stop
+ data: {"type":"content_block_stop","index":1 }
+
+ event: message_delta
+ data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"output_tokens":67} }
+
+ event: message_stop
+ data: {"type":"message_stop" }
+
+ headers:
+ Content-Type:
+ - text/event-stream; charset=utf-8
+ status: 200 OK
+ code: 200
+ duration: 790.875833ms
+- id: 1
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 895
+ host: ""
+ body: '{"max_tokens":4000,"messages":[{"content":[{"text":"What''s the weather in Florence,Italy?","type":"text"}],"role":"user"},{"content":[{"text":"I''ll check the current weather in Florence, Italy for you.","type":"text"},{"id":"toolu_vrtx_01Tj3azsUbpPDwNvW3itTJ3L","input":{"location":"Florence,Italy"},"name":"weather","type":"tool_use"}],"role":"assistant"},{"content":[{"tool_use_id":"toolu_vrtx_01Tj3azsUbpPDwNvW3itTJ3L","content":[{"text":"40 C","type":"text"}],"type":"tool_result"}],"role":"user"}],"system":[{"text":"You are a helpful assistant","type":"text"}],"tool_choice":{"disable_parallel_tool_use":false,"type":"auto"},"tools":[{"input_schema":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location"}],"stream":true,"anthropic_version":"vertex-2023-10-16"}'
+ headers:
+ Accept:
+ - application/json
+ Content-Type:
+ - application/json
+ User-Agent:
+ - Anthropic/Go 1.13.0
+ url: https://us-east5-aiplatform.googleapis.com/v1/projects/fantasy-playground-472418/locations/us-east5/publishers/anthropic/models/claude-3-7-sonnet@20250219:streamRawPredict
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
+ uncompressed: true
+ body: |+
+ event: message_start
+ data: {"type":"message_start","message":{"id":"msg_vrtx_0164AzFzxtcpgGX36csNs7ch","type":"message","role":"assistant","model":"claude-3-7-sonnet-20250219","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":475,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":2}} }
+
+ event: ping
+ data: {"type": "ping"}
+
+ event: content_block_start
+ data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"The"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" current temperature in Florence,"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Italy is 40ยฐ"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"C (104ยฐF"}}
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"),"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" which is very hot."} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" If"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" you're there"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" or"}}
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" planning to"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" visit, make"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" sure to stay hydrate"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"d and try"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" to avoi"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"d extende"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"d exposure to the sun during"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" the hottest parts of"} }
+
+ event: content_block_delta
+ data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" the day."} }
+
+ event: content_block_stop
+ data: {"type":"content_block_stop","index":0 }
+
+ event: message_delta
+ data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"output_tokens":59} }
+
+ event: message_stop
+ data: {"type":"message_stop" }
+
+ headers:
+ Content-Type:
+ - text/event-stream; charset=utf-8
+ status: 200 OK
+ code: 200
+ duration: 1.460643125s
@@ -0,0 +1,154 @@
+---
+version: 2
+interactions:
+- id: 0
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 826
+ host: us-east5-aiplatform.googleapis.com
+ body: |
+ {"contents":[{"parts":[{"text":"Add and multiply the number 2 and 3"}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant. CRITICAL: Always use both add and multiply at the same time ALWAYS."}],"role":"user"},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Add two numbers","name":"add","parameters":{"properties":{"a":{"description":"first number","type":"INTEGER"},"b":{"description":"second number","type":"INTEGER"}},"required":["a","b"],"type":"OBJECT"}},{"description":"Multiply two numbers","name":"multiply","parameters":{"properties":{"a":{"description":"first number","type":"INTEGER"},"b":{"description":"second number","type":"INTEGER"}},"required":["a","b"],"type":"OBJECT"}}]}]}
+ headers:
+ Content-Type:
+ - application/json
+ User-Agent:
+ - google-genai-sdk/1.29.0 gl-go/go1.25.0
+ url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-flash:generateContent
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
+ uncompressed: true
+ body: |
+ {
+ "candidates": [
+ {
+ "content": {
+ "role": "model",
+ "parts": [
+ {
+ "functionCall": {
+ "name": "add",
+ "args": {
+ "b": 3,
+ "a": 2
+ }
+ },
+ "thoughtSignature": "CtYBAR/MhbZp5ZDuhyHbftCznQzuyaI5rPK4iL6DCOZOAmHm2hvqsydZ6Zw+07tzqcdyvt0Xj3Jnh9XktQUlSX7lLhgt9ChPZYfBbTUMPnBujEDNLtWhe8/7rZrBKchffl35uHsDpucQ+I+KC9Wj6NzQyaUr/TlGlyGsEXG6RotaEkVFjgxkbwLI7Ibh7CKjSQfqRd5cRz3ANCA9Td7OGCMRGXFGVwm8iC9lmhRtIOFUGxP2WyU/Nnsr3wGO9i4q+3gK17X2+rNbqMKHgb0W0anxkm4kfn8EDw=="
+ },
+ {
+ "functionCall": {
+ "name": "multiply",
+ "args": {
+ "b": 3,
+ "a": 2
+ }
+ }
+ }
+ ]
+ },
+ "finishReason": "STOP",
+ "avgLogprobs": -0.949029541015625
+ }
+ ],
+ "usageMetadata": {
+ "promptTokenCount": 60,
+ "candidatesTokenCount": 10,
+ "totalTokenCount": 129,
+ "trafficType": "ON_DEMAND",
+ "promptTokensDetails": [
+ {
+ "modality": "TEXT",
+ "tokenCount": 60
+ }
+ ],
+ "candidatesTokensDetails": [
+ {
+ "modality": "TEXT",
+ "tokenCount": 10
+ }
+ ],
+ "thoughtsTokenCount": 59
+ },
+ "modelVersion": "gemini-2.5-flash",
+ "createTime": "2025-10-10T17:53:33.301138Z",
+ "responseId": "HUjpaNKwEoav1tEPtZXfiQc"
+ }
+ headers:
+ Content-Type:
+ - application/json; charset=UTF-8
+ status: 200 OK
+ code: 200
+ duration: 1.033450667s
+- id: 1
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 1173
+ host: us-east5-aiplatform.googleapis.com
+ body: |
@@ -0,0 +1,65 @@
+---
+version: 2
+interactions:
+- id: 0
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 809
+ host: us-east5-aiplatform.googleapis.com
+ body: |
+ {"contents":[{"parts":[{"text":"Add and multiply the number 2 and 3"}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant. Always use both add and multiply at the same time."}],"role":"user"},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Add two numbers","name":"add","parameters":{"properties":{"a":{"description":"first number","type":"INTEGER"},"b":{"description":"second number","type":"INTEGER"}},"required":["a","b"],"type":"OBJECT"}},{"description":"Multiply two numbers","name":"multiply","parameters":{"properties":{"a":{"description":"first number","type":"INTEGER"},"b":{"description":"second number","type":"INTEGER"}},"required":["a","b"],"type":"OBJECT"}}]}]}
+ form:
+ alt:
+ - sse
+ headers:
+ Content-Type:
+ - application/json
+ User-Agent:
+ - google-genai-sdk/1.29.0 gl-go/go1.25.0
+ url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-flash:streamGenerateContent?alt=sse
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
@@ -0,0 +1,70 @@
+---
+version: 2
+interactions:
+- id: 0
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 202
+ host: us-east5-aiplatform.googleapis.com
+ body: |
+ {"contents":[{"parts":[{"text":"Say hi in Portuguese"}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"}}
+ headers:
+ Content-Type:
+ - application/json
+ User-Agent:
+ - google-genai-sdk/1.29.0 gl-go/go1.25.0
+ url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-flash:generateContent
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
+ uncompressed: true
+ body: |
+ {
+ "candidates": [
+ {
+ "content": {
+ "role": "model",
+ "parts": [
+ {
+ "text": "Olรก!"
+ }
+ ]
+ },
+ "finishReason": "STOP",
+ "avgLogprobs": -2.0520646572113037
+ }
+ ],
+ "usageMetadata": {
+ "promptTokenCount": 9,
+ "candidatesTokenCount": 2,
+ "totalTokenCount": 37,
+ "trafficType": "ON_DEMAND",
+ "promptTokensDetails": [
+ {
+ "modality": "TEXT",
+ "tokenCount": 9
+ }
+ ],
+ "candidatesTokensDetails": [
+ {
+ "modality": "TEXT",
+ "tokenCount": 2
+ }
+ ],
+ "thoughtsTokenCount": 26
+ },
+ "modelVersion": "gemini-2.5-flash",
+ "createTime": "2025-10-10T17:53:28.119129Z",
+ "responseId": "GEjpaNmiB8Kh18kP2devgQ4"
+ }
+ headers:
+ Content-Type:
+ - application/json; charset=UTF-8
+ status: 200 OK
+ code: 200
+ duration: 1.410897667s
@@ -0,0 +1,34 @@
+---
+version: 2
+interactions:
+- id: 0
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 202
+ host: us-east5-aiplatform.googleapis.com
+ body: |
+ {"contents":[{"parts":[{"text":"Say hi in Portuguese"}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"}}
+ form:
+ alt:
+ - sse
+ headers:
+ Content-Type:
+ - application/json
+ User-Agent:
+ - google-genai-sdk/1.29.0 gl-go/go1.25.0
+ url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-flash:streamGenerateContent?alt=sse
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
+ body: "data: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\": [{\"text\": \"Olรก! (pronounced \\\"oh-LAH\\\")\"}]},\"finishReason\": \"STOP\"}],\"usageMetadata\": {\"promptTokenCount\": 9,\"candidatesTokenCount\": 9,\"totalTokenCount\": 45,\"trafficType\": \"ON_DEMAND\",\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 9}],\"candidatesTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 9}],\"thoughtsTokenCount\": 27},\"modelVersion\": \"gemini-2.5-flash\",\"createTime\": \"2025-10-10T17:53:29.051002Z\",\"responseId\": \"GUjpaLqOA4av1tEPtZXfiQc\"}\r\n\r\n"
+ headers:
+ Content-Type:
+ - text/event-stream
+ status: 200 OK
+ code: 200
+ duration: 780.130208ms
@@ -0,0 +1,142 @@
+---
+version: 2
+interactions:
+- id: 0
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 509
+ host: us-east5-aiplatform.googleapis.com
+ body: |
+ {"contents":[{"parts":[{"text":"What's the weather in Florence,Italy?"}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"STRING"}},"required":["location"],"type":"OBJECT"}}]}]}
+ headers:
+ Content-Type:
+ - application/json
+ User-Agent:
+ - google-genai-sdk/1.29.0 gl-go/go1.25.0
+ url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-flash:generateContent
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
+ uncompressed: true
+ body: |
+ {
+ "candidates": [
+ {
+ "content": {
+ "role": "model",
+ "parts": [
+ {
+ "functionCall": {
+ "name": "weather",
+ "args": {
+ "location": "Florence,Italy"
+ }
+ },
+ "thoughtSignature": "CvoBAR/MhbYk0qvoO1yRgdHDwwyxH/IbvJEJWkExyjhCp5q/0S0Zf9zBcxa2OWwWdQJR8+Z0JMwJ0PLQnf58ln2HT24wU1p3Nr2gMxAVoZUaB4Uxo/g5rq5C5sFVqfrdzeMXIDxhtrC0Q8OzSEcQy2XIjrrmu0XZLF3BVU58ewt4Ok4/HRGzoworbz23/JLZxUEmB4Jz3TmQD3+tCNhENGIko9zcXctE/R06mFmVF/WaihIM1ibpNichDjYZqmHq5NGSE36wpBaxwJgfxxNwspek3hjVT4EsDn97FJsMeL5I3W1j0Tu8XjF7BX92tWcmP9jZO4iF5O2nda6bbQ=="
+ }
+ ]
+ },
+ "finishReason": "STOP",
+ "avgLogprobs": -1.0515016555786132
+ }
+ ],
+ "usageMetadata": {
+ "promptTokenCount": 28,
+ "candidatesTokenCount": 5,
+ "totalTokenCount": 84,
+ "trafficType": "ON_DEMAND",
+ "promptTokensDetails": [
+ {
+ "modality": "TEXT",
+ "tokenCount": 28
+ }
+ ],
+ "candidatesTokensDetails": [
+ {
+ "modality": "TEXT",
+ "tokenCount": 5
+ }
+ ],
+ "thoughtsTokenCount": 51
+ },
+ "modelVersion": "gemini-2.5-flash",
+ "createTime": "2025-10-10T17:53:30.097682Z",
+ "responseId": "GkjpaJL7BYXg1tEPj-il0Ak"
+ }
+ headers:
+ Content-Type:
+ - application/json; charset=UTF-8
+ status: 200 OK
+ code: 200
+ duration: 765.1515ms
+- id: 1
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 734
+ host: us-east5-aiplatform.googleapis.com
+ body: |
+ {"contents":[{"parts":[{"text":"What's the weather in Florence,Italy?"}],"role":"user"},{"parts":[{"functionCall":{"args":{"location":"Florence,Italy"},"id":"weather","name":"weather"}}],"role":"model"},{"parts":[{"functionResponse":{"id":"weather","name":"weather","response":{"result":"40 C"}}}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"STRING"}},"required":["location"],"type":"OBJECT"}}]}]}
+ headers:
+ Content-Type:
+ - application/json
+ User-Agent:
+ - google-genai-sdk/1.29.0 gl-go/go1.25.0
+ url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-flash:generateContent
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
+ uncompressed: true
+ body: |
+ {
+ "candidates": [
+ {
+ "content": {
+ "role": "model",
+ "parts": [
+ {
+ "text": "The weather in Florence, Italy is 40 degrees Celsius."
+ }
+ ]
+ },
+ "finishReason": "STOP",
+ "avgLogprobs": -0.048118614233457126
+ }
+ ],
+ "usageMetadata": {
+ "promptTokenCount": 38,
+ "candidatesTokenCount": 13,
+ "totalTokenCount": 51,
+ "trafficType": "ON_DEMAND",
+ "promptTokensDetails": [
+ {
+ "modality": "TEXT",
+ "tokenCount": 38
+ }
+ ],
+ "candidatesTokensDetails": [
+ {
+ "modality": "TEXT",
+ "tokenCount": 13
+ }
+ ]
+ },
+ "modelVersion": "gemini-2.5-flash",
+ "createTime": "2025-10-10T17:53:30.858865Z",
+ "responseId": "GkjpaPG1NOnqr9wPkPmEqQc"
+ }
+ headers:
+ Content-Type:
+ - application/json; charset=UTF-8
+ status: 200 OK
+ code: 200
+ duration: 613.84925ms
@@ -0,0 +1,65 @@
+---
+version: 2
+interactions:
+- id: 0
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 509
+ host: us-east5-aiplatform.googleapis.com
+ body: |
+ {"contents":[{"parts":[{"text":"What's the weather in Florence,Italy?"}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"STRING"}},"required":["location"],"type":"OBJECT"}}]}]}
+ form:
+ alt:
+ - sse
+ headers:
+ Content-Type:
+ - application/json
+ User-Agent:
+ - google-genai-sdk/1.29.0 gl-go/go1.25.0
+ url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-flash:streamGenerateContent?alt=sse
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
@@ -0,0 +1,154 @@
+---
+version: 2
+interactions:
+- id: 0
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 826
+ host: us-east5-aiplatform.googleapis.com
+ body: |
+ {"contents":[{"parts":[{"text":"Add and multiply the number 2 and 3"}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant. CRITICAL: Always use both add and multiply at the same time ALWAYS."}],"role":"user"},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Add two numbers","name":"add","parameters":{"properties":{"a":{"description":"first number","type":"INTEGER"},"b":{"description":"second number","type":"INTEGER"}},"required":["a","b"],"type":"OBJECT"}},{"description":"Multiply two numbers","name":"multiply","parameters":{"properties":{"a":{"description":"first number","type":"INTEGER"},"b":{"description":"second number","type":"INTEGER"}},"required":["a","b"],"type":"OBJECT"}}]}]}
+ headers:
+ Content-Type:
+ - application/json
+ User-Agent:
+ - google-genai-sdk/1.29.0 gl-go/go1.25.0
+ url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-pro:generateContent
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
+ uncompressed: true
+ body: |
+ {
+ "candidates": [
+ {
+ "content": {
+ "role": "model",
+ "parts": [
+ {
+ "functionCall": {
+ "name": "add",
+ "args": {
+ "a": 2,
+ "b": 3
+ }
+ },
+ "thoughtSignature": "CqQCAR/MhbZLwIC6tafwHAkCxScqjr2T0r1NLWoahLzRTjgt+N9/7szY8vWOM7QZWZZ88VI9n2FshjX2uMxOuA17pXgQkyvSD3RFCTbzN46tFVYUY+ZyOLMM5YXSyHV40LjXUjbuzMAl/zy+m3ePoYHjQa6xnYhjBPSb/By2HvrCQeDkvRJlvh0uG6xxUr2+0mH0T6ml3Dz6M1LIBHIQiQb20vaPtYn2AyboMVIZA2wFPr14kQhVrOec6fwLc9EtVhoEQO+l+/wPIKfbSdxoX1iA9WqgcdarYtREK7FMcM7afsFKpxziZzPw8BEOAmR2piTTSLPpRckvvB0AkRs25Cnq8IYd2A6D543MpTWrZVcvMcLxL9SJ1DGitNCwc3T7NrPRxR6M+w=="
+ },
+ {
+ "functionCall": {
+ "name": "multiply",
+ "args": {
+ "a": 2,
+ "b": 3
+ }
+ }
+ }
+ ]
+ },
+ "finishReason": "STOP",
+ "avgLogprobs": -0.074593436717987058
+ }
+ ],
+ "usageMetadata": {
+ "promptTokenCount": 60,
+ "candidatesTokenCount": 10,
+ "totalTokenCount": 149,
+ "trafficType": "ON_DEMAND",
+ "promptTokensDetails": [
+ {
+ "modality": "TEXT",
+ "tokenCount": 60
+ }
+ ],
+ "candidatesTokensDetails": [
+ {
+ "modality": "TEXT",
+ "tokenCount": 10
+ }
+ ],
+ "thoughtsTokenCount": 79
+ },
+ "modelVersion": "gemini-2.5-pro",
+ "createTime": "2025-10-10T17:54:09.984997Z",
+ "responseId": "QUjpaKWPPNOJ0ekPr4ebwAs"
+ }
+ headers:
+ Content-Type:
+ - application/json; charset=UTF-8
+ status: 200 OK
+ code: 200
+ duration: 2.03884825s
+- id: 1
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 1173
+ host: us-east5-aiplatform.googleapis.com
+ body: |
@@ -0,0 +1,65 @@
+---
+version: 2
+interactions:
+- id: 0
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 809
+ host: us-east5-aiplatform.googleapis.com
+ body: |
+ {"contents":[{"parts":[{"text":"Add and multiply the number 2 and 3"}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant. Always use both add and multiply at the same time."}],"role":"user"},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Add two numbers","name":"add","parameters":{"properties":{"a":{"description":"first number","type":"INTEGER"},"b":{"description":"second number","type":"INTEGER"}},"required":["a","b"],"type":"OBJECT"}},{"description":"Multiply two numbers","name":"multiply","parameters":{"properties":{"a":{"description":"first number","type":"INTEGER"},"b":{"description":"second number","type":"INTEGER"}},"required":["a","b"],"type":"OBJECT"}}]}]}
+ form:
+ alt:
+ - sse
+ headers:
+ Content-Type:
+ - application/json
+ User-Agent:
+ - google-genai-sdk/1.29.0 gl-go/go1.25.0
+ url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-pro:streamGenerateContent?alt=sse
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
@@ -0,0 +1,70 @@
+---
+version: 2
+interactions:
+- id: 0
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 202
+ host: us-east5-aiplatform.googleapis.com
+ body: |
+ {"contents":[{"parts":[{"text":"Say hi in Portuguese"}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"}}
+ headers:
+ Content-Type:
+ - application/json
+ User-Agent:
+ - google-genai-sdk/1.29.0 gl-go/go1.25.0
+ url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-pro:generateContent
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
+ uncompressed: true
+ body: |
+ {
+ "candidates": [
+ {
+ "content": {
+ "role": "model",
+ "parts": [
+ {
+ "text": "Of course!\n\nThe most common ways to say \"hi\" in Portuguese are:\n\n* **Olรก!** (This is the direct translation of \"hello\" and can be used in any situation, formal or informal.)\n* **Oi!** (This is more informal, like \"hi,\" and is extremely common, especially in Brazil.)\n\nYou can also use greetings that change with the time of day:\n\n* **Bom dia** (Good morning)\n* **Boa tarde** (Good afternoon)\n* **Boa noite** (Good evening / Good night)"
+ }
+ ]
+ },
+ "finishReason": "STOP",
+ "avgLogprobs": -1.9789696365106302
+ }
+ ],
+ "usageMetadata": {
+ "promptTokenCount": 9,
+ "candidatesTokenCount": 122,
+ "totalTokenCount": 1356,
+ "trafficType": "ON_DEMAND",
+ "promptTokensDetails": [
+ {
+ "modality": "TEXT",
+ "tokenCount": 9
+ }
+ ],
+ "candidatesTokensDetails": [
+ {
+ "modality": "TEXT",
+ "tokenCount": 122
+ }
+ ],
+ "thoughtsTokenCount": 1225
+ },
+ "modelVersion": "gemini-2.5-pro",
+ "createTime": "2025-10-10T17:53:37.635488Z",
+ "responseId": "IUjpaODkJunqr9wPkPmEqQc"
+ }
+ headers:
+ Content-Type:
+ - application/json; charset=UTF-8
+ status: 200 OK
+ code: 200
+ duration: 14.255680041s
@@ -0,0 +1,34 @@
+---
+version: 2
+interactions:
+- id: 0
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 202
+ host: us-east5-aiplatform.googleapis.com
+ body: |
+ {"contents":[{"parts":[{"text":"Say hi in Portuguese"}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"}}
+ form:
+ alt:
+ - sse
+ headers:
+ Content-Type:
+ - application/json
+ User-Agent:
+ - google-genai-sdk/1.29.0 gl-go/go1.25.0
+ url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-pro:streamGenerateContent?alt=sse
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
@@ -0,0 +1,142 @@
+---
+version: 2
+interactions:
+- id: 0
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 509
+ host: us-east5-aiplatform.googleapis.com
+ body: |
+ {"contents":[{"parts":[{"text":"What's the weather in Florence,Italy?"}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"STRING"}},"required":["location"],"type":"OBJECT"}}]}]}
+ headers:
+ Content-Type:
+ - application/json
+ User-Agent:
+ - google-genai-sdk/1.29.0 gl-go/go1.25.0
+ url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-pro:generateContent
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
+ uncompressed: true
+ body: |
+ {
+ "candidates": [
+ {
+ "content": {
+ "role": "model",
+ "parts": [
+ {
+ "functionCall": {
+ "name": "weather",
+ "args": {
+ "location": "Florence, Italy"
+ }
+ },
+ "thoughtSignature": "Cv4DAR/MhbZ2LpWbGDKTyyTnSEI5Mbxsa8KH+9LlZ7C1whClIZwMMYizqs+M3qhEkbCwG4lqJXruVsWCWHhA8Mth+s3XzLc4cq3DChXa/vjuNuTGi7NWDzjAOA5ZY+BnK658YQvva+1dFinvrKu1H928HLMQkthqikGFX/oEJw+VJo0tKTWAEKU00oL5D3BL10AWE+D7xcuc/sxoEsJXq+cJaZf4TqNuQ2WvsPi0bx+CIqDmCVJ8Zr7S94jYj0CiAX+taFLoPyvpjG79R5kcnqI6euqhckUnsSbG3nXOeHBiNvsaTD3eHjl+lIs6rWOCVu7sQDOQhO2IkZlrVl+/uYzWFLz/4JJYODYtECgJCz7VK5OSeqIx/YOxADIMpCCgF5S74pGz+9o33foKqukPtPHiJ22YMOs37RYFZDR8f5cnvkomHwIChRQ1T723wsGHLK/KD2c6mb2I8eeVtYQwODyP11ryI5r7G7aMUKM6NKu9K/FzlSkURUlJ18hZ1tPaIyFYGys3+WI0Q7CbxP9Yc7M6luXxy8UdiMqZkk7fegM4EO3IVHp4yYB9exU9Y1QjhY1jTsZcgYZd8QMLpI6mRtwnqtsPF6ymqvo9jfxi1FXCAjhyiNjmP1IPjt1hPoYXbOb+Ntbb9XvGxWtGv1ZhVSveggLzbI53wZFTGd6IuhWd"
+ }
+ ]
+ },
+ "finishReason": "STOP",
+ "avgLogprobs": -0.83615646362304685
+ }
+ ],
+ "usageMetadata": {
+ "promptTokenCount": 28,
+ "candidatesTokenCount": 5,
+ "totalTokenCount": 150,
+ "trafficType": "ON_DEMAND",
+ "promptTokensDetails": [
+ {
+ "modality": "TEXT",
+ "tokenCount": 28
+ }
+ ],
+ "candidatesTokensDetails": [
+ {
+ "modality": "TEXT",
+ "tokenCount": 5
+ }
+ ],
+ "thoughtsTokenCount": 117
+ },
+ "modelVersion": "gemini-2.5-pro",
+ "createTime": "2025-10-10T17:54:02.708890Z",
+ "responseId": "OkjpaJqiK6GI0ekPqveHmA4"
+ }
+ headers:
+ Content-Type:
+ - application/json; charset=UTF-8
+ status: 200 OK
+ code: 200
+ duration: 2.841282292s
+- id: 1
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 735
+ host: us-east5-aiplatform.googleapis.com
+ body: |
+ {"contents":[{"parts":[{"text":"What's the weather in Florence,Italy?"}],"role":"user"},{"parts":[{"functionCall":{"args":{"location":"Florence, Italy"},"id":"weather","name":"weather"}}],"role":"model"},{"parts":[{"functionResponse":{"id":"weather","name":"weather","response":{"result":"40 C"}}}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"STRING"}},"required":["location"],"type":"OBJECT"}}]}]}
+ headers:
+ Content-Type:
+ - application/json
+ User-Agent:
+ - google-genai-sdk/1.29.0 gl-go/go1.25.0
+ url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-pro:generateContent
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
+ uncompressed: true
+ body: |
+ {
+ "candidates": [
+ {
+ "content": {
+ "role": "model",
+ "parts": [
+ {
+ "text": "The weather in Florence, Italy is 40 degrees Celsius.\n"
+ }
+ ]
+ },
+ "finishReason": "STOP",
+ "avgLogprobs": -0.07556527001517159
+ }
+ ],
+ "usageMetadata": {
+ "promptTokenCount": 38,
+ "candidatesTokenCount": 14,
+ "totalTokenCount": 52,
+ "trafficType": "ON_DEMAND",
+ "promptTokensDetails": [
+ {
+ "modality": "TEXT",
+ "tokenCount": 38
+ }
+ ],
+ "candidatesTokensDetails": [
+ {
+ "modality": "TEXT",
+ "tokenCount": 14
+ }
+ ]
+ },
+ "modelVersion": "gemini-2.5-pro",
+ "createTime": "2025-10-10T17:54:05.547479Z",
+ "responseId": "PUjpaJe1IbqD0ekPpPnL0A0"
+ }
+ headers:
+ Content-Type:
+ - application/json; charset=UTF-8
+ status: 200 OK
+ code: 200
+ duration: 1.102223375s
@@ -0,0 +1,65 @@
+---
+version: 2
+interactions:
+- id: 0
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 509
+ host: us-east5-aiplatform.googleapis.com
+ body: |
+ {"contents":[{"parts":[{"text":"What's the weather in Florence,Italy?"}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"STRING"}},"required":["location"],"type":"OBJECT"}}]}]}
+ form:
+ alt:
+ - sse
+ headers:
+ Content-Type:
+ - application/json
+ User-Agent:
+ - google-genai-sdk/1.29.0 gl-go/go1.25.0
+ url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-pro:streamGenerateContent?alt=sse
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
@@ -0,0 +1,3 @@
+---
+version: 2
+interactions: []
@@ -0,0 +1,70 @@
+---
+version: 2
+interactions:
+- id: 0
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 180
+ host: us-central1-aiplatform.googleapis.com
+ body: |
+ {"contents":[{"parts":[{"text":"Say hi in Portuguese"}],"role":"user"}],"generationConfig":{},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"}}
+ headers:
+ Content-Type:
+ - application/json
+ User-Agent:
+ - google-genai-sdk/1.25.0 gl-go/go1.25.0
+ url: https://us-central1-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-central1/publishers/google/models/gemini-2.5-flash:generateContent
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
+ uncompressed: true
+ body: |
+ {
+ "candidates": [
+ {
+ "content": {
+ "role": "model",
+ "parts": [
+ {
+ "text": "Olรก!"
+ }
+ ]
+ },
+ "finishReason": "STOP",
+ "avgLogprobs": -0.57995378971099854
+ }
+ ],
+ "usageMetadata": {
+ "promptTokenCount": 9,
+ "candidatesTokenCount": 2,
+ "totalTokenCount": 37,
+ "trafficType": "ON_DEMAND",
+ "promptTokensDetails": [
+ {
+ "modality": "TEXT",
+ "tokenCount": 9
+ }
+ ],
+ "candidatesTokensDetails": [
+ {
+ "modality": "TEXT",
+ "tokenCount": 2
+ }
+ ],
+ "thoughtsTokenCount": 26
+ },
+ "modelVersion": "gemini-2.5-flash",
+ "createTime": "2025-09-24T19:46:03.607780Z",
+ "responseId": "e0rUaKSMJb-gm9IP0PuYmQo"
+ }
+ headers:
+ Content-Type:
+ - application/json; charset=UTF-8
+ status: 200 OK
+ code: 200
+ duration: 1.489268833s
@@ -0,0 +1,70 @@
+---
+version: 2
+interactions:
+- id: 0
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 180
+ host: us-central1-aiplatform.googleapis.com
+ body: |
+ {"contents":[{"parts":[{"text":"Say hi in Portuguese"}],"role":"user"}],"generationConfig":{},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"}}
+ headers:
+ Content-Type:
+ - application/json
+ User-Agent:
+ - google-genai-sdk/1.25.0 gl-go/go1.25.0
+ url: https://us-central1-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-central1/publishers/google/models/gemini-2.5-pro:generateContent
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
+ uncompressed: true
+ body: |
+ {
+ "candidates": [
+ {
+ "content": {
+ "role": "model",
+ "parts": [
+ {
+ "text": "Of course! The most common ways to say \"hi\" in Portuguese are:\n\n* **Olรก** (oh-LAH) - This is the equivalent of \"hello\" and can be used in any situation.\n* **Oi** (oy) - This is more informal, like \"hi,\" and is extremely common, especially in Brazil.\n\nYou can also use a greeting depending on the time of day:\n\n* **Bom dia** (bohm JEE-ah) - Good morning\n* **Boa tarde** (BOH-ah TAR-jee) - Good afternoon\n* **Boa noite** (BOH-ah NOY-tchee) - Good evening / Good night"
+ }
+ ]
+ },
+ "finishReason": "STOP",
+ "avgLogprobs": -0.93591674386638479
+ }
+ ],
+ "usageMetadata": {
+ "promptTokenCount": 9,
+ "candidatesTokenCount": 146,
+ "totalTokenCount": 905,
+ "trafficType": "ON_DEMAND",
+ "promptTokensDetails": [
+ {
+ "modality": "TEXT",
+ "tokenCount": 9
+ }
+ ],
+ "candidatesTokensDetails": [
+ {
+ "modality": "TEXT",
+ "tokenCount": 146
+ }
+ ],
+ "thoughtsTokenCount": 750
+ },
+ "modelVersion": "gemini-2.5-pro",
+ "createTime": "2025-09-24T19:46:04.550048Z",
+ "responseId": "fErUaKDJIaChmecP8LzZwQs"
+ }
+ headers:
+ Content-Type:
+ - application/json; charset=UTF-8
+ status: 200 OK
+ code: 200
+ duration: 8.665756459s