From 014decbfa729b2738fd9c7e1bdfd55d3425eed47 Mon Sep 17 00:00:00 2001 From: Bruno Scheufler Date: Mon, 16 Dec 2024 08:11:55 +0100 Subject: [PATCH 1/5] upstream inngest --- examples/connect/main.go | 9 ++++++ go.mod | 2 +- go.sum | 2 ++ handler.go | 2 +- .../inngest/inngest/pkg/consts/consts.go | 21 +++++++++++-- .../inngest/inngest/pkg/consts/otel.go | 2 ++ .../inngest/inngest/pkg/event/event.go | 1 + .../pkg/execution/state/driver_response.go | 15 +++++++++ .../inngest/pkg/execution/state/opcode.go | 31 +++++++++++++++++++ .../inngest/pkg/execution/state/state.go | 2 ++ .../inngest/inngest/pkg/inngest/graph.go | 3 ++ .../inngest/inngest/pkg/logger/stdlib.go | 20 +++++++++--- .../pkg/telemetry/exporters/convert.go | 2 ++ .../inngest/pkg/telemetry/trace/tracer.go | 2 +- .../inngest/proto/gen/run/v2/run.pb.go | 8 +++-- vendor/modules.txt | 2 +- 16 files changed, 110 insertions(+), 14 deletions(-) diff --git a/examples/connect/main.go b/examples/connect/main.go index e74eb295..77dac6ec 100644 --- a/examples/connect/main.go +++ b/examples/connect/main.go @@ -3,7 +3,9 @@ package main import ( "context" "fmt" + "github.com/inngest/inngest/pkg/logger" "os" + "strings" "github.com/inngest/inngestgo" ) @@ -15,6 +17,13 @@ func main() { h := inngestgo.NewHandler("connect-test", inngestgo.HandlerOpts{ SigningKey: &key, Dev: inngestgo.BoolPtr(true), + Logger: logger.StdlibLogger(ctx), + ConnectURLs: []string{ + "ws://unavailable-1", + fmt.Sprintf("%s/connect", strings.Replace(inngestgo.DevServerURL(), "http", "ws", 1)), + "ws://unavailable-2", + "ws://unavailable-3", + }, }) f := inngestgo.CreateFunction( diff --git a/go.mod b/go.mod index 498f876a..bdc234c6 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/google/uuid v1.6.0 github.com/gosimple/slug v1.12.0 github.com/gowebpki/jcs v1.0.0 - github.com/inngest/inngest v1.3.1-0.20241122155305-f9a9e9ca9b15 + github.com/inngest/inngest v1.3.3-0.20241214115712-303a81fc478c github.com/oklog/ulid/v2 v2.1.0 github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 github.com/sashabaranov/go-openai v1.35.6 diff --git a/go.sum b/go.sum index 0e4ca995..50fd5296 100644 --- a/go.sum +++ b/go.sum @@ -63,6 +63,8 @@ github.com/inngest/inngest v1.2.1-0.20241121162138-fa921e44acf1 h1:yVbhmibleJZrX github.com/inngest/inngest v1.2.1-0.20241121162138-fa921e44acf1/go.mod h1:+Nl49tpdy+gRzEYHgEb3eNV7aheh8iXyP15XKc+nVU4= github.com/inngest/inngest v1.3.1-0.20241122155305-f9a9e9ca9b15 h1:akZNhly7HjVQW5WHMwt/Y4C2m5DeWJCo7+qlmlnUNpw= github.com/inngest/inngest v1.3.1-0.20241122155305-f9a9e9ca9b15/go.mod h1:WtTSpwUMRNc5ZbuPUSlHWF0GI0ntQ2YJ438LJEzxFkc= +github.com/inngest/inngest v1.3.3-0.20241214115712-303a81fc478c h1:2SndkXi0j9zeQoHIkr3RDsmA2HC1uv3BwxRyFmQfm4o= +github.com/inngest/inngest v1.3.3-0.20241214115712-303a81fc478c/go.mod h1:OSG+TvlA3XPIBXfNQJyynTLYPLwJkEq5eU5gIJFYiak= github.com/karlseguin/ccache/v2 v2.0.8 h1:lT38cE//uyf6KcFok0rlgXtGFBWxkI6h/qg4tbFyDnA= github.com/karlseguin/ccache/v2 v2.0.8/go.mod h1:2BDThcfQMf/c0jnZowt16eW405XIqZPavt+HoYEtcxQ= github.com/karlseguin/expect v1.0.2-0.20190806010014-778a5f0c6003 h1:vJ0Snvo+SLMY72r5J4sEfkuE7AFbixEP2qRbEcum/wA= diff --git a/handler.go b/handler.go index d5b38823..defdc5fa 100644 --- a/handler.go +++ b/handler.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "io" + "log/slog" "net/http" "net/url" "os" @@ -24,7 +25,6 @@ import ( "github.com/inngest/inngestgo/internal/sdkrequest" "github.com/inngest/inngestgo/internal/types" "github.com/inngest/inngestgo/step" - "log/slog" ) var ( diff --git a/vendor/github.com/inngest/inngest/pkg/consts/consts.go b/vendor/github.com/inngest/inngest/pkg/consts/consts.go index 37ef8bc8..39993a8b 100644 --- a/vendor/github.com/inngest/inngest/pkg/consts/consts.go +++ b/vendor/github.com/inngest/inngest/pkg/consts/consts.go @@ -1,8 +1,9 @@ package consts import ( - "github.com/google/uuid" "time" + + "github.com/google/uuid" ) const ( @@ -28,8 +29,19 @@ const ( // our system. MaxFunctionTimeout = 2 * time.Hour - // MaxBodySize is the maximum payload size read on any HTTP response. - MaxBodySize = 1024 * 1024 * 4 // 4MB + // MaxStepOutputSize is the maximum size of the output of a step. + MaxStepOutputSize = 1024 * 1024 * 4 // 4MB + + // MaxStepInputSize is the maximum size of the input of a step. + MaxStepInputSize = 1024 * 1024 * 4 // 4MB + + // MaxSDKResponseBodySize is the maximum payload size in the response from + // the SDK. + MaxSDKResponseBodySize = MaxStepOutputSize + MaxStepInputSize + + // MaxSDKRequestBodySize is the maximum payload size in the request to the + // SDK. + MaxSDKRequestBodySize = 1024 * 1024 * 4 // 4MB // DefaultMaxStateSizeLimit is the maximum number of bytes of output state per function run allowed. DefaultMaxStateSizeLimit = 1024 * 1024 * 32 // 32MB @@ -123,6 +135,9 @@ const ( PauseExpiredDeletionGracePeriod = time.Second * 10 DefaultQueueShardName = "default" + + // Minimum number of pauses before using the aggregate pause handler. + AggregatePauseThreshold = 50 ) var ( diff --git a/vendor/github.com/inngest/inngest/pkg/consts/otel.go b/vendor/github.com/inngest/inngest/pkg/consts/otel.go index dc830ea6..f52e2f7a 100644 --- a/vendor/github.com/inngest/inngest/pkg/consts/otel.go +++ b/vendor/github.com/inngest/inngest/pkg/consts/otel.go @@ -40,6 +40,7 @@ const ( OtelSysFunctionStatusCode = "sys.function.status.code" OtelSysFunctionOutput = "sys.function.output" OtelSysFunctionLink = "sys.function.link" + OtelSysFunctionHasAI = "sys.function.hasAI" OtelSysStepID = "sys.step.id" OtelSysStepDisplayName = "sys.step.display.name" @@ -60,6 +61,7 @@ const ( OtelSysStepAIRequest = "sys.step.ai.req" // ai request metadata OtelSysStepAIResponse = "sys.step.ai.res" // ai response metadata OtelSysStepRunType = "sys.step.run.type" + OtelSysStepPlan = "sys.step.plan" // indicate this is a planning step OtelSysStepSleepEndAt = "sys.step.sleep.end" diff --git a/vendor/github.com/inngest/inngest/pkg/event/event.go b/vendor/github.com/inngest/inngest/pkg/event/event.go index 2f60edec..b7cf6d72 100644 --- a/vendor/github.com/inngest/inngest/pkg/event/event.go +++ b/vendor/github.com/inngest/inngest/pkg/event/event.go @@ -20,6 +20,7 @@ const ( InternalNamePrefix = "inngest/" FnFailedName = InternalNamePrefix + "function.failed" FnFinishedName = InternalNamePrefix + "function.finished" + FnCancelledName = InternalNamePrefix + "function.cancelled" // InvokeEventName is the event name used to invoke specific functions via an // API. Note that invoking functions still sends an event in the usual manner. InvokeFnName = InternalNamePrefix + "function.invoked" diff --git a/vendor/github.com/inngest/inngest/pkg/execution/state/driver_response.go b/vendor/github.com/inngest/inngest/pkg/execution/state/driver_response.go index 172fbd63..0b911553 100644 --- a/vendor/github.com/inngest/inngest/pkg/execution/state/driver_response.go +++ b/vendor/github.com/inngest/inngest/pkg/execution/state/driver_response.go @@ -126,6 +126,21 @@ func (r DriverResponse) NextRetryAt() *time.Time { return r.RetryAt } +// HasAI checks if any ops in the response are related to AI. +func (r DriverResponse) HasAI() bool { + if r.Generator == nil { + return false + } + + for _, op := range r.Generator { + if op.HasAI() { + return true + } + } + + return false +} + func (r DriverResponse) Error() string { if r.Err == nil { return "" diff --git a/vendor/github.com/inngest/inngest/pkg/execution/state/opcode.go b/vendor/github.com/inngest/inngest/pkg/execution/state/opcode.go index a9afb4f6..ff6c1068 100644 --- a/vendor/github.com/inngest/inngest/pkg/execution/state/opcode.go +++ b/vendor/github.com/inngest/inngest/pkg/execution/state/opcode.go @@ -5,6 +5,7 @@ import ( "fmt" "time" + "github.com/inngest/inngest/pkg/consts" "github.com/inngest/inngest/pkg/dateutil" "github.com/inngest/inngest/pkg/enums" "github.com/inngest/inngest/pkg/event" @@ -12,6 +13,11 @@ import ( "github.com/xhit/go-str2duration/v2" ) +var ( + ErrStepInputTooLarge = fmt.Errorf("step input size is greater than the limit") + ErrStepOutputTooLarge = fmt.Errorf("step output size is greater than the limit") +) + type GeneratorOpcode struct { // Op represents the type of operation invoked in the function. Op enums.Opcode `json:"op"` @@ -36,6 +42,18 @@ type GeneratorOpcode struct { DisplayName *string `json:"displayName"` } +func (g GeneratorOpcode) Validate() error { + if input, _ := g.Input(); input != "" && len(input) > consts.MaxStepInputSize { + return ErrStepOutputTooLarge + } + + if output, _ := g.Output(); output != "" && len(output) > consts.MaxStepOutputSize { + return ErrStepOutputTooLarge + } + + return nil +} + // Get the name of the step as defined in code by the user. func (g GeneratorOpcode) UserDefinedName() string { if g.DisplayName != nil { @@ -48,6 +66,19 @@ func (g GeneratorOpcode) UserDefinedName() string { return g.Name } +// HasAI checks if this op is related to AI. +func (g GeneratorOpcode) HasAI() bool { + if g.Op == enums.OpcodeAIGateway { + return true + } + + if g.RunType() == "step.ai.wrap" { + return true + } + + return false +} + // Get the stringified input of the step, if `step.Run` was passed inputs // or if we're using request offloading. func (g GeneratorOpcode) Input() (string, error) { diff --git a/vendor/github.com/inngest/inngest/pkg/execution/state/state.go b/vendor/github.com/inngest/inngest/pkg/execution/state/state.go index 17403a0d..95a77271 100644 --- a/vendor/github.com/inngest/inngest/pkg/execution/state/state.go +++ b/vendor/github.com/inngest/inngest/pkg/execution/state/state.go @@ -233,6 +233,7 @@ type Metadata struct { // SpanID is the spanID used for this function run. SpanID string `json:"sid"` + HasAI bool `json:"hasAI,omitempty"` } func (md *Metadata) GetSpanID() (*trace.SpanID, error) { @@ -248,6 +249,7 @@ type MetadataUpdate struct { DisableImmediateExecution bool `json:"disableImmediateExecution,omitempty"` RequestVersion int `json:"rv"` StartedAt time.Time `json:"sat"` + HasAI bool `json:"hasAI,omitempty"` } // State represents the current state of a fn run. It is data-structure diff --git a/vendor/github.com/inngest/inngest/pkg/inngest/graph.go b/vendor/github.com/inngest/inngest/pkg/inngest/graph.go index 45d9656b..a7df8545 100644 --- a/vendor/github.com/inngest/inngest/pkg/inngest/graph.go +++ b/vendor/github.com/inngest/inngest/pkg/inngest/graph.go @@ -18,6 +18,9 @@ type Edge struct { // // We cannot use "Incoming" here as the incoming name still needs to tbe the generator. IncomingGeneratorStep string `json:"gen,omitempty"` + // IncomingGeneratorStepName is the name from step planned. it should be empty for + // other cases + IncomingGeneratorStepName string `json:"gen_name,omitempty"` // Outgoing is the name of the generator step or step that last ran. Outgoing string `json:"outgoing"` } diff --git a/vendor/github.com/inngest/inngest/pkg/logger/stdlib.go b/vendor/github.com/inngest/inngest/pkg/logger/stdlib.go index ac8fe0c5..51e89b59 100644 --- a/vendor/github.com/inngest/inngest/pkg/logger/stdlib.go +++ b/vendor/github.com/inngest/inngest/pkg/logger/stdlib.go @@ -21,7 +21,17 @@ func StdlibLogger(ctx context.Context) *slog.Logger { logger := ctx.Value(stdlibCtxKey) if logger == nil { return slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{ - Level: StdlibLevel(), + Level: StdlibLevel("LOG_LEVEL"), + })) + } + return logger.(*slog.Logger) +} + +func StdlibLoggerWithCustomVarName(ctx context.Context, varName string) *slog.Logger { + logger := ctx.Value(stdlibCtxKey) + if logger == nil { + return slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{ + Level: StdlibLevel(varName), })) } return logger.(*slog.Logger) @@ -31,8 +41,8 @@ func WithStdlib(ctx context.Context, logger *slog.Logger) context.Context { return context.WithValue(ctx, stdlibCtxKey, logger) } -func StdlibLevel() slog.Level { - switch strings.ToLower(Level()) { +func StdlibLevel(levelVarName string) slog.Level { + switch strings.ToLower(Level(levelVarName)) { case "trace": return slog.LevelDebug case "debug": @@ -49,6 +59,6 @@ func StdlibLevel() slog.Level { } } -func Level() string { - return os.Getenv("LOG_LEVEL") +func Level(levelVarName string) string { + return os.Getenv(levelVarName) } diff --git a/vendor/github.com/inngest/inngest/pkg/telemetry/exporters/convert.go b/vendor/github.com/inngest/inngest/pkg/telemetry/exporters/convert.go index 6e263da1..46695a95 100644 --- a/vendor/github.com/inngest/inngest/pkg/telemetry/exporters/convert.go +++ b/vendor/github.com/inngest/inngest/pkg/telemetry/exporters/convert.go @@ -159,6 +159,8 @@ func toProtoKind(code string) runv2.SpanStepOp { return runv2.SpanStepOp_STEP case enums.OpcodeStepError: return runv2.SpanStepOp_STEP_ERROR + case enums.OpcodeAIGateway: + return runv2.SpanStepOp_AI_GATEWAY default: return runv2.SpanStepOp_RUN diff --git a/vendor/github.com/inngest/inngest/pkg/telemetry/trace/tracer.go b/vendor/github.com/inngest/inngest/pkg/telemetry/trace/tracer.go index acb793e1..a5eaac45 100644 --- a/vendor/github.com/inngest/inngest/pkg/telemetry/trace/tracer.go +++ b/vendor/github.com/inngest/inngest/pkg/telemetry/trace/tracer.go @@ -105,7 +105,7 @@ func (o TracerOpts) MaxPayloadSizeBytes() int { return size } - return (consts.AbsoluteMaxEventSize + consts.MaxBodySize) * 2 + return (consts.AbsoluteMaxEventSize + consts.MaxSDKResponseBodySize) * 2 } func NewUserTracer(ctx context.Context, opts TracerOpts) error { diff --git a/vendor/github.com/inngest/inngest/proto/gen/run/v2/run.pb.go b/vendor/github.com/inngest/inngest/proto/gen/run/v2/run.pb.go index e86521f6..7cabe894 100644 --- a/vendor/github.com/inngest/inngest/proto/gen/run/v2/run.pb.go +++ b/vendor/github.com/inngest/inngest/proto/gen/run/v2/run.pb.go @@ -105,6 +105,7 @@ const ( SpanStepOp_STEP SpanStepOp = 4 SpanStepOp_STEP_ERROR SpanStepOp = 5 SpanStepOp_NONE SpanStepOp = 6 + SpanStepOp_AI_GATEWAY SpanStepOp = 7 ) // Enum value maps for SpanStepOp. @@ -117,6 +118,7 @@ var ( 4: "STEP", 5: "STEP_ERROR", 6: "NONE", + 7: "AI_GATEWAY", } SpanStepOp_value = map[string]int32{ "RUN": 0, @@ -126,6 +128,7 @@ var ( "STEP": 4, "STEP_ERROR": 5, "NONE": 6, + "AI_GATEWAY": 7, } ) @@ -1086,13 +1089,14 @@ var file_run_v2_run_proto_rawDesc = []byte{ 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0xac, 0x02, 0x12, 0x0b, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x90, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x4c, 0x45, 0x44, 0x10, 0xf4, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x53, 0x4b, 0x49, 0x50, - 0x50, 0x45, 0x44, 0x10, 0xd8, 0x04, 0x2a, 0x64, 0x0a, 0x0a, 0x53, 0x70, 0x61, 0x6e, 0x53, 0x74, + 0x50, 0x45, 0x44, 0x10, 0xd8, 0x04, 0x2a, 0x74, 0x0a, 0x0a, 0x53, 0x70, 0x61, 0x6e, 0x53, 0x74, 0x65, 0x70, 0x4f, 0x70, 0x12, 0x07, 0x0a, 0x03, 0x52, 0x55, 0x4e, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x49, 0x4e, 0x56, 0x4f, 0x4b, 0x45, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x4c, 0x45, 0x45, 0x50, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x57, 0x41, 0x49, 0x54, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x54, 0x45, 0x50, 0x10, 0x04, 0x12, 0x0e, 0x0a, 0x0a, 0x53, 0x54, 0x45, 0x50, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, - 0x10, 0x05, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x06, 0x42, 0x33, 0x5a, 0x31, + 0x10, 0x05, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x06, 0x12, 0x0e, 0x0a, 0x0a, + 0x41, 0x49, 0x5f, 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x10, 0x07, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x6e, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x2f, 0x69, 0x6e, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x72, 0x75, 0x6e, 0x2f, 0x76, 0x32, 0x3b, 0x72, 0x75, 0x6e, 0x76, diff --git a/vendor/modules.txt b/vendor/modules.txt index e2e7c15a..2c054d03 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -108,7 +108,7 @@ github.com/hashicorp/hcl/json/token # github.com/inngest/expr v0.0.0-20241106234328-863dff7deec0 ## explicit; go 1.23.2 github.com/inngest/expr -# github.com/inngest/inngest v1.3.1-0.20241122155305-f9a9e9ca9b15 +# github.com/inngest/inngest v1.3.3-0.20241214115712-303a81fc478c ## explicit; go 1.23.2 github.com/inngest/inngest/pkg/connect/types github.com/inngest/inngest/pkg/connect/wsproto From c8c3cdf27b439e38e763b53ac469d183091b470a Mon Sep 17 00:00:00 2001 From: Bruno Scheufler Date: Wed, 18 Dec 2024 21:44:46 +0100 Subject: [PATCH 2/5] use start route --- connect.go | 1 - connect/connection.go | 49 ++- connect/gateway_hosts.go | 59 --- connect/handler.go | 26 +- connect/handshake.go | 7 +- connect/workerapi.go | 61 +++ go.mod | 5 +- go.sum | 12 +- handler.go | 6 - .../inngest/inngest/pkg/consts/consts.go | 2 + .../inngest/pkg/util/aigateway/aigateway.go | 166 +++++++- .../inngest/pkg/util/aigateway/request.go | 6 +- .../inngest/inngest/pkg/util/normalize.go | 6 +- .../proto/gen/connect/v1/connect.pb.go | 259 ++++++++--- .../liushuangls/go-anthropic/v2/.gitignore | 23 + .../liushuangls/go-anthropic/v2/LICENSE | 201 +++++++++ .../liushuangls/go-anthropic/v2/README.md | 382 +++++++++++++++++ .../liushuangls/go-anthropic/v2/batch.go | 288 +++++++++++++ .../liushuangls/go-anthropic/v2/client.go | 167 ++++++++ .../go-anthropic/v2/clientadapter.go | 15 + .../liushuangls/go-anthropic/v2/common.go | 42 ++ .../liushuangls/go-anthropic/v2/complete.go | 58 +++ .../go-anthropic/v2/complete_stream.go | 125 ++++++ .../liushuangls/go-anthropic/v2/config.go | 123 ++++++ .../go-anthropic/v2/count_tokens.go | 31 ++ .../go-anthropic/v2/defaultadapter.go | 36 ++ .../liushuangls/go-anthropic/v2/error.go | 94 ++++ .../liushuangls/go-anthropic/v2/message.go | 402 ++++++++++++++++++ .../go-anthropic/v2/message_stream.go | 243 +++++++++++ .../go-anthropic/v2/ratelimit_headers.go | 85 ++++ .../go-anthropic/v2/vertexadapter.go | 95 +++++ .../go-anthropic/v2/vertexaisupport.go | 12 + .../go-anthropic/v2/vertexerror.go | 35 ++ vendor/modules.txt | 5 +- 34 files changed, 2924 insertions(+), 203 deletions(-) delete mode 100644 connect/gateway_hosts.go create mode 100644 connect/workerapi.go create mode 100644 vendor/github.com/liushuangls/go-anthropic/v2/.gitignore create mode 100644 vendor/github.com/liushuangls/go-anthropic/v2/LICENSE create mode 100644 vendor/github.com/liushuangls/go-anthropic/v2/README.md create mode 100644 vendor/github.com/liushuangls/go-anthropic/v2/batch.go create mode 100644 vendor/github.com/liushuangls/go-anthropic/v2/client.go create mode 100644 vendor/github.com/liushuangls/go-anthropic/v2/clientadapter.go create mode 100644 vendor/github.com/liushuangls/go-anthropic/v2/common.go create mode 100644 vendor/github.com/liushuangls/go-anthropic/v2/complete.go create mode 100644 vendor/github.com/liushuangls/go-anthropic/v2/complete_stream.go create mode 100644 vendor/github.com/liushuangls/go-anthropic/v2/config.go create mode 100644 vendor/github.com/liushuangls/go-anthropic/v2/count_tokens.go create mode 100644 vendor/github.com/liushuangls/go-anthropic/v2/defaultadapter.go create mode 100644 vendor/github.com/liushuangls/go-anthropic/v2/error.go create mode 100644 vendor/github.com/liushuangls/go-anthropic/v2/message.go create mode 100644 vendor/github.com/liushuangls/go-anthropic/v2/message_stream.go create mode 100644 vendor/github.com/liushuangls/go-anthropic/v2/ratelimit_headers.go create mode 100644 vendor/github.com/liushuangls/go-anthropic/v2/vertexadapter.go create mode 100644 vendor/github.com/liushuangls/go-anthropic/v2/vertexaisupport.go create mode 100644 vendor/github.com/liushuangls/go-anthropic/v2/vertexerror.go diff --git a/connect.go b/connect.go index 069d1649..473dfa89 100644 --- a/connect.go +++ b/connect.go @@ -54,7 +54,6 @@ func (h *handler) Connect(ctx context.Context) error { APIBaseUrl: h.GetAPIBaseURL(), IsDev: h.isDev(), DevServerUrl: DevServerURL(), - ConnectUrls: h.ConnectURLs, InstanceId: h.InstanceId, BuildId: h.BuildId, Platform: Ptr(platform()), diff --git a/connect/connection.go b/connect/connection.go index ac0504c4..4bfe3332 100644 --- a/connect/connection.go +++ b/connect/connection.go @@ -24,6 +24,7 @@ type connectReport struct { type connectOpt func(opts *connectOpts) type connectOpts struct { notifyConnectedChan chan struct{} + excludeGateways []string } func withNotifyConnectedChan(ch chan struct{}) connectOpt { @@ -32,6 +33,12 @@ func withNotifyConnectedChan(ch chan struct{}) connectOpt { } } +func withExcludeGateways(exclude ...string) connectOpt { + return func(opts *connectOpts) { + opts.excludeGateways = exclude + } +} + func (h *connectHandler) connect(ctx context.Context, data connectionEstablishData, opts ...connectOpt) { o := connectOpts{} for _, opt := range opts { @@ -39,7 +46,7 @@ func (h *connectHandler) connect(ctx context.Context, data connectionEstablishDa } // Set up connection (including connect handshake protocol) - preparedConn, err := h.prepareConnection(ctx, data) + preparedConn, err := h.prepareConnection(ctx, data, o.excludeGateways) if err != nil { h.logger.Error("could not establish connection", "err", err) @@ -60,7 +67,7 @@ func (h *connectHandler) connect(ctx context.Context, data connectionEstablishDa } // Set up connection lifecycle logic (receiving messages, handling requests, etc.) - err = h.handleConnection(ctx, data, preparedConn.ws, preparedConn.gatewayHost) + err = h.handleConnection(ctx, data, preparedConn.ws, preparedConn.gatewayGroupName) if err != nil { h.logger.Error("could not handle connection", "err", err) @@ -89,23 +96,24 @@ type connectionEstablishData struct { } type connection struct { - ws *websocket.Conn - gatewayHost string - connectionId string + ws *websocket.Conn + gatewayGroupName string + connectionId string } -func (h *connectHandler) prepareConnection(ctx context.Context, data connectionEstablishData) (connection, error) { +func (h *connectHandler) prepareConnection(ctx context.Context, data connectionEstablishData, excludeGateways []string) (connection, error) { connectTimeout, cancelConnectTimeout := context.WithTimeout(ctx, 10*time.Second) defer cancelConnectTimeout() - gatewayHost := h.hostsManager.pickAvailableGateway() - if gatewayHost == "" { - // All gateways have been tried, reset the internal state to retry - h.hostsManager.resetGateways() - - return connection{}, reconnectError{fmt.Errorf("no available gateway hosts")} + startRes, err := h.apiClient.start(ctx, data.hashedSigningKey, &connectproto.StartRequest{ + ExcludeGateways: excludeGateways, + }) + if err != nil { + return connection{}, reconnectError{fmt.Errorf("could not start connection: %w", err)} } + gatewayHost := startRes.GetGatewayEndpoint() + // Establish WebSocket connection to one of the gateways ws, _, err := websocket.Dial(connectTimeout, gatewayHost, &websocket.DialOptions{ Subprotocols: []string{ @@ -113,7 +121,6 @@ func (h *connectHandler) prepareConnection(ctx context.Context, data connectionE }, }) if err != nil { - h.hostsManager.markUnreachableGateway(gatewayHost) return connection{}, reconnectError{fmt.Errorf("could not connect to gateway: %w", err)} } @@ -122,19 +129,19 @@ func (h *connectHandler) prepareConnection(ctx context.Context, data connectionE h.logger.Debug("websocket connection established", "gateway_host", gatewayHost) - err = h.performConnectHandshake(ctx, connectionId.String(), ws, gatewayHost, data) + err = h.performConnectHandshake(ctx, connectionId.String(), ws, startRes, data) if err != nil { return connection{}, reconnectError{fmt.Errorf("could not perform connect handshake: %w", err)} } return connection{ - ws: ws, - gatewayHost: gatewayHost, - connectionId: connectionId.String(), + ws: ws, + gatewayGroupName: startRes.GetGatewayGroup(), + connectionId: connectionId.String(), }, nil } -func (h *connectHandler) handleConnection(ctx context.Context, data connectionEstablishData, ws *websocket.Conn, gatewayHost string) error { +func (h *connectHandler) handleConnection(ctx context.Context, data connectionEstablishData, ws *websocket.Conn, gatewayGroupName string) error { ctx, cancel := context.WithCancel(ctx) defer cancel() @@ -217,8 +224,6 @@ func (h *connectHandler) handleConnection(ctx context.Context, data connectionEs // - Worker shutdown, parent context got cancelled if err := eg.Wait(); err != nil && ctx.Err() == nil { if errors.Is(err, errGatewayDraining) { - h.hostsManager.markDrainingGateway(gatewayHost) - // Gateway is draining and will not accept new connections. // We must reconnect to a different gateway, only then can we close the old connection. waitUntilConnected, doneWaiting := context.WithTimeout(context.Background(), 10*time.Second) @@ -232,7 +237,7 @@ func (h *connectHandler) handleConnection(ctx context.Context, data connectionEs }() // Establish new connection, notify the routine above when the new connection is established - go h.connect(context.Background(), data, withNotifyConnectedChan(notifyConnectedChan)) + go h.connect(context.Background(), data, withNotifyConnectedChan(notifyConnectedChan), withExcludeGateways(gatewayGroupName)) // Wait until the new connection is established before closing the old one <-waitUntilConnected.Done() @@ -303,7 +308,7 @@ func (h *connectHandler) withTemporaryConnection(data connectionEstablishData, h return fmt.Errorf("could not establish connection after %d attempts", maxAttempts) } - ws, err := h.prepareConnection(context.Background(), data) + ws, err := h.prepareConnection(context.Background(), data, nil) if err != nil { attempts++ continue diff --git a/connect/gateway_hosts.go b/connect/gateway_hosts.go deleted file mode 100644 index 73b0639c..00000000 --- a/connect/gateway_hosts.go +++ /dev/null @@ -1,59 +0,0 @@ -package connect - -import "sync" - -type hostsManager struct { - gatewayHosts []string - availableGatewayHosts map[string]struct{} - drainingGatewayHosts map[string]struct{} - unreachableGatewayHosts map[string]struct{} - hostsLock sync.RWMutex -} - -func newHostsManager(gatewayHosts []string) *hostsManager { - hm := &hostsManager{ - gatewayHosts: gatewayHosts, - availableGatewayHosts: make(map[string]struct{}), - drainingGatewayHosts: make(map[string]struct{}), - unreachableGatewayHosts: make(map[string]struct{}), - } - - hm.resetGateways() - - return hm -} - -func (h *hostsManager) pickAvailableGateway() string { - h.hostsLock.RLock() - defer h.hostsLock.RUnlock() - - for host := range h.availableGatewayHosts { - return host - } - return "" -} - -func (h *hostsManager) markDrainingGateway(host string) { - h.hostsLock.Lock() - defer h.hostsLock.Unlock() - delete(h.availableGatewayHosts, host) - h.drainingGatewayHosts[host] = struct{}{} -} - -func (h *hostsManager) markUnreachableGateway(host string) { - h.hostsLock.Lock() - defer h.hostsLock.Unlock() - delete(h.availableGatewayHosts, host) - h.unreachableGatewayHosts[host] = struct{}{} -} - -func (h *hostsManager) resetGateways() { - h.hostsLock.Lock() - defer h.hostsLock.Unlock() - h.availableGatewayHosts = make(map[string]struct{}) - h.drainingGatewayHosts = make(map[string]struct{}) - h.unreachableGatewayHosts = make(map[string]struct{}) - for _, host := range h.gatewayHosts { - h.availableGatewayHosts[host] = struct{}{} - } -} diff --git a/connect/handler.go b/connect/handler.go index 76146898..a40550c0 100644 --- a/connect/handler.go +++ b/connect/handler.go @@ -18,7 +18,6 @@ import ( "log/slog" "os" "runtime" - "strings" "sync" "time" ) @@ -35,6 +34,7 @@ func Connect(ctx context.Context, opts Opts, invoker FunctionInvoker, logger *sl notifyConnectDoneChan: make(chan connectReport), notifyConnectedChan: make(chan struct{}), initiateConnectionChan: make(chan struct{}), + apiClient: newWorkerApiClient(opts.APIBaseUrl), } wp := NewWorkerPool(ctx, opts.WorkerConcurrency, ch.processExecutorRequest) @@ -71,7 +71,6 @@ type Opts struct { APIBaseUrl string IsDev bool DevServerUrl string - ConnectUrls []string InstanceId *string BuildId *string @@ -91,8 +90,6 @@ type connectHandler struct { messageBuffer []*connectproto.ConnectMessage messageBufferLock sync.Mutex - hostsManager *hostsManager - workerPool *workerPool // Notify when connect finishes (either with an error or because the context got canceled) @@ -103,6 +100,8 @@ type connectHandler struct { // Channel to imperatively initiate a connection initiateConnectionChan chan struct{} + + apiClient *workerApiClient } // authContext is wrapper for information related to authentication @@ -132,13 +131,6 @@ func (h *connectHandler) Connect(ctx context.Context) error { return fmt.Errorf("failed to serialize connect config: %w", err) } - hosts := h.connectURLs() - if len(hosts) == 0 { - return fmt.Errorf("no connect URLs provided") - } - - h.hostsManager = newHostsManager(hosts) - var attempts int // We construct a connection loop, which will attempt to reconnect on failure @@ -305,18 +297,6 @@ func (h *connectHandler) processExecutorRequest(msg workerPoolMsg) { } } -func (h *connectHandler) connectURLs() []string { - if len(h.opts.ConnectUrls) > 0 { - return h.opts.ConnectUrls - } - - if h.opts.IsDev { - return []string{fmt.Sprintf("%s/connect", strings.Replace(h.opts.DevServerUrl, "http", "ws", 1))} - } - - return nil -} - func (h *connectHandler) instanceId() string { if h.opts.InstanceId != nil { return *h.opts.InstanceId diff --git a/connect/handshake.go b/connect/handshake.go index 48082326..cab18a87 100644 --- a/connect/handshake.go +++ b/connect/handshake.go @@ -28,7 +28,7 @@ func shouldReconnect(err error) bool { return errors.Is(err, reconnectError{}) } -func (h *connectHandler) performConnectHandshake(ctx context.Context, connectionId string, ws *websocket.Conn, gatewayHost string, data connectionEstablishData) error { +func (h *connectHandler) performConnectHandshake(ctx context.Context, connectionId string, ws *websocket.Conn, startResponse *connectproto.StartResponse, data connectionEstablishData) error { // Wait for gateway hello message { initialMessageTimeout, cancelInitialTimeout := context.WithTimeout(ctx, 5*time.Second) @@ -36,12 +36,10 @@ func (h *connectHandler) performConnectHandshake(ctx context.Context, connection var helloMessage connectproto.ConnectMessage err := wsproto.Read(initialMessageTimeout, ws, &helloMessage) if err != nil { - h.hostsManager.markUnreachableGateway(gatewayHost) return reconnectError{fmt.Errorf("did not receive gateway hello message: %w", err)} } if helloMessage.Kind != connectproto.GatewayMessageType_GATEWAY_HELLO { - h.hostsManager.markUnreachableGateway(gatewayHost) return reconnectError{fmt.Errorf("expected gateway hello message, got %s", helloMessage.Kind)} } @@ -63,7 +61,8 @@ func (h *connectHandler) performConnectHandshake(ctx context.Context, connection ConnectionId: connectionId, }, AuthData: &connectproto.AuthData{ - HashedSigningKey: data.hashedSigningKey, + SessionToken: startResponse.GetSessionToken(), + SyncToken: startResponse.GetSyncToken(), }, AppName: h.opts.AppName, Config: &connectproto.ConfigDetails{ diff --git a/connect/workerapi.go b/connect/workerapi.go new file mode 100644 index 00000000..01d90676 --- /dev/null +++ b/connect/workerapi.go @@ -0,0 +1,61 @@ +package connect + +import ( + "bytes" + "context" + "fmt" + "github.com/inngest/inngest/proto/gen/connect/v1" + "google.golang.org/protobuf/proto" + "io" + "net/http" +) + +type workerApiClient struct { + client http.Client + apiBaseUrl string +} + +func newWorkerApiClient(apiBaseUrl string) *workerApiClient { + return &workerApiClient{ + apiBaseUrl: apiBaseUrl, + } +} + +func (a *workerApiClient) start(ctx context.Context, hashedSigningKey []byte, req *connect.StartRequest) (*connect.StartResponse, error) { + reqBody, err := proto.Marshal(req) + if err != nil { + return nil, fmt.Errorf("could not marshal start request: %w", err) + } + + httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, fmt.Sprintf("%s/v0/connect/start", a.apiBaseUrl), bytes.NewBuffer(reqBody)) + if err != nil { + return nil, fmt.Errorf("could not create start request: %w", err) + } + + httpReq.Header.Set("Content-Type", "application/protobuf") + httpReq.Header.Set("Authorization", fmt.Sprintf("Bearer %s", string(hashedSigningKey))) + + httpRes, err := a.client.Do(httpReq) + if err != nil { + return nil, fmt.Errorf("could not send start request: %w", err) + } + + defer httpRes.Body.Close() + + if httpRes.StatusCode != http.StatusOK { + return nil, fmt.Errorf("unexpected status code: %d", httpRes.StatusCode) + } + + byt, err := io.ReadAll(httpRes.Body) + if err != nil { + return nil, fmt.Errorf("could not read start response: %w", err) + } + + res := &connect.StartResponse{} + err = proto.Unmarshal(byt, res) + if err != nil { + return nil, fmt.Errorf("could not unmarshal start response: %w", err) + } + + return res, nil +} diff --git a/go.mod b/go.mod index bdc234c6..10f43e4c 100644 --- a/go.mod +++ b/go.mod @@ -7,13 +7,12 @@ require ( github.com/google/uuid v1.6.0 github.com/gosimple/slug v1.12.0 github.com/gowebpki/jcs v1.0.0 - github.com/inngest/inngest v1.3.3-0.20241214115712-303a81fc478c + github.com/inngest/inngest v1.3.4-0.20241218202510-b750c9bf0ba6 github.com/oklog/ulid/v2 v2.1.0 github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 github.com/sashabaranov/go-openai v1.35.6 github.com/stretchr/testify v1.9.0 github.com/xhit/go-str2duration/v2 v2.1.0 - golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c golang.org/x/sync v0.8.0 google.golang.org/protobuf v1.35.1 ) @@ -43,6 +42,7 @@ require ( github.com/inngest/expr v0.0.0-20241106234328-863dff7deec0 // indirect github.com/karlseguin/ccache/v2 v2.0.8 // indirect github.com/klauspost/compress v1.17.2 // indirect + github.com/liushuangls/go-anthropic/v2 v2.12.2 // indirect github.com/magiconair/properties v1.8.5 // indirect github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect @@ -89,6 +89,7 @@ require ( go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.28.0 // indirect + golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect golang.org/x/mod v0.21.0 // indirect golang.org/x/net v0.30.0 // indirect golang.org/x/sys v0.26.0 // indirect diff --git a/go.sum b/go.sum index 50fd5296..96e1369e 100644 --- a/go.sum +++ b/go.sum @@ -59,12 +59,10 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/inngest/expr v0.0.0-20241106234328-863dff7deec0 h1:cqaGD0mx745BYyVGZ3GJsiZETktC64h1r9zdDInmKIs= github.com/inngest/expr v0.0.0-20241106234328-863dff7deec0/go.mod h1:0Dllw9clwlMWWxfiSsHY9VdE+Zjt/8SVCMxK9r39aKE= -github.com/inngest/inngest v1.2.1-0.20241121162138-fa921e44acf1 h1:yVbhmibleJZrXqT4IUIqaA+tAAf4iCmVi2eIct8QHwI= -github.com/inngest/inngest v1.2.1-0.20241121162138-fa921e44acf1/go.mod h1:+Nl49tpdy+gRzEYHgEb3eNV7aheh8iXyP15XKc+nVU4= -github.com/inngest/inngest v1.3.1-0.20241122155305-f9a9e9ca9b15 h1:akZNhly7HjVQW5WHMwt/Y4C2m5DeWJCo7+qlmlnUNpw= -github.com/inngest/inngest v1.3.1-0.20241122155305-f9a9e9ca9b15/go.mod h1:WtTSpwUMRNc5ZbuPUSlHWF0GI0ntQ2YJ438LJEzxFkc= -github.com/inngest/inngest v1.3.3-0.20241214115712-303a81fc478c h1:2SndkXi0j9zeQoHIkr3RDsmA2HC1uv3BwxRyFmQfm4o= -github.com/inngest/inngest v1.3.3-0.20241214115712-303a81fc478c/go.mod h1:OSG+TvlA3XPIBXfNQJyynTLYPLwJkEq5eU5gIJFYiak= +github.com/inngest/inngest v1.3.4-0.20241218201514-632b6fe3c996 h1:vO3bLgmQd/stlTJU/IIRtE+N9D9/LmzC+vfwVyJeNCE= +github.com/inngest/inngest v1.3.4-0.20241218201514-632b6fe3c996/go.mod h1:UfL9PYy1SECtj/vG01UZXPIoEJsamNqRPtz+Uyhli5k= +github.com/inngest/inngest v1.3.4-0.20241218202510-b750c9bf0ba6 h1:znR2kHI/mZhD5RInIanQCVFllzNFhRc8wdL1nOu2umI= +github.com/inngest/inngest v1.3.4-0.20241218202510-b750c9bf0ba6/go.mod h1:UfL9PYy1SECtj/vG01UZXPIoEJsamNqRPtz+Uyhli5k= github.com/karlseguin/ccache/v2 v2.0.8 h1:lT38cE//uyf6KcFok0rlgXtGFBWxkI6h/qg4tbFyDnA= github.com/karlseguin/ccache/v2 v2.0.8/go.mod h1:2BDThcfQMf/c0jnZowt16eW405XIqZPavt+HoYEtcxQ= github.com/karlseguin/expect v1.0.2-0.20190806010014-778a5f0c6003 h1:vJ0Snvo+SLMY72r5J4sEfkuE7AFbixEP2qRbEcum/wA= @@ -76,6 +74,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/liushuangls/go-anthropic/v2 v2.12.2 h1:nq+HR3RYYK4/btEjET8nDenQO3NoSDKAuGXP8qNq2c8= +github.com/liushuangls/go-anthropic/v2 v2.12.2/go.mod h1:5ZwRLF5TQ+y5s/MC9Z1IJYx9WUFgQCKfqFM2xreIQLk= github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= diff --git a/handler.go b/handler.go index defdc5fa..b8fbd821 100644 --- a/handler.go +++ b/handler.go @@ -106,12 +106,6 @@ type HandlerOpts struct { // This only needs to be set when self hosting. RegisterURL *string - // ConnectURLs are the URLs to use for establishing outbound connections. If nil - // this defaults to Inngest's Connect endpoint. - // - // This only needs to be set when self hosting. - ConnectURLs []string - // InstanceId represents a stable identifier to be used for identifying connected SDKs. // This can be a hostname or other identifier that remains stable across restarts. // diff --git a/vendor/github.com/inngest/inngest/pkg/consts/consts.go b/vendor/github.com/inngest/inngest/pkg/consts/consts.go index 39993a8b..b78fc972 100644 --- a/vendor/github.com/inngest/inngest/pkg/consts/consts.go +++ b/vendor/github.com/inngest/inngest/pkg/consts/consts.go @@ -144,4 +144,6 @@ var ( // DevServerAccountId is the fixed account ID used internally in the dev server. DevServerAccountId = uuid.MustParse("72d87f98-871b-5b9f-a9f1-e9e2ef0a8f55") DevServerEnvId = uuid.MustParse("b711b20a-fecc-4183-b3d5-65da9028d1d1") + + DevServerConnectJwtSecret = []byte("this-does-not-need-to-be-secret") ) diff --git a/vendor/github.com/inngest/inngest/pkg/util/aigateway/aigateway.go b/vendor/github.com/inngest/inngest/pkg/util/aigateway/aigateway.go index e61dd637..ec99f495 100644 --- a/vendor/github.com/inngest/inngest/pkg/util/aigateway/aigateway.go +++ b/vendor/github.com/inngest/inngest/pkg/util/aigateway/aigateway.go @@ -5,6 +5,9 @@ import ( "encoding/json" "fmt" "net/url" + + "github.com/liushuangls/go-anthropic/v2" + "github.com/sashabaranov/go-openai" ) // ParsedRequest represents the parsed request data for a given inference request. @@ -20,17 +23,44 @@ type ParsedInferenceRequest struct { MaxTokens int `json:"max_tokens,omitempty"` MaxCompletionTokens int `json:"max_completion_tokens,omitempty"` StopSequences []string `json:"stop,omitempty"` - // TODO: Input messages and so on. - // TODO: Tools + // Tools represents the tools available in the request + Tools []ToolUseRequest `json:"tools,omitempty"` + // ToolChoice indicates whether the model should automatically choose to use tools, + // is being forced to use a tool, or is being forced to use a _specific_ tool. + ToolChoice string `json:"tool_choice,omitempty"` + // AgentName represents the name of the agent that made this request, if + // provided as a request header. + AgentName string `json:"agent_name"` } // ParsedInferenceResponse represents the parsed output for a given inference request. type ParsedInferenceResponse struct { - ID string `json:"id"` - TokensIn int32 `json:"tokens_in"` - TokensOut int32 `json:"tokens_out"` - StopReason string `json:"stop_reason"` - // TODO: Tool use selections, parsed. + ID string `json:"id"` + TokensIn int32 `json:"tokens_in"` + TokensOut int32 `json:"tokens_out"` + StopReason string `json:"stop_reason,omitempty"` + Tools []ToolUseResponse `json:"tools,omitempty"` + // XXX: We do not yet extract content, just like we do not yet extract prompts. + Error string `json:"error,omitempty"` +} + +type Choice struct { +} + +// ToolUseRequest represents a tool provided to a model in the request. +type ToolUseRequest struct { + Name string `json:"name"` + Description string `json:"description"` + Parameters json.RawMessage `json:"parameters"` +} + +// ToolResponse indicates that the model is asking to invoke a specific tool, using the +// given ID to track the tool's output. +type ToolUseResponse struct { + // ID represents the ID assigned to this tool + ID string `json:"id"` + Name string `json:"name"` + Arguments string `json:"arguments"` } func ParseUnknownInput(ctx context.Context, req json.RawMessage) (ParsedInferenceRequest, error) { @@ -56,11 +86,44 @@ func ParseInput(ctx context.Context, req Request) (ParsedInferenceRequest, error fallthrough default: // Parse everything as an OpenAI Chat request. - rf := RFOpenAIChatCompletion{} + rf := OpenAIChatCompletionRequest{} if err := json.Unmarshal(req.Body, &rf); err != nil { return ParsedInferenceRequest{}, err } + // Parse the tool choice. + var toolChoice string + switch t := rf.ToolChoice.(type) { + case string: + toolChoice = t + case openai.ToolChoice: + toolChoice = t.Function.Name + } + + // Parse the tools. + tools := make([]ToolUseRequest, len(rf.Tools)) + for i, t := range rf.Tools { + if t.Function == nil { + continue + } + + var params json.RawMessage + switch typ := t.Function.Parameters.(type) { + case json.RawMessage: + params = typ + case []byte: + params = typ + case string: + params = json.RawMessage(typ) + } + + tools[i] = ToolUseRequest{ + Name: t.Function.Name, + Description: t.Function.Description, + Parameters: params, + } + } + return ParsedInferenceRequest{ Model: rf.Model, Seed: rf.Seed, @@ -69,7 +132,94 @@ func ParseInput(ctx context.Context, req Request) (ParsedInferenceRequest, error MaxTokens: rf.MaxTokens, MaxCompletionTokens: rf.MaxCompletionTokens, StopSequences: rf.Stop, + ToolChoice: toolChoice, + Tools: tools, }, nil } } + +func ParseOutput(ctx context.Context, format string, response []byte) (ParsedInferenceResponse, error) { + switch format { + case FormatAnthropic: + r := anthropic.MessagesResponse{} + err := json.Unmarshal(response, &r) + if err != nil { + return ParsedInferenceResponse{}, fmt.Errorf("error parsing openai response: %w", err) + } + + if r.Type == anthropic.MessagesResponseTypeError { + r := anthropic.ErrorResponse{} + err := json.Unmarshal(response, &r) + if err != nil { + return ParsedInferenceResponse{Error: "anthropic API error"}, fmt.Errorf("error parsing openai response: %w", err) + } + msg := "anthropic API error" + if r.Error != nil { + msg = string(r.Error.Type) + } + return ParsedInferenceResponse{ + Error: msg, + }, fmt.Errorf("anthropic api error: %s", msg) + } + + tools := []ToolUseResponse{} + for _, m := range r.Content { + switch m.Type { + case "text": + // ignore, for now + case "tool_use": + tools = append(tools, ToolUseResponse{ + ID: m.ID, + Name: m.Name, + Arguments: string(m.Input), + }) + } + } + + return ParsedInferenceResponse{ + ID: r.ID, + TokensIn: int32(r.Usage.InputTokens), + TokensOut: int32(r.Usage.OutputTokens), + StopReason: string(r.StopReason), + Tools: tools, + }, nil + case FormatOpenAIChat: + fallthrough + default: + // OpenAI Chat is the default format, so fall through to the default. + r := openai.ChatCompletionResponse{} + err := json.Unmarshal(response, &r) + if err != nil { + return ParsedInferenceResponse{}, fmt.Errorf("error parsing openai response: %w", err) + } + + if len(r.Choices) == 0 { + return ParsedInferenceResponse{ + ID: r.ID, + TokensIn: int32(r.Usage.PromptTokens), + TokensOut: int32(r.Usage.CompletionTokens), + }, fmt.Errorf("no choices returned in openai api response") + } + + choice := r.Choices[0] + // XXX: We do not support n>1 in OpenAI requests just yet + + tools := make([]ToolUseResponse, len(choice.Message.ToolCalls)) + for i, t := range choice.Message.ToolCalls { + tools[i] = ToolUseResponse{ + ID: t.ID, + Name: t.Function.Name, + Arguments: t.Function.Arguments, + } + } + + return ParsedInferenceResponse{ + ID: r.ID, + TokensIn: int32(r.Usage.PromptTokens), + TokensOut: int32(r.Usage.CompletionTokens), + StopReason: string(choice.FinishReason), + Tools: tools, + }, nil + } +} diff --git a/vendor/github.com/inngest/inngest/pkg/util/aigateway/request.go b/vendor/github.com/inngest/inngest/pkg/util/aigateway/request.go index 3a40b6a1..564915dd 100644 --- a/vendor/github.com/inngest/inngest/pkg/util/aigateway/request.go +++ b/vendor/github.com/inngest/inngest/pkg/util/aigateway/request.go @@ -83,5 +83,7 @@ func (r Request) HTTPRequest() (*http.Request, error) { return req, nil } -// RFOpenAIChatCompletion represents an OpenAI compatible format. -type RFOpenAIChatCompletion openai.ChatCompletionRequest +type ( + // OpenAIChatCompletionRequest represents an OpenAI compatible format. + OpenAIChatCompletionRequest openai.ChatCompletionRequest +) diff --git a/vendor/github.com/inngest/inngest/pkg/util/normalize.go b/vendor/github.com/inngest/inngest/pkg/util/normalize.go index 4dca7497..2d885f21 100644 --- a/vendor/github.com/inngest/inngest/pkg/util/normalize.go +++ b/vendor/github.com/inngest/inngest/pkg/util/normalize.go @@ -18,8 +18,10 @@ func NormalizeAppURL(u string, forceHTTPS bool) string { parsed = stripDeployID(*parsed) if forceHTTPS { - if parsed.Scheme != "https" { - parsed.Scheme = "https" + isWebSocket := strings.HasPrefix(parsed.Scheme, "ws") + parsed.Scheme = "https" + if isWebSocket { + parsed.Scheme = "wss" } } diff --git a/vendor/github.com/inngest/inngest/proto/gen/connect/v1/connect.pb.go b/vendor/github.com/inngest/inngest/proto/gen/connect/v1/connect.pb.go index 226ec61e..799ee508 100644 --- a/vendor/github.com/inngest/inngest/proto/gen/connect/v1/connect.pb.go +++ b/vendor/github.com/inngest/inngest/proto/gen/connect/v1/connect.pb.go @@ -143,10 +143,11 @@ func (SDKResponseStatus) EnumDescriptor() ([]byte, []int) { type ConnectionStatus int32 const ( - ConnectionStatus_CONNECTED ConnectionStatus = 0 - ConnectionStatus_READY ConnectionStatus = 1 - ConnectionStatus_DRAINING ConnectionStatus = 2 - ConnectionStatus_DISCONNECTED ConnectionStatus = 3 + ConnectionStatus_CONNECTED ConnectionStatus = 0 + ConnectionStatus_READY ConnectionStatus = 1 + ConnectionStatus_DRAINING ConnectionStatus = 2 + ConnectionStatus_DISCONNECTING ConnectionStatus = 3 + ConnectionStatus_DISCONNECTED ConnectionStatus = 4 ) // Enum value maps for ConnectionStatus. @@ -155,13 +156,15 @@ var ( 0: "CONNECTED", 1: "READY", 2: "DRAINING", - 3: "DISCONNECTED", + 3: "DISCONNECTING", + 4: "DISCONNECTED", } ConnectionStatus_value = map[string]int32{ - "CONNECTED": 0, - "READY": 1, - "DRAINING": 2, - "DISCONNECTED": 3, + "CONNECTED": 0, + "READY": 1, + "DRAINING": 2, + "DISCONNECTING": 3, + "DISCONNECTED": 4, } ) @@ -468,9 +471,8 @@ type AuthData struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - HashedSigningKey []byte `protobuf:"bytes,1,opt,name=hashed_signing_key,json=hashedSigningKey,proto3" json:"hashed_signing_key,omitempty"` - AccountId string `protobuf:"bytes,2,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"` - EnvId string `protobuf:"bytes,3,opt,name=env_id,json=envId,proto3" json:"env_id,omitempty"` + SessionToken string `protobuf:"bytes,1,opt,name=session_token,json=sessionToken,proto3" json:"session_token,omitempty"` + SyncToken string `protobuf:"bytes,2,opt,name=sync_token,json=syncToken,proto3" json:"sync_token,omitempty"` } func (x *AuthData) Reset() { @@ -503,23 +505,16 @@ func (*AuthData) Descriptor() ([]byte, []int) { return file_connect_v1_connect_proto_rawDescGZIP(), []int{4} } -func (x *AuthData) GetHashedSigningKey() []byte { +func (x *AuthData) GetSessionToken() string { if x != nil { - return x.HashedSigningKey - } - return nil -} - -func (x *AuthData) GetAccountId() string { - if x != nil { - return x.AccountId + return x.SessionToken } return "" } -func (x *AuthData) GetEnvId() string { +func (x *AuthData) GetSyncToken() string { if x != nil { - return x.EnvId + return x.SyncToken } return "" } @@ -1189,6 +1184,120 @@ func (x *ConnGroup) GetBuildId() string { return "" } +type StartResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + GatewayEndpoint string `protobuf:"bytes,1,opt,name=gateway_endpoint,json=gatewayEndpoint,proto3" json:"gateway_endpoint,omitempty"` + GatewayGroup string `protobuf:"bytes,2,opt,name=gateway_group,json=gatewayGroup,proto3" json:"gateway_group,omitempty"` + SessionToken string `protobuf:"bytes,3,opt,name=session_token,json=sessionToken,proto3" json:"session_token,omitempty"` + SyncToken string `protobuf:"bytes,4,opt,name=sync_token,json=syncToken,proto3" json:"sync_token,omitempty"` +} + +func (x *StartResponse) Reset() { + *x = StartResponse{} + mi := &file_connect_v1_connect_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StartResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StartResponse) ProtoMessage() {} + +func (x *StartResponse) ProtoReflect() protoreflect.Message { + mi := &file_connect_v1_connect_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StartResponse.ProtoReflect.Descriptor instead. +func (*StartResponse) Descriptor() ([]byte, []int) { + return file_connect_v1_connect_proto_rawDescGZIP(), []int{13} +} + +func (x *StartResponse) GetGatewayEndpoint() string { + if x != nil { + return x.GatewayEndpoint + } + return "" +} + +func (x *StartResponse) GetGatewayGroup() string { + if x != nil { + return x.GatewayGroup + } + return "" +} + +func (x *StartResponse) GetSessionToken() string { + if x != nil { + return x.SessionToken + } + return "" +} + +func (x *StartResponse) GetSyncToken() string { + if x != nil { + return x.SyncToken + } + return "" +} + +type StartRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ExcludeGateways []string `protobuf:"bytes,1,rep,name=exclude_gateways,json=excludeGateways,proto3" json:"exclude_gateways,omitempty"` +} + +func (x *StartRequest) Reset() { + *x = StartRequest{} + mi := &file_connect_v1_connect_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StartRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StartRequest) ProtoMessage() {} + +func (x *StartRequest) ProtoReflect() protoreflect.Message { + mi := &file_connect_v1_connect_proto_msgTypes[14] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StartRequest.ProtoReflect.Descriptor instead. +func (*StartRequest) Descriptor() ([]byte, []int) { + return file_connect_v1_connect_proto_rawDescGZIP(), []int{14} +} + +func (x *StartRequest) GetExcludeGateways() []string { + if x != nil { + return x.ExcludeGateways + } + return nil +} + var File_connect_v1_connect_proto protoreflect.FileDescriptor var file_connect_v1_connect_proto_rawDesc = []byte{ @@ -1225,14 +1334,12 @@ var file_connect_v1_connect_proto_rawDesc = []byte{ 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x70, 0x69, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x70, - 0x69, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x22, 0x6e, 0x0a, 0x08, 0x41, 0x75, 0x74, 0x68, 0x44, - 0x61, 0x74, 0x61, 0x12, 0x2c, 0x0a, 0x12, 0x68, 0x61, 0x73, 0x68, 0x65, 0x64, 0x5f, 0x73, 0x69, - 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x10, 0x68, 0x61, 0x73, 0x68, 0x65, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4b, 0x65, - 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, - 0x12, 0x15, 0x0a, 0x06, 0x65, 0x6e, 0x76, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x65, 0x6e, 0x76, 0x49, 0x64, 0x22, 0xaa, 0x04, 0x0a, 0x18, 0x57, 0x6f, 0x72, 0x6b, + 0x69, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x22, 0x4e, 0x0a, 0x08, 0x41, 0x75, 0x74, 0x68, 0x44, + 0x61, 0x74, 0x61, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x79, 0x6e, 0x63, + 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x79, + 0x6e, 0x63, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xaa, 0x04, 0x0a, 0x18, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x3c, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, @@ -1352,38 +1459,54 @@ var file_connect_v1_connect_proto_rawDesc = []byte{ 0x63, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x1e, 0x0a, 0x08, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x07, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, - 0x69, 0x64, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x2a, - 0xf0, 0x01, 0x0a, 0x12, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, - 0x59, 0x5f, 0x48, 0x45, 0x4c, 0x4c, 0x4f, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x57, 0x4f, 0x52, - 0x4b, 0x45, 0x52, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x10, 0x01, 0x12, 0x1c, 0x0a, - 0x18, 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, - 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x02, 0x12, 0x1c, 0x0a, 0x18, 0x47, - 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x4f, 0x52, 0x5f, - 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x57, 0x4f, 0x52, - 0x4b, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12, 0x57, - 0x4f, 0x52, 0x4b, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x41, 0x43, - 0x4b, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x57, 0x4f, 0x52, 0x4b, 0x45, 0x52, 0x5f, 0x52, 0x45, - 0x50, 0x4c, 0x59, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x57, 0x4f, 0x52, 0x4b, 0x45, 0x52, 0x5f, - 0x50, 0x41, 0x55, 0x53, 0x45, 0x10, 0x07, 0x12, 0x14, 0x0a, 0x10, 0x57, 0x4f, 0x52, 0x4b, 0x45, - 0x52, 0x5f, 0x48, 0x45, 0x41, 0x52, 0x54, 0x42, 0x45, 0x41, 0x54, 0x10, 0x08, 0x12, 0x13, 0x0a, - 0x0f, 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x49, 0x4e, 0x47, - 0x10, 0x09, 0x2a, 0x3b, 0x0a, 0x11, 0x53, 0x44, 0x4b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x11, 0x0a, 0x0d, 0x4e, 0x4f, 0x54, 0x5f, 0x43, - 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x4f, - 0x4e, 0x45, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x2a, - 0x4c, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x01, 0x12, 0x0c, 0x0a, - 0x08, 0x44, 0x52, 0x41, 0x49, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x44, - 0x49, 0x53, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x03, 0x2a, 0x2d, 0x0a, - 0x16, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x13, 0x0a, 0x0f, 0x57, 0x4f, 0x52, 0x4b, 0x45, - 0x52, 0x5f, 0x53, 0x48, 0x55, 0x54, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x42, 0x39, 0x5a, 0x37, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x6e, 0x6e, 0x67, 0x65, - 0x73, 0x74, 0x2f, 0x69, 0x6e, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2f, 0x76, 0x31, 0x3b, - 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x69, 0x64, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x22, + 0xa3, 0x01, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x29, 0x0a, 0x10, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x65, 0x6e, 0x64, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x67, 0x61, 0x74, + 0x65, 0x77, 0x61, 0x79, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, + 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, + 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x79, 0x6e, 0x63, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x39, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x5f, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, + 0x2a, 0xf0, 0x01, 0x0a, 0x12, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x41, 0x54, 0x45, 0x57, + 0x41, 0x59, 0x5f, 0x48, 0x45, 0x4c, 0x4c, 0x4f, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x57, 0x4f, + 0x52, 0x4b, 0x45, 0x52, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x10, 0x01, 0x12, 0x1c, + 0x0a, 0x18, 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, + 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x02, 0x12, 0x1c, 0x0a, 0x18, + 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x4f, 0x52, + 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x57, 0x4f, + 0x52, 0x4b, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12, + 0x57, 0x4f, 0x52, 0x4b, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x41, + 0x43, 0x4b, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x57, 0x4f, 0x52, 0x4b, 0x45, 0x52, 0x5f, 0x52, + 0x45, 0x50, 0x4c, 0x59, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x57, 0x4f, 0x52, 0x4b, 0x45, 0x52, + 0x5f, 0x50, 0x41, 0x55, 0x53, 0x45, 0x10, 0x07, 0x12, 0x14, 0x0a, 0x10, 0x57, 0x4f, 0x52, 0x4b, + 0x45, 0x52, 0x5f, 0x48, 0x45, 0x41, 0x52, 0x54, 0x42, 0x45, 0x41, 0x54, 0x10, 0x08, 0x12, 0x13, + 0x0a, 0x0f, 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x49, 0x4e, + 0x47, 0x10, 0x09, 0x2a, 0x3b, 0x0a, 0x11, 0x53, 0x44, 0x4b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x11, 0x0a, 0x0d, 0x4e, 0x4f, 0x54, 0x5f, + 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x44, + 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, + 0x2a, 0x5f, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x01, 0x12, 0x0c, + 0x0a, 0x08, 0x44, 0x52, 0x41, 0x49, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, + 0x44, 0x49, 0x53, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, + 0x10, 0x0a, 0x0c, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, + 0x04, 0x2a, 0x2d, 0x0a, 0x16, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x44, 0x69, 0x73, 0x63, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x13, 0x0a, 0x0f, 0x57, + 0x4f, 0x52, 0x4b, 0x45, 0x52, 0x5f, 0x53, 0x48, 0x55, 0x54, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x00, + 0x42, 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, + 0x6e, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x2f, 0x69, 0x6e, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( @@ -1399,7 +1522,7 @@ func file_connect_v1_connect_proto_rawDescGZIP() []byte { } var file_connect_v1_connect_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_connect_v1_connect_proto_msgTypes = make([]protoimpl.MessageInfo, 13) +var file_connect_v1_connect_proto_msgTypes = make([]protoimpl.MessageInfo, 15) var file_connect_v1_connect_proto_goTypes = []any{ (GatewayMessageType)(0), // 0: connect.v1.GatewayMessageType (SDKResponseStatus)(0), // 1: connect.v1.SDKResponseStatus @@ -1418,7 +1541,9 @@ var file_connect_v1_connect_proto_goTypes = []any{ (*ConnMetadata)(nil), // 14: connect.v1.ConnMetadata (*SystemAttributes)(nil), // 15: connect.v1.SystemAttributes (*ConnGroup)(nil), // 16: connect.v1.ConnGroup - (*timestamppb.Timestamp)(nil), // 17: google.protobuf.Timestamp + (*StartResponse)(nil), // 17: connect.v1.StartResponse + (*StartRequest)(nil), // 18: connect.v1.StartRequest + (*timestamppb.Timestamp)(nil), // 19: google.protobuf.Timestamp } var file_connect_v1_connect_proto_depIdxs = []int32{ 0, // 0: connect.v1.ConnectMessage.kind:type_name -> connect.v1.GatewayMessageType @@ -1429,7 +1554,7 @@ var file_connect_v1_connect_proto_depIdxs = []int32{ 15, // 5: connect.v1.WorkerConnectRequestData.system_attributes:type_name -> connect.v1.SystemAttributes 1, // 6: connect.v1.SDKResponse.status:type_name -> connect.v1.SDKResponseStatus 2, // 7: connect.v1.ConnMetadata.status:type_name -> connect.v1.ConnectionStatus - 17, // 8: connect.v1.ConnMetadata.last_heartbeat_at:type_name -> google.protobuf.Timestamp + 19, // 8: connect.v1.ConnMetadata.last_heartbeat_at:type_name -> google.protobuf.Timestamp 15, // 9: connect.v1.ConnMetadata.attributes:type_name -> connect.v1.SystemAttributes 14, // 10: connect.v1.ConnGroup.conns:type_name -> connect.v1.ConnMetadata 11, // [11:11] is the sub-list for method output_type @@ -1457,7 +1582,7 @@ func file_connect_v1_connect_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_connect_v1_connect_proto_rawDesc, NumEnums: 4, - NumMessages: 13, + NumMessages: 15, NumExtensions: 0, NumServices: 0, }, diff --git a/vendor/github.com/liushuangls/go-anthropic/v2/.gitignore b/vendor/github.com/liushuangls/go-anthropic/v2/.gitignore new file mode 100644 index 00000000..02ac8955 --- /dev/null +++ b/vendor/github.com/liushuangls/go-anthropic/v2/.gitignore @@ -0,0 +1,23 @@ +# If you prefer the allow list template instead of the deny list, see community template: +# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore +# +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# Go workspace file +go.work + +.idea diff --git a/vendor/github.com/liushuangls/go-anthropic/v2/LICENSE b/vendor/github.com/liushuangls/go-anthropic/v2/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/vendor/github.com/liushuangls/go-anthropic/v2/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/liushuangls/go-anthropic/v2/README.md b/vendor/github.com/liushuangls/go-anthropic/v2/README.md new file mode 100644 index 00000000..273d1851 --- /dev/null +++ b/vendor/github.com/liushuangls/go-anthropic/v2/README.md @@ -0,0 +1,382 @@ +# go-anthropic + +[![Go Reference](https://pkg.go.dev/badge/github.com/liushuangls/go-anthropic/v2.svg)](https://pkg.go.dev/github.com/liushuangls/go-anthropic/v2) +[![Go Report Card](https://goreportcard.com/badge/github.com/liushuangls/go-anthropic/v2)](https://goreportcard.com/report/github.com/liushuangls/go-anthropic/v2) +[![codecov](https://codecov.io/gh/liushuangls/go-anthropic/graph/badge.svg?token=O6JSAOZORX)](https://codecov.io/gh/liushuangls/go-anthropic) +[![Sanity check](https://github.com/liushuangls/go-anthropic/actions/workflows/pr.yml/badge.svg)](https://github.com/liushuangls/go-anthropic/actions/workflows/pr.yml) + +Anthropic Claude API wrapper for Go (Unofficial). Support: + +- Completions +- Streaming Completions +- Messages +- Streaming Messages +- Vision +- Tool use +- Prompt Caching +- PDF +- Token Counting + +## Installation + +``` +go get github.com/liushuangls/go-anthropic/v2 +``` + +Currently, go-anthropic requires Go version 1.21 or greater. + +## Usage + +### Messages example usage: + +```go +package main + +import ( + "errors" + "fmt" + + "github.com/liushuangls/go-anthropic/v2" +) + +func main() { + client := anthropic.NewClient("your anthropic api key") + resp, err := client.CreateMessages(context.Background(), anthropic.MessagesRequest{ + Model: anthropic.ModelClaude3Haiku20240307, + Messages: []anthropic.Message{ + anthropic.NewUserTextMessage("What is your name?"), + }, + MaxTokens: 1000, + }) + if err != nil { + var e *anthropic.APIError + if errors.As(err, &e) { + fmt.Printf("Messages error, type: %s, message: %s", e.Type, e.Message) + } else { + fmt.Printf("Messages error: %v\n", err) + } + return + } + fmt.Println(resp.Content[0].GetText()) +} +``` + +### Messages stream example usage: + +```go +package main + +import ( + "errors" + "fmt" + + "github.com/liushuangls/go-anthropic/v2" +) + +func main() { + client := anthropic.NewClient("your anthropic api key") + resp, err := client.CreateMessagesStream(context.Background(), anthropic.MessagesStreamRequest{ + MessagesRequest: anthropic.MessagesRequest{ + Model: anthropic.ModelClaude3Haiku20240307, + Messages: []anthropic.Message{ + anthropic.NewUserTextMessage("What is your name?"), + }, + MaxTokens: 1000, + }, + OnContentBlockDelta: func(data anthropic.MessagesEventContentBlockDeltaData) { + fmt.Printf("Stream Content: %s\n", data.Delta.Text) + }, + }) + if err != nil { + var e *anthropic.APIError + if errors.As(err, &e) { + fmt.Printf("Messages stream error, type: %s, message: %s", e.Type, e.Message) + } else { + fmt.Printf("Messages stream error: %v\n", err) + } + return + } + fmt.Println(resp.Content[0].GetText()) +} +``` + +### Other examples: + +
+Messages Vision example + +```go +package main + +import ( + "errors" + "fmt" + + "github.com/liushuangls/go-anthropic/v2" +) + +func main() { + client := anthropic.NewClient("your anthropic api key") + + imagePath := "xxx" + imageMediaType := "image/jpeg" + imageFile, err := os.Open(imagePath) + if err != nil { + panic(err) + } + imageData, err := io.ReadAll(imageFile) + if err != nil { + panic(err) + } + + resp, err := client.CreateMessages(context.Background(), anthropic.MessagesRequest{ + Model: anthropic.ModelClaude3Opus20240229, + Messages: []anthropic.Message{ + { + Role: anthropic.RoleUser, + Content: []anthropic.MessageContent{ + anthropic.NewImageMessageContent( + anthropic.NewMessageContentSource( + anthropic.MessagesContentSourceTypeBase64, + imageMediaType, + imageData, + ), + ), + anthropic.NewTextMessageContent("Describe this image."), + }, + }, + }, + MaxTokens: 1000, + }) + if err != nil { + var e *anthropic.APIError + if errors.As(err, &e) { + fmt.Printf("Messages error, type: %s, message: %s", e.Type, e.Message) + } else { + fmt.Printf("Messages error: %v\n", err) + } + return + } + fmt.Println(*resp.Content[0].GetText()) +} +``` +
+ +
+ +Messages Tool use example + +```go +package main + +import ( + "context" + "fmt" + + "github.com/liushuangls/go-anthropic/v2" + "github.com/liushuangls/go-anthropic/v2/jsonschema" +) + +func main() { + client := anthropic.NewClient( + "your anthropic api key", + ) + + request := anthropic.MessagesRequest{ + Model: anthropic.ModelClaude3Haiku20240307, + Messages: []anthropic.Message{ + anthropic.NewUserTextMessage("What is the weather like in San Francisco?"), + }, + MaxTokens: 1000, + Tools: []anthropic.ToolDefinition{ + { + Name: "get_weather", + Description: "Get the current weather in a given location", + InputSchema: jsonschema.Definition{ + Type: jsonschema.Object, + Properties: map[string]jsonschema.Definition{ + "location": { + Type: jsonschema.String, + Description: "The city and state, e.g. San Francisco, CA", + }, + "unit": { + Type: jsonschema.String, + Enum: []string{"celsius", "fahrenheit"}, + Description: "The unit of temperature, either 'celsius' or 'fahrenheit'", + }, + }, + Required: []string{"location"}, + }, + }, + }, + } + + resp, err := client.CreateMessages(context.Background(), request) + if err != nil { + panic(err) + } + + request.Messages = append(request.Messages, anthropic.Message{ + Role: anthropic.RoleAssistant, + Content: resp.Content, + }) + + var toolUse *anthropic.MessageContentToolUse + + for _, c := range resp.Content { + if c.Type == anthropic.MessagesContentTypeToolUse { + toolUse = c.MessageContentToolUse + } + } + + if toolUse == nil { + panic("tool use not found") + } + + request.Messages = append(request.Messages, anthropic.NewToolResultsMessage(toolUse.ID, "65 degrees", false)) + + resp, err = client.CreateMessages(context.Background(), request) + if err != nil { + panic(err) + } + fmt.Printf("Response: %+v\n", resp) +} +``` + +
+ +
+Prompt Caching + +doc: https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching + +```go +package main + +import ( + "context" + "errors" + "fmt" + + "github.com/liushuangls/go-anthropic/v2" +) + +func main() { + client := anthropic.NewClient( + "your anthropic api key", + anthropic.WithBetaVersion(anthropic.BetaPromptCaching20240731), + ) + + resp, err := client.CreateMessages( + context.Background(), + anthropic.MessagesRequest{ + Model: anthropic.ModelClaude3Haiku20240307, + MultiSystem: []anthropic.MessageSystemPart{ + { + Type: "text", + Text: "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.", + }, + { + Type: "text", + Text: "", + CacheControl: &anthropic.MessageCacheControl{ + Type: anthropic.CacheControlTypeEphemeral, + }, + }, + }, + Messages: []anthropic.Message{ + anthropic.NewUserTextMessage("Analyze the major themes in Pride and Prejudice.") + }, + MaxTokens: 1000, + }) + if err != nil { + var e *anthropic.APIError + if errors.As(err, &e) { + fmt.Printf("Messages error, type: %s, message: %s", e.Type, e.Message) + } else { + fmt.Printf("Messages error: %v\n", err) + } + return + } + fmt.Printf("Usage: %+v\n", resp.Usage) + fmt.Println(resp.Content[0].GetText()) +} +``` + +
+ +
+VertexAI example + + +If you are using a Google Credentials file, you can use the following code to create a client: + +```go + +package main + +import ( + "context" + "errors" + "fmt" + "os" + + "github.com/liushuangls/go-anthropic/v2" + "golang.org/x/oauth2/google" +) + +func main() { + credBytes, err := os.ReadFile("") + if err != nil { + fmt.Println("Error reading file") + return + } + + ts, err := google.JWTAccessTokenSourceWithScope(credBytes, "https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/cloud-platform.read-only") + if err != nil { + fmt.Println("Error creating token source") + return + } + + // use JWTAccessTokenSourceWithScope + token, err := ts.Token() + if err != nil { + fmt.Println("Error getting token") + return + } + + fmt.Println(token.AccessToken) + + client := anthropic.NewClient(token.AccessToken, anthropic.WithVertexAI("", "")) + + resp, err := client.CreateMessagesStream(context.Background(), anthropic.MessagesStreamRequest{ + MessagesRequest: anthropic.MessagesRequest{ + Model: anthropic.ModelClaude3Haiku20240307, + Messages: []anthropic.Message{ + anthropic.NewUserTextMessage("What is your name?"), + }, + MaxTokens: 1000, + }, + OnContentBlockDelta: func(data anthropic.MessagesEventContentBlockDeltaData) { + fmt.Printf("Stream Content: %s\n", *data.Delta.Text) + }, + }) + if err != nil { + var e *anthropic.APIError + if errors.As(err, &e) { + fmt.Printf("Messages stream error, type: %s, message: %s", e.Type, e.Message) + } else { + fmt.Printf("Messages stream error: %v\n", err) + } + return + } + fmt.Println(resp.Content[0].GetText()) +} + +``` +
+ +## Acknowledgments +The following project had particular influence on go-anthropic is design. + +- [sashabaranov/go-openai](https://github.com/sashabaranov/go-openai) diff --git a/vendor/github.com/liushuangls/go-anthropic/v2/batch.go b/vendor/github.com/liushuangls/go-anthropic/v2/batch.go new file mode 100644 index 00000000..b73e9167 --- /dev/null +++ b/vendor/github.com/liushuangls/go-anthropic/v2/batch.go @@ -0,0 +1,288 @@ +package anthropic + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "net/url" + "time" +) + +type ResultType string + +const ( + ResultTypeSucceeded ResultType = "succeeded" + ResultTypeErrored ResultType = "errored" + ResultTypeCanceled ResultType = "canceled" + ResultTypeExpired ResultType = "expired" +) + +type BatchId string + +type BatchResponseType string + +const ( + BatchResponseTypeMessageBatch BatchResponseType = "message_batch" +) + +type ProcessingStatus string + +const ( + ProcessingStatusInProgress ProcessingStatus = "in_progress" + ProcessingStatusCanceling ProcessingStatus = "canceling" + ProcessingStatusEnded ProcessingStatus = "ended" +) + +// While in beta, batches may contain up to 10,000 requests and be up to 32 MB in total size. +type BatchRequest struct { + Requests []InnerRequests `json:"requests"` +} + +type InnerRequests struct { + CustomId string `json:"custom_id"` + Params MessagesRequest `json:"params"` +} + +// All times returned in RFC 3339 +type BatchResponse struct { + httpHeader + + BatchRespCore +} + +type BatchRespCore struct { + Id BatchId `json:"id"` + Type BatchResponseType `json:"type"` + ProcessingStatus ProcessingStatus `json:"processing_status"` + RequestCounts RequestCounts `json:"request_counts"` + EndedAt *time.Time `json:"ended_at"` + CreatedAt time.Time `json:"created_at"` + ExpiresAt time.Time `json:"expires_at"` + ArchivedAt *time.Time `json:"archived_at"` + CancelInitiatedAt *time.Time `json:"cancel_initiated_at"` + ResultsUrl *string `json:"results_url"` +} + +type RequestCounts struct { + Processing int `json:"processing"` + Succeeded int `json:"succeeded"` + Errored int `json:"errored"` + Canceled int `json:"canceled"` + Expired int `json:"expired"` +} + +func (c *Client) CreateBatch( + ctx context.Context, + request BatchRequest, +) (*BatchResponse, error) { + var setters []requestSetter + if len(c.config.BetaVersion) > 0 { + setters = append(setters, withBetaVersion(c.config.BetaVersion...)) + } + + urlSuffix := "/messages/batches" + req, err := c.newRequest(ctx, http.MethodPost, urlSuffix, request, setters...) + if err != nil { + return nil, err + } + + var response BatchResponse + err = c.sendRequest(req, &response) + + return &response, err +} + +func (c *Client) RetrieveBatch( + ctx context.Context, + batchId BatchId, +) (*BatchResponse, error) { + var setters []requestSetter + if len(c.config.BetaVersion) > 0 { + setters = append(setters, withBetaVersion(c.config.BetaVersion...)) + } + + urlSuffix := "/messages/batches/" + string(batchId) + req, err := c.newRequest(ctx, http.MethodGet, urlSuffix, nil, setters...) + if err != nil { + return nil, err + } + + var response BatchResponse + err = c.sendRequest(req, &response) + + return &response, err +} + +type BatchResultCore struct { + Type ResultType `json:"type"` + Result MessagesResponse `json:"message"` +} + +type BatchResult struct { + CustomId string `json:"custom_id"` + Result BatchResultCore `json:"result"` +} + +type RetrieveBatchResultsResponse struct { + httpHeader + + // Each line in the file is a JSON object containing the result of a + // single request in the Message Batch. Results are not guaranteed to + // be in the same order as requests. Use the custom_id field to match + // results to requests. + + Responses []BatchResult + RawResponse []byte +} + +func (c *Client) RetrieveBatchResults( + ctx context.Context, + batchId BatchId, +) (*RetrieveBatchResultsResponse, error) { + var setters []requestSetter + if len(c.config.BetaVersion) > 0 { + setters = append(setters, withBetaVersion(c.config.BetaVersion...)) + } + + // The documentation states that the URL should be obtained from the results_url field in the batch response. + // It clearly states that the URL should 'not be assumed'. However this seems to work fine. + urlSuffix := "/messages/batches/" + string(batchId) + "/results" + req, err := c.newRequest(ctx, http.MethodGet, urlSuffix, nil, setters...) + if err != nil { + return nil, err + } + + var response RetrieveBatchResultsResponse + + res, err := c.config.HTTPClient.Do(req) + if err != nil { + return nil, err + } + defer res.Body.Close() + + response.SetHeader(res.Header) + + if err := c.handlerRequestError(res); err != nil { + return nil, err + } + + response.RawResponse, err = io.ReadAll(res.Body) + if err != nil { + return nil, err + } + + response.Responses, err = decodeRawResponse(response.RawResponse) + if err != nil { + return nil, err + } + + return &response, err +} + +func decodeRawResponse(rawResponse []byte) ([]BatchResult, error) { + // This looks fishy, but this logic works. + // https://goplay.tools/snippet/tDPm3GJVv0_s + var results []BatchResult + for _, line := range bytes.Split(rawResponse, []byte("\n")) { + if len(line) == 0 { + continue + } + + var parsed BatchResult + err := json.Unmarshal(line, &parsed) + if err != nil { + return nil, err + } + + results = append(results, parsed) + } + + return results, nil +} + +type ListBatchesResponse struct { + httpHeader + + Data []BatchRespCore `json:"data"` + HasMore bool `json:"has_more"` + FirstId *BatchId `json:"first_id"` + LastId *BatchId `json:"last_id"` +} + +type ListBatchesRequest struct { + BeforeId *string `json:"before_id,omitempty"` + AfterId *string `json:"after_id,omitempty"` + Limit *int `json:"limit,omitempty"` +} + +func (l ListBatchesRequest) validate() error { + if l.Limit != nil && (*l.Limit < 1 || *l.Limit > 100) { + return errors.New("limit must be between 1 and 100") + } + + return nil +} + +func (c *Client) ListBatches( + ctx context.Context, + lBatchReq ListBatchesRequest, +) (*ListBatchesResponse, error) { + var setters []requestSetter + if len(c.config.BetaVersion) > 0 { + setters = append(setters, withBetaVersion(c.config.BetaVersion...)) + } + + if err := lBatchReq.validate(); err != nil { + return nil, err + } + + urlSuffix := "/messages/batches" + + v := url.Values{} + if lBatchReq.BeforeId != nil { + v.Set("before_id", *lBatchReq.BeforeId) + } + if lBatchReq.AfterId != nil { + v.Set("after_id", *lBatchReq.AfterId) + } + if lBatchReq.Limit != nil { + v.Set("limit", fmt.Sprintf("%d", *lBatchReq.Limit)) + } + + // encode the query parameters into the URL + urlSuffix += "?" + v.Encode() + req, err := c.newRequest(ctx, http.MethodGet, urlSuffix, nil, setters...) + if err != nil { + return nil, err + } + + var response ListBatchesResponse + err = c.sendRequest(req, &response) + + return &response, err +} + +func (c *Client) CancelBatch( + ctx context.Context, + batchId BatchId, +) (*BatchResponse, error) { + var setters []requestSetter + if len(c.config.BetaVersion) > 0 { + setters = append(setters, withBetaVersion(c.config.BetaVersion...)) + } + + urlSuffix := "/messages/batches/" + string(batchId) + "/cancel" + req, err := c.newRequest(ctx, http.MethodPost, urlSuffix, nil, setters...) + if err != nil { + return nil, err + } + + var response BatchResponse + err = c.sendRequest(req, &response) + + return &response, err +} diff --git a/vendor/github.com/liushuangls/go-anthropic/v2/client.go b/vendor/github.com/liushuangls/go-anthropic/v2/client.go new file mode 100644 index 00000000..f80fde7a --- /dev/null +++ b/vendor/github.com/liushuangls/go-anthropic/v2/client.go @@ -0,0 +1,167 @@ +package anthropic + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "net/http" +) + +type Client struct { + config ClientConfig +} + +type Response interface { + SetHeader(http.Header) +} + +type httpHeader http.Header + +func (h *httpHeader) SetHeader(header http.Header) { + *h = httpHeader(header) +} + +func (h *httpHeader) Header() http.Header { + return http.Header(*h) +} + +func (h *httpHeader) GetRateLimitHeaders() (RateLimitHeaders, error) { + return newRateLimitHeaders(h.Header()) +} + +// NewClient create new Anthropic API client +func NewClient(apiKey string, opts ...ClientOption) *Client { + return &Client{ + config: newConfig(apiKey, opts...), + } +} + +func (c *Client) sendRequest(req *http.Request, v Response) error { + res, err := c.config.HTTPClient.Do(req) + if err != nil { + return err + } + defer res.Body.Close() + + v.SetHeader(res.Header) + + if err := c.handlerRequestError(res); err != nil { + return err + } + + if err = json.NewDecoder(res.Body).Decode(v); err != nil { + return err + } + + return nil +} + +func (c *Client) handlerRequestError(resp *http.Response) error { + if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusBadRequest { + body, err := io.ReadAll(resp.Body) + if err != nil { + return fmt.Errorf("error, reading response body: %w", err) + } + + // use the adapter to translate the error, if it can + if err, handled := c.config.Adapter.TranslateError(resp, body); handled { + return err + } + + var errRes ErrorResponse + err = json.Unmarshal(body, &errRes) + if err != nil || errRes.Error == nil { + reqErr := RequestError{ + StatusCode: resp.StatusCode, + Err: err, + Body: body, + } + return &reqErr + } + + return fmt.Errorf("error, status code: %d, message: %w", resp.StatusCode, errRes.Error) + } + return nil +} + +type requestSetter func(req *http.Request) + +func withBetaVersion(betaVersion ...BetaVersion) requestSetter { + version := "" + for i, v := range betaVersion { + version += string(v) + if i < len(betaVersion)-1 { + version += "," + } + } + + return func(req *http.Request) { + req.Header.Set("anthropic-beta", version) + } +} + +func (c *Client) newRequest( + ctx context.Context, + method, urlSuffix string, + body any, + requestSetters ...requestSetter, +) (req *http.Request, err error) { + + // prepare the request + var fullURL string + fullURL, err = c.config.Adapter.PrepareRequest(c, method, urlSuffix, body) + if err != nil { + return nil, err + } + + var reqBody []byte + if body != nil { + reqBody, err = json.Marshal(body) + if err != nil { + return nil, err + } + } + + req, err = http.NewRequestWithContext( + ctx, + method, + fullURL, + bytes.NewBuffer(reqBody), + ) + if err != nil { + return nil, err + } + + req.Header.Set("Content-Type", "application/json; charset=utf-8") + req.Header.Set("Accept", "application/json; charset=utf-8") + + // set any provider-specific headers (including Authorization) + c.config.Adapter.SetRequestHeaders(c, req) + + for _, setter := range requestSetters { + setter(req) + } + + return req, nil +} + +func (c *Client) newStreamRequest( + ctx context.Context, + method, urlSuffix string, + body any, + requestSetters ...requestSetter, +) (req *http.Request, + err error) { + req, err = c.newRequest(ctx, method, urlSuffix, body, requestSetters...) + if err != nil { + return nil, err + } + + req.Header.Set("Accept", "text/event-stream") + req.Header.Set("Cache-Control", "no-cache") + req.Header.Set("Connection", "keep-alive") + + return req, nil +} diff --git a/vendor/github.com/liushuangls/go-anthropic/v2/clientadapter.go b/vendor/github.com/liushuangls/go-anthropic/v2/clientadapter.go new file mode 100644 index 00000000..5fc55307 --- /dev/null +++ b/vendor/github.com/liushuangls/go-anthropic/v2/clientadapter.go @@ -0,0 +1,15 @@ +package anthropic + +import ( + "net/http" +) + +// ClientAdapter is an interface that defines the methods that allow use of the anthropic API with different providers. +type ClientAdapter interface { + // Translate provider specific errors. Responds with an error and a boolean indicating if the error has been successfully parsed. + TranslateError(resp *http.Response, body []byte) (error, bool) + // Prepare the request for the provider and return the full URL + PrepareRequest(c *Client, method, urlSuffix string, body any) (string, error) + // Set the request headers for the provider + SetRequestHeaders(c *Client, req *http.Request) error +} diff --git a/vendor/github.com/liushuangls/go-anthropic/v2/common.go b/vendor/github.com/liushuangls/go-anthropic/v2/common.go new file mode 100644 index 00000000..17e5dcda --- /dev/null +++ b/vendor/github.com/liushuangls/go-anthropic/v2/common.go @@ -0,0 +1,42 @@ +package anthropic + +type Model string + +const ( + ModelClaude2Dot0 Model = "claude-2.0" + ModelClaude2Dot1 Model = "claude-2.1" + ModelClaude3Opus20240229 Model = "claude-3-opus-20240229" + ModelClaude3Sonnet20240229 Model = "claude-3-sonnet-20240229" + ModelClaude3Dot5Sonnet20240620 Model = "claude-3-5-sonnet-20240620" + ModelClaude3Dot5Sonnet20241022 Model = "claude-3-5-sonnet-20241022" + ModelClaude3Dot5SonnetLatest Model = "claude-3-5-sonnet-latest" + ModelClaude3Haiku20240307 Model = "claude-3-haiku-20240307" + ModelClaude3Dot5HaikuLatest Model = "claude-3-5-haiku-latest" + ModelClaude3Dot5Haiku20241022 Model = "claude-3-5-haiku-20241022" +) + +type ChatRole string + +const ( + RoleUser ChatRole = "user" + RoleAssistant ChatRole = "assistant" +) + +func (m Model) asVertexModel() string { + switch m { + case ModelClaude3Opus20240229: + return "claude-3-opus@20240229" + case ModelClaude3Sonnet20240229: + return "claude-3-sonnet@20240229" + case ModelClaude3Dot5Sonnet20240620: + return "claude-3-5-sonnet@20240620" + case ModelClaude3Dot5Sonnet20241022: + return "claude-3-5-sonnet-v2@20241022" + case ModelClaude3Haiku20240307: + return "claude-3-haiku@20240307" + case ModelClaude3Dot5Haiku20241022: + return "claude-3-5-haiku@20241022" + default: + return string(m) + } +} diff --git a/vendor/github.com/liushuangls/go-anthropic/v2/complete.go b/vendor/github.com/liushuangls/go-anthropic/v2/complete.go new file mode 100644 index 00000000..16ce23f8 --- /dev/null +++ b/vendor/github.com/liushuangls/go-anthropic/v2/complete.go @@ -0,0 +1,58 @@ +package anthropic + +import ( + "context" + "net/http" +) + +type CompleteRequest struct { + Model Model `json:"model"` + Prompt string `json:"prompt"` + MaxTokensToSample int `json:"max_tokens_to_sample"` + + StopSequences []string `json:"stop_sequences,omitempty"` + Temperature *float32 `json:"temperature,omitempty"` + TopP *float32 `json:"top_p,omitempty"` + TopK *int `json:"top_k,omitempty"` + MetaData map[string]any `json:"meta_data,omitempty"` + Stream bool `json:"stream,omitempty"` +} + +func (c *CompleteRequest) SetTemperature(t float32) { + c.Temperature = &t +} + +func (c *CompleteRequest) SetTopP(p float32) { + c.TopP = &p +} + +func (c *CompleteRequest) SetTopK(k int) { + c.TopK = &k +} + +type CompleteResponse struct { + httpHeader + + Type string `json:"type"` + ID string `json:"id"` + Completion string `json:"completion"` + // possible values are: stop_sequence、max_tokens、null + StopReason string `json:"stop_reason"` + Model Model `json:"model"` +} + +func (c *Client) CreateComplete( + ctx context.Context, + request CompleteRequest, +) (response CompleteResponse, err error) { + request.Stream = false + + urlSuffix := "/complete" + req, err := c.newRequest(ctx, http.MethodPost, urlSuffix, &request) + if err != nil { + return + } + + err = c.sendRequest(req, &response) + return +} diff --git a/vendor/github.com/liushuangls/go-anthropic/v2/complete_stream.go b/vendor/github.com/liushuangls/go-anthropic/v2/complete_stream.go new file mode 100644 index 00000000..5b1559ab --- /dev/null +++ b/vendor/github.com/liushuangls/go-anthropic/v2/complete_stream.go @@ -0,0 +1,125 @@ +package anthropic + +import ( + "bufio" + "bytes" + "context" + "encoding/json" + "errors" + "io" + "net/http" +) + +type CompleteEvent string + +const ( + CompleteEventError CompleteEvent = "error" + CompleteEventCompletion CompleteEvent = "completion" + CompleteEventPing CompleteEvent = "ping" +) + +type CompleteStreamRequest struct { + CompleteRequest + + OnCompletion func(CompleteResponse) `json:"-"` + OnPing func(CompleteStreamPingData) `json:"-"` + OnError func(ErrorResponse) `json:"-"` +} + +type CompleteStreamPingData struct { + Type string `json:"type"` +} + +func (c *Client) CreateCompleteStream( + ctx context.Context, + request CompleteStreamRequest, +) (response CompleteResponse, err error) { + request.Stream = true + + urlSuffix := "/complete" + req, err := c.newStreamRequest(ctx, http.MethodPost, urlSuffix, &request) + if err != nil { + return + } + + resp, err := c.config.HTTPClient.Do(req) + if err != nil { + return + } + defer resp.Body.Close() + + response.SetHeader(resp.Header) + + if err := c.handlerRequestError(resp); err != nil { + return response, err + } + + reader := bufio.NewReader(resp.Body) + var ( + event []byte + emptyMessageCount uint + ) + for { + rawLine, readErr := reader.ReadBytes('\n') + if readErr != nil { + if errors.Is(readErr, io.EOF) { + break + } + return response, readErr + } + + noSpaceLine := bytes.TrimSpace(rawLine) + if len(noSpaceLine) == 0 { + continue + } + if bytes.HasPrefix(noSpaceLine, eventPrefix) { + event = bytes.TrimSpace(bytes.TrimPrefix(noSpaceLine, eventPrefix)) + continue + } + if bytes.HasPrefix(noSpaceLine, dataPrefix) { + var ( + data = bytes.TrimPrefix(noSpaceLine, dataPrefix) + eventType = CompleteEvent(event) + ) + switch eventType { + case CompleteEventError: + var d ErrorResponse + if err := json.Unmarshal(data, &d); err != nil { + return response, err + } + if request.OnError != nil { + request.OnError(d) + } + return response, d.Error + case CompleteEventPing: + var d CompleteStreamPingData + if err := json.Unmarshal(data, &d); err != nil { + return response, err + } + if request.OnPing != nil { + request.OnPing(d) + } + continue + case CompleteEventCompletion: + var d CompleteResponse + if err := json.Unmarshal(data, &d); err != nil { + return response, err + } + if request.OnCompletion != nil { + request.OnCompletion(d) + } + response.Type = d.Type + response.ID = d.ID + response.StopReason = d.StopReason + response.Model = d.Model + response.Completion += d.Completion + continue + } + } + emptyMessageCount++ + if emptyMessageCount > c.config.EmptyMessagesLimit { + return response, ErrTooManyEmptyStreamMessages + } + } + return +} diff --git a/vendor/github.com/liushuangls/go-anthropic/v2/config.go b/vendor/github.com/liushuangls/go-anthropic/v2/config.go new file mode 100644 index 00000000..f8deaff5 --- /dev/null +++ b/vendor/github.com/liushuangls/go-anthropic/v2/config.go @@ -0,0 +1,123 @@ +package anthropic + +import ( + "fmt" + "net/http" +) + +const ( + anthropicAPIURLv1 = "https://api.anthropic.com/v1" + defaultEmptyMessagesLimit uint = 300 +) + +type APIVersion string + +const ( + APIVersion20230601 APIVersion = "2023-06-01" + APIVersionVertex20231016 APIVersion = "vertex-2023-10-16" +) + +type BetaVersion string + +const ( + BetaTools20240404 BetaVersion = "tools-2024-04-04" + BetaTools20240516 BetaVersion = "tools-2024-05-16" + BetaPromptCaching20240731 BetaVersion = "prompt-caching-2024-07-31" + BetaMessageBatches20240924 BetaVersion = "message-batches-2024-09-24" + BetaTokenCounting20241101 BetaVersion = "token-counting-2024-11-01" + BetaMaxTokens35Sonnet20240715 BetaVersion = "max-tokens-3-5-sonnet-2024-07-15" +) + +type ApiKeyFunc func() string + +// ClientConfig is a configuration of a client. +type ClientConfig struct { + apiKeyFunc ApiKeyFunc + apiKey string + + BaseURL string + APIVersion APIVersion + BetaVersion []BetaVersion + HTTPClient *http.Client + + EmptyMessagesLimit uint + + Adapter ClientAdapter +} + +type ClientOption func(c *ClientConfig) + +func newConfig(apiKey string, opts ...ClientOption) ClientConfig { + c := ClientConfig{ + apiKey: apiKey, + + BaseURL: anthropicAPIURLv1, + APIVersion: APIVersion20230601, + HTTPClient: &http.Client{}, + + EmptyMessagesLimit: defaultEmptyMessagesLimit, + Adapter: &DefaultAdapter{}, + } + + for _, opt := range opts { + opt(&c) + } + + return c +} + +func (c *ClientConfig) GetApiKey() string { + if c.apiKeyFunc != nil { + return c.apiKeyFunc() + } + return c.apiKey +} + +func WithBaseURL(baseUrl string) ClientOption { + return func(c *ClientConfig) { + c.BaseURL = baseUrl + } +} + +func WithAPIVersion(apiVersion APIVersion) ClientOption { + return func(c *ClientConfig) { + c.APIVersion = apiVersion + } +} + +func WithHTTPClient(cli *http.Client) ClientOption { + return func(c *ClientConfig) { + c.HTTPClient = cli + } +} + +func WithEmptyMessagesLimit(limit uint) ClientOption { + return func(c *ClientConfig) { + c.EmptyMessagesLimit = limit + } +} + +func WithBetaVersion(betaVersion ...BetaVersion) ClientOption { + return func(c *ClientConfig) { + c.BetaVersion = betaVersion + } +} + +func WithVertexAI(projectID string, location string) ClientOption { + return func(c *ClientConfig) { + c.BaseURL = fmt.Sprintf( + "https://%s-aiplatform.googleapis.com/v1/projects/%s/locations/%s/publishers/anthropic/models", + location, + projectID, + location, + ) + c.APIVersion = APIVersionVertex20231016 + c.Adapter = &VertexAdapter{} + } +} + +func WithApiKeyFunc(apiKeyFunc ApiKeyFunc) ClientOption { + return func(c *ClientConfig) { + c.apiKeyFunc = apiKeyFunc + } +} diff --git a/vendor/github.com/liushuangls/go-anthropic/v2/count_tokens.go b/vendor/github.com/liushuangls/go-anthropic/v2/count_tokens.go new file mode 100644 index 00000000..24515658 --- /dev/null +++ b/vendor/github.com/liushuangls/go-anthropic/v2/count_tokens.go @@ -0,0 +1,31 @@ +package anthropic + +import ( + "context" + "net/http" +) + +type CountTokensResponse struct { + httpHeader + + InputTokens int `json:"input_tokens"` +} + +func (c *Client) CountTokens( + ctx context.Context, + request MessagesRequest, +) (response CountTokensResponse, err error) { + var setters []requestSetter + if len(c.config.BetaVersion) > 0 { + setters = append(setters, withBetaVersion(c.config.BetaVersion...)) + } + + urlSuffix := "/messages/count_tokens" + req, err := c.newRequest(ctx, http.MethodPost, urlSuffix, &request, setters...) + if err != nil { + return + } + + err = c.sendRequest(req, &response) + return +} diff --git a/vendor/github.com/liushuangls/go-anthropic/v2/defaultadapter.go b/vendor/github.com/liushuangls/go-anthropic/v2/defaultadapter.go new file mode 100644 index 00000000..e2533e83 --- /dev/null +++ b/vendor/github.com/liushuangls/go-anthropic/v2/defaultadapter.go @@ -0,0 +1,36 @@ +package anthropic + +import ( + "fmt" + "net/http" +) + +var _ ClientAdapter = (*DefaultAdapter)(nil) + +type DefaultAdapter struct { +} + +func (v *DefaultAdapter) TranslateError(resp *http.Response, body []byte) (error, bool) { + return nil, false +} + +func (v *DefaultAdapter) fullURL(baseUrl string, suffix string) string { + // replace the first slash with a colon + return fmt.Sprintf("%s%s", baseUrl, suffix) +} + +func (v *DefaultAdapter) PrepareRequest( + c *Client, + method string, + urlSuffix string, + body any, +) (string, error) { + return v.fullURL(c.config.BaseURL, urlSuffix), nil +} + +func (v *DefaultAdapter) SetRequestHeaders(c *Client, req *http.Request) error { + req.Header.Set("X-Api-Key", c.config.GetApiKey()) + req.Header.Set("Anthropic-Version", string(c.config.APIVersion)) + + return nil +} diff --git a/vendor/github.com/liushuangls/go-anthropic/v2/error.go b/vendor/github.com/liushuangls/go-anthropic/v2/error.go new file mode 100644 index 00000000..11884067 --- /dev/null +++ b/vendor/github.com/liushuangls/go-anthropic/v2/error.go @@ -0,0 +1,94 @@ +package anthropic + +import ( + "errors" + "fmt" +) + +type ErrType string + +const ( + // ErrTypeInvalidRequest There was an issue with the format or content of your request. + ErrTypeInvalidRequest ErrType = "invalid_request_error" + // ErrTypeAuthentication There's an issue with your API key. + ErrTypeAuthentication ErrType = "authentication_error" + // ErrTypePermission Your API key does not have permission to use the specified resource. + ErrTypePermission ErrType = "permission_error" + // ErrTypeNotFound The requested resource was not found. + ErrTypeNotFound ErrType = "not_found_error" + // ErrTypeTooLarge Request exceeds the maximum allowed number of bytes. + ErrTypeTooLarge ErrType = "request_too_large" + // ErrTypeRateLimit Your account has hit a rate limit. + ErrTypeRateLimit ErrType = "rate_limit_error" + // ErrTypeApi An unexpected error has occurred internal to Anthropic's systems. + ErrTypeApi ErrType = "api_error" + // ErrTypeOverloaded Anthropic's API is temporarily overloaded. + ErrTypeOverloaded ErrType = "overloaded_error" +) + +var ( + ErrSteamingNotSupportTools = errors.New("streaming is not yet supported tools") +) + +// APIError provides error information returned by the Anthropic API. +type APIError struct { + Type ErrType `json:"type"` + Message string `json:"message"` +} + +func (e *APIError) IsInvalidRequestErr() bool { + return e.Type == ErrTypeInvalidRequest +} + +func (e *APIError) IsAuthenticationErr() bool { + return e.Type == ErrTypeAuthentication +} + +func (e *APIError) IsPermissionErr() bool { + return e.Type == ErrTypePermission +} + +func (e *APIError) IsNotFoundErr() bool { + return e.Type == ErrTypeNotFound +} + +func (e *APIError) IsTooLargeErr() bool { + return e.Type == ErrTypeTooLarge +} + +func (e *APIError) IsRateLimitErr() bool { + return e.Type == ErrTypeRateLimit +} + +func (e *APIError) IsApiErr() bool { + return e.Type == ErrTypeApi +} + +func (e *APIError) IsOverloadedErr() bool { + return e.Type == ErrTypeOverloaded +} + +// RequestError provides information about generic request errors. +type RequestError struct { + StatusCode int + Err error + Body []byte +} + +type ErrorResponse struct { + Type string `json:"type"` + Error *APIError `json:"error,omitempty"` +} + +func (e *APIError) Error() string { + return fmt.Sprintf("anthropic api error type: %s, message: %s", e.Type, e.Message) +} + +func (e *RequestError) Error() string { + return fmt.Sprintf( + "anthropic request error status code: %d, err: %s, body: %s", + e.StatusCode, + e.Err, + e.Body, + ) +} diff --git a/vendor/github.com/liushuangls/go-anthropic/v2/message.go b/vendor/github.com/liushuangls/go-anthropic/v2/message.go new file mode 100644 index 00000000..88838d5c --- /dev/null +++ b/vendor/github.com/liushuangls/go-anthropic/v2/message.go @@ -0,0 +1,402 @@ +package anthropic + +import ( + "context" + "encoding/json" + "net/http" +) + +type MessagesResponseType string + +const ( + MessagesResponseTypeMessage MessagesResponseType = "message" + MessagesResponseTypeError MessagesResponseType = "error" +) + +type MessagesContentType string + +const ( + MessagesContentTypeText MessagesContentType = "text" + MessagesContentTypeTextDelta MessagesContentType = "text_delta" + MessagesContentTypeImage MessagesContentType = "image" + MessagesContentTypeToolResult MessagesContentType = "tool_result" + MessagesContentTypeToolUse MessagesContentType = "tool_use" + MessagesContentTypeInputJsonDelta MessagesContentType = "input_json_delta" + MessagesContentTypeDocument MessagesContentType = "document" +) + +type MessagesStopReason string + +const ( + MessagesStopReasonEndTurn MessagesStopReason = "end_turn" + MessagesStopReasonMaxTokens MessagesStopReason = "max_tokens" + MessagesStopReasonStopSequence MessagesStopReason = "stop_sequence" + MessagesStopReasonToolUse MessagesStopReason = "tool_use" +) + +type MessagesContentSourceType string + +const ( + MessagesContentSourceTypeBase64 = "base64" +) + +type MessagesRequest struct { + Model Model `json:"model,omitempty"` + AnthropicVersion string `json:"anthropic_version,omitempty"` + Messages []Message `json:"messages"` + MaxTokens int `json:"max_tokens,omitempty"` + + System string `json:"-"` + MultiSystem []MessageSystemPart `json:"-"` + Metadata map[string]any `json:"metadata,omitempty"` + StopSequences []string `json:"stop_sequences,omitempty"` + Stream bool `json:"stream,omitempty"` + Temperature *float32 `json:"temperature,omitempty"` + TopP *float32 `json:"top_p,omitempty"` + TopK *int `json:"top_k,omitempty"` + Tools []ToolDefinition `json:"tools,omitempty"` + ToolChoice *ToolChoice `json:"tool_choice,omitempty"` +} + +func (m MessagesRequest) MarshalJSON() ([]byte, error) { + type Alias MessagesRequest + aux := struct { + System interface{} `json:"system,omitempty"` + Alias + }{ + Alias: (Alias)(m), + } + + // 根据 MultiSystem 是否为空来设置 system 字段 + if len(m.MultiSystem) > 0 { + aux.System = m.MultiSystem + } else if len(m.System) > 0 { + aux.System = m.System + } + + return json.Marshal(aux) +} + +var _ VertexAISupport = (*MessagesRequest)(nil) + +func (m MessagesRequest) GetModel() Model { + return m.Model +} + +func (m *MessagesRequest) SetAnthropicVersion(version APIVersion) { + m.AnthropicVersion = string(version) + m.Model = "" +} + +func (m *MessagesRequest) SetTemperature(t float32) { + m.Temperature = &t +} + +func (m *MessagesRequest) SetTopP(p float32) { + m.TopP = &p +} + +func (m *MessagesRequest) SetTopK(k int) { + m.TopK = &k +} + +func (m *MessagesRequest) IsStreaming() bool { + return m.Stream +} + +type MessageSystemPart struct { + Type string `json:"type"` + Text string `json:"text"` + CacheControl *MessageCacheControl `json:"cache_control,omitempty"` +} + +func NewMultiSystemMessages(texts ...string) []MessageSystemPart { + var systemParts []MessageSystemPart + for _, text := range texts { + systemParts = append(systemParts, NewSystemMessagePart(text)) + } + return systemParts +} + +func NewSystemMessagePart(text string) MessageSystemPart { + return MessageSystemPart{ + Type: "text", + Text: text, + } +} + +type Message struct { + Role ChatRole `json:"role"` + Content []MessageContent `json:"content"` +} + +func NewUserTextMessage(text string) Message { + return Message{ + Role: RoleUser, + Content: []MessageContent{NewTextMessageContent(text)}, + } +} + +func NewAssistantTextMessage(text string) Message { + return Message{ + Role: RoleAssistant, + Content: []MessageContent{NewTextMessageContent(text)}, + } +} + +func NewToolResultsMessage(toolUseID, content string, isError bool) Message { + return Message{ + Role: RoleUser, + Content: []MessageContent{NewToolResultMessageContent(toolUseID, content, isError)}, + } +} + +func (m Message) GetFirstContent() MessageContent { + if len(m.Content) == 0 { + return MessageContent{} + } + return m.Content[0] +} + +type CacheControlType string + +const ( + CacheControlTypeEphemeral CacheControlType = "ephemeral" +) + +type MessageCacheControl struct { + Type CacheControlType `json:"type"` +} + +type MessageContent struct { + Type MessagesContentType `json:"type"` + + Text *string `json:"text,omitempty"` + + Source *MessageContentSource `json:"source,omitempty"` + + *MessageContentToolResult + + *MessageContentToolUse + + PartialJson *string `json:"partial_json,omitempty"` + + CacheControl *MessageCacheControl `json:"cache_control,omitempty"` +} + +func NewTextMessageContent(text string) MessageContent { + return MessageContent{ + Type: MessagesContentTypeText, + Text: &text, + } +} + +func NewImageMessageContent(source MessageContentSource) MessageContent { + return MessageContent{ + Type: MessagesContentTypeImage, + Source: &source, + } +} + +func NewDocumentMessageContent(source MessageContentSource) MessageContent { + return MessageContent{ + Type: MessagesContentTypeDocument, + Source: &source, + } +} + +func NewToolResultMessageContent(toolUseID, content string, isError bool) MessageContent { + return MessageContent{ + Type: MessagesContentTypeToolResult, + MessageContentToolResult: NewMessageContentToolResult(toolUseID, content, isError), + } +} + +func NewToolUseMessageContent(toolUseID, name string, input json.RawMessage) MessageContent { + return MessageContent{ + Type: MessagesContentTypeToolUse, + MessageContentToolUse: NewMessageContentToolUse(toolUseID, name, input), + } +} + +func (m *MessageContent) SetCacheControl(ts ...CacheControlType) { + t := CacheControlTypeEphemeral + if len(ts) > 0 { + t = ts[0] + } + m.CacheControl = &MessageCacheControl{ + Type: t, + } +} + +func (m *MessageContent) GetText() string { + if m.Text != nil { + return *m.Text + } + return "" +} + +func (m *MessageContent) ConcatText(s string) { + if m.Text == nil { + m.Text = &s + } else { + *m.Text += s + } +} + +func (m *MessageContent) MergeContentDelta(mc MessageContent) { + switch mc.Type { + case MessagesContentTypeText: + m.ConcatText(mc.GetText()) + case MessagesContentTypeTextDelta: + m.ConcatText(mc.GetText()) + case MessagesContentTypeImage: + m.Source = mc.Source + case MessagesContentTypeToolResult: + m.MessageContentToolResult = mc.MessageContentToolResult + case MessagesContentTypeToolUse: + m.MessageContentToolUse = &MessageContentToolUse{ + ID: mc.MessageContentToolUse.ID, + Name: mc.MessageContentToolUse.Name, + } + case MessagesContentTypeInputJsonDelta: + if m.PartialJson == nil { + m.PartialJson = mc.PartialJson + } else { + *m.PartialJson += *mc.PartialJson + } + } +} + +type MessageContentToolResult struct { + ToolUseID *string `json:"tool_use_id,omitempty"` + Content []MessageContent `json:"content,omitempty"` + IsError *bool `json:"is_error,omitempty"` +} + +func NewMessageContentToolResult( + toolUseID, content string, + isError bool, +) *MessageContentToolResult { + return &MessageContentToolResult{ + ToolUseID: &toolUseID, + Content: []MessageContent{ + { + Type: MessagesContentTypeText, + Text: &content, + }, + }, + IsError: &isError, + } +} + +type MessageContentSource struct { + Type MessagesContentSourceType `json:"type"` + MediaType string `json:"media_type"` + Data any `json:"data"` +} + +func NewMessageContentSource( + sourceType MessagesContentSourceType, + mediaType string, + data any, +) MessageContentSource { + return MessageContentSource{ + Type: sourceType, + MediaType: mediaType, + Data: data, + } +} + +type MessageContentToolUse struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Input json.RawMessage `json:"input,omitempty"` +} + +func NewMessageContentToolUse( + toolUseId, name string, + input json.RawMessage, +) *MessageContentToolUse { + return &MessageContentToolUse{ + ID: toolUseId, + Name: name, + Input: input, + } +} + +func (c *MessageContentToolUse) UnmarshalInput(v any) error { + return json.Unmarshal(c.Input, v) +} + +type MessagesResponse struct { + httpHeader + + ID string `json:"id"` + Type MessagesResponseType `json:"type"` + Role ChatRole `json:"role"` + Content []MessageContent `json:"content"` + Model Model `json:"model"` + StopReason MessagesStopReason `json:"stop_reason"` + StopSequence string `json:"stop_sequence"` + Usage MessagesUsage `json:"usage"` +} + +// GetFirstContentText get Content[0].Text avoid panic +func (m MessagesResponse) GetFirstContentText() string { + if len(m.Content) == 0 { + return "" + } + return m.Content[0].GetText() +} + +type MessagesUsage struct { + InputTokens int `json:"input_tokens"` + OutputTokens int `json:"output_tokens"` + + // The number of tokens written to the cache when creating a new entry. + CacheCreationInputTokens int `json:"cache_creation_input_tokens,omitempty"` + // The number of tokens retrieved from the cache for associated request. + CacheReadInputTokens int `json:"cache_read_input_tokens,omitempty"` +} + +type ToolDefinition struct { + Name string `json:"name"` + Description string `json:"description,omitempty"` + // InputSchema is an object describing the tool. + // You can pass json.RawMessage to describe the schema, + // or you can pass in a struct which serializes to the proper JSON schema. + // The jsonschema package is provided for convenience, but you should + // consider another specialized library if you require more complex schemas. + InputSchema any `json:"input_schema"` + + CacheControl *MessageCacheControl `json:"cache_control,omitempty"` +} + +type ToolChoice struct { + // oneof: auto(default) any tool + Type string `json:"type"` + Name string `json:"name,omitempty"` +} + +func (c *Client) CreateMessages( + ctx context.Context, + request MessagesRequest, +) (response MessagesResponse, err error) { + request.Stream = false + + var setters []requestSetter + if len(c.config.BetaVersion) > 0 { + setters = append(setters, withBetaVersion(c.config.BetaVersion...)) + } + + urlSuffix := "/messages" + + req, err := c.newRequest(ctx, http.MethodPost, urlSuffix, &request, setters...) + if err != nil { + return + } + + err = c.sendRequest(req, &response) + return +} diff --git a/vendor/github.com/liushuangls/go-anthropic/v2/message_stream.go b/vendor/github.com/liushuangls/go-anthropic/v2/message_stream.go new file mode 100644 index 00000000..9e8256bf --- /dev/null +++ b/vendor/github.com/liushuangls/go-anthropic/v2/message_stream.go @@ -0,0 +1,243 @@ +package anthropic + +import ( + "bufio" + "bytes" + "context" + "encoding/json" + "errors" + "io" + "net/http" + "slices" +) + +var ( + eventPrefix = []byte("event:") + dataPrefix = []byte("data:") + ErrTooManyEmptyStreamMessages = errors.New("stream has sent too many empty messages") +) + +type ( + // MessagesEvent docs: https://docs.anthropic.com/claude/reference/messages-streaming + MessagesEvent string +) + +const ( + MessagesEventError MessagesEvent = "error" + MessagesEventMessageStart MessagesEvent = "message_start" + MessagesEventContentBlockStart MessagesEvent = "content_block_start" + MessagesEventPing MessagesEvent = "ping" + MessagesEventContentBlockDelta MessagesEvent = "content_block_delta" + MessagesEventContentBlockStop MessagesEvent = "content_block_stop" + MessagesEventMessageDelta MessagesEvent = "message_delta" + MessagesEventMessageStop MessagesEvent = "message_stop" +) + +type MessagesStreamRequest struct { + MessagesRequest + + OnError func(ErrorResponse) `json:"-"` + OnPing func(MessagesEventPingData) `json:"-"` + OnMessageStart func(MessagesEventMessageStartData) `json:"-"` + OnContentBlockStart func(MessagesEventContentBlockStartData) `json:"-"` + OnContentBlockDelta func(MessagesEventContentBlockDeltaData) `json:"-"` + OnContentBlockStop func(MessagesEventContentBlockStopData, MessageContent) `json:"-"` + OnMessageDelta func(MessagesEventMessageDeltaData) `json:"-"` + OnMessageStop func(MessagesEventMessageStopData) `json:"-"` +} + +type MessagesEventMessageStartData struct { + Type MessagesEvent `json:"type"` + Message MessagesResponse `json:"message"` +} + +type MessagesEventContentBlockStartData struct { + Type MessagesEvent `json:"type"` + Index int `json:"index"` + ContentBlock MessageContent `json:"content_block"` +} + +type MessagesEventPingData struct { + Type string `json:"type"` +} + +type MessagesEventContentBlockDeltaData struct { + Type string `json:"type"` + Index int `json:"index"` + Delta MessageContent `json:"delta"` +} + +type MessagesEventContentBlockStopData struct { + Type string `json:"type"` + Index int `json:"index"` +} + +type MessagesEventMessageDeltaData struct { + Type string `json:"type"` + Delta MessagesResponse `json:"delta"` + Usage MessagesUsage `json:"usage"` +} + +type MessagesEventMessageStopData struct { + Type string `json:"type"` +} + +func (c *Client) CreateMessagesStream( + ctx context.Context, + request MessagesStreamRequest, +) (response MessagesResponse, err error) { + request.Stream = true + + var setters []requestSetter + if len(c.config.BetaVersion) > 0 { + setters = append(setters, withBetaVersion(c.config.BetaVersion...)) + } + + urlSuffix := "/messages" + + req, err := c.newStreamRequest(ctx, http.MethodPost, urlSuffix, &request, setters...) + if err != nil { + return + } + + resp, err := c.config.HTTPClient.Do(req) + if err != nil { + return + } + defer resp.Body.Close() + + response.SetHeader(resp.Header) + + if err := c.handlerRequestError(resp); err != nil { + return response, err + } + + reader := bufio.NewReader(resp.Body) + var ( + event []byte + emptyMessageCount uint + ) + for { + rawLine, readErr := reader.ReadBytes('\n') + if readErr != nil { + if errors.Is(readErr, io.EOF) { + break + } + return response, readErr + } + + noSpaceLine := bytes.TrimSpace(rawLine) + if len(noSpaceLine) == 0 { + continue + } + if bytes.HasPrefix(noSpaceLine, eventPrefix) { + event = bytes.TrimSpace(bytes.TrimPrefix(noSpaceLine, eventPrefix)) + continue + } + if bytes.HasPrefix(noSpaceLine, dataPrefix) { + var ( + data = bytes.TrimPrefix(noSpaceLine, dataPrefix) + eventType = MessagesEvent(event) + ) + switch eventType { + case MessagesEventError: + var eventData ErrorResponse + if err := json.Unmarshal(data, &eventData); err != nil { + return response, err + } + if request.OnError != nil { + request.OnError(eventData) + } + return response, eventData.Error + case MessagesEventPing: + var d MessagesEventPingData + if err := json.Unmarshal(data, &d); err != nil { + return response, err + } + if request.OnPing != nil { + request.OnPing(d) + } + continue + case MessagesEventMessageStart: + var d MessagesEventMessageStartData + if err := json.Unmarshal(data, &d); err != nil { + return response, err + } + if request.OnMessageStart != nil { + request.OnMessageStart(d) + } + response = d.Message + response.SetHeader(resp.Header) + continue + case MessagesEventContentBlockStart: + var d MessagesEventContentBlockStartData + if err := json.Unmarshal(data, &d); err != nil { + return response, err + } + if request.OnContentBlockStart != nil { + request.OnContentBlockStart(d) + } + response.Content = slices.Insert(response.Content, d.Index, d.ContentBlock) + continue + case MessagesEventContentBlockDelta: + var d MessagesEventContentBlockDeltaData + if err := json.Unmarshal(data, &d); err != nil { + return response, err + } + if request.OnContentBlockDelta != nil { + request.OnContentBlockDelta(d) + } + if len(response.Content)-1 < d.Index { + response.Content = slices.Insert(response.Content, d.Index, d.Delta) + } else { + response.Content[d.Index].MergeContentDelta(d.Delta) + } + continue + case MessagesEventContentBlockStop: + var d MessagesEventContentBlockStopData + if err := json.Unmarshal(data, &d); err != nil { + return response, err + } + var stopContent MessageContent + if len(response.Content) > d.Index { + stopContent = response.Content[d.Index] + if stopContent.Type == MessagesContentTypeToolUse { + stopContent.Input = json.RawMessage(*stopContent.PartialJson) + stopContent.PartialJson = nil + response.Content[d.Index] = stopContent + } + } + if request.OnContentBlockStop != nil { + request.OnContentBlockStop(d, stopContent) + } + continue + case MessagesEventMessageDelta: + var d MessagesEventMessageDeltaData + if err := json.Unmarshal(data, &d); err != nil { + return response, err + } + if request.OnMessageDelta != nil { + request.OnMessageDelta(d) + } + response.StopReason = d.Delta.StopReason + response.StopSequence = d.Delta.StopSequence + response.Usage.OutputTokens = d.Usage.OutputTokens + continue + case MessagesEventMessageStop: + var d MessagesEventMessageStopData + if err := json.Unmarshal(data, &d); err != nil { + return response, err + } + if request.OnMessageStop != nil { + request.OnMessageStop(d) + } + continue + } + } + emptyMessageCount++ + if emptyMessageCount > c.config.EmptyMessagesLimit { + return response, ErrTooManyEmptyStreamMessages + } + } + return +} diff --git a/vendor/github.com/liushuangls/go-anthropic/v2/ratelimit_headers.go b/vendor/github.com/liushuangls/go-anthropic/v2/ratelimit_headers.go new file mode 100644 index 00000000..fae701ff --- /dev/null +++ b/vendor/github.com/liushuangls/go-anthropic/v2/ratelimit_headers.go @@ -0,0 +1,85 @@ +package anthropic + +import ( + "errors" + "fmt" + "net/http" + "strconv" + "time" +) + +type rateLimitHeaderKey string + +const ( + requestsLimit rateLimitHeaderKey = "anthropic-ratelimit-requests-limit" + requestsRemaining rateLimitHeaderKey = "anthropic-ratelimit-requests-remaining" + requestsReset rateLimitHeaderKey = "anthropic-ratelimit-requests-reset" + tokensLimit rateLimitHeaderKey = "anthropic-ratelimit-tokens-limit" + tokensRemaining rateLimitHeaderKey = "anthropic-ratelimit-tokens-remaining" + tokensReset rateLimitHeaderKey = "anthropic-ratelimit-tokens-reset" + retryAfter rateLimitHeaderKey = "retry-after" +) + +type RateLimitHeaders struct { + // The maximum number of requests allowed within the rate limit window. + RequestsLimit int `json:"anthropic-ratelimit-requests-limit"` + // The number of requests remaining within the current rate limit window. + RequestsRemaining int `json:"anthropic-ratelimit-requests-remaining"` + // The time when the request rate limit window will reset, provided in RFC 3339 format. + RequestsReset time.Time `json:"anthropic-ratelimit-requests-reset"` + // The maximum number of tokens allowed within the rate limit window. + TokensLimit int `json:"anthropic-ratelimit-tokens-limit"` + // The number of tokens remaining, rounded to the nearest thousand, within the current rate limit window. + TokensRemaining int `json:"anthropic-ratelimit-tokens-remaining"` + // The time when the token rate limit window will reset, provided in RFC 3339 format. + TokensReset time.Time `json:"anthropic-ratelimit-tokens-reset"` + // The number of seconds until the rate limit window resets. + RetryAfter int `json:"retry-after"` +} + +func newRateLimitHeaders(h http.Header) (RateLimitHeaders, error) { + var errs []error + + parseIntHeader := func(key rateLimitHeaderKey, required bool) int { + value, err := strconv.Atoi(h.Get(string(key))) + if err != nil { + if !required { + return -1 + } + errs = append(errs, fmt.Errorf("failed to parse %s: %w", key, err)) + return 0 + } + return value + } + + parseTimeHeader := func(key rateLimitHeaderKey, required bool) time.Time { + value, err := time.Parse(time.RFC3339, h.Get(string(key))) + if err != nil { + if !required { + return time.Time{} + } + errs = append(errs, fmt.Errorf("failed to parse %s: %w", key, err)) + return time.Time{} + } + return value + } + + headers := RateLimitHeaders{} + headers.RequestsLimit = parseIntHeader(requestsLimit, true) + headers.RequestsRemaining = parseIntHeader(requestsRemaining, true) + headers.RequestsReset = parseTimeHeader(requestsReset, true) + + headers.TokensLimit = parseIntHeader(tokensLimit, true) + headers.TokensRemaining = parseIntHeader(tokensRemaining, true) + headers.TokensReset = parseTimeHeader(tokensReset, true) + + headers.RetryAfter = parseIntHeader(retryAfter, false) // optional + + if len(errs) > 0 { + return headers, fmt.Errorf("error(s) parsing rate limit headers: %w", + errors.Join(errs...), + ) + } + + return headers, nil +} diff --git a/vendor/github.com/liushuangls/go-anthropic/v2/vertexadapter.go b/vendor/github.com/liushuangls/go-anthropic/v2/vertexadapter.go new file mode 100644 index 00000000..9613944b --- /dev/null +++ b/vendor/github.com/liushuangls/go-anthropic/v2/vertexadapter.go @@ -0,0 +1,95 @@ +package anthropic + +import ( + "encoding/json" + "fmt" + "net/http" +) + +var _ ClientAdapter = (*VertexAdapter)(nil) + +type VertexAdapter struct { +} + +func (v *VertexAdapter) TranslateError(resp *http.Response, body []byte) (error, bool) { + switch resp.StatusCode { + case http.StatusUnauthorized, + http.StatusForbidden, + http.StatusNotFound, + http.StatusTooManyRequests: + var errRes VertexAIErrorResponse + err := json.Unmarshal(body, &errRes) + if err != nil { + // it could be an array + var errResArr []VertexAIErrorResponse + err = json.Unmarshal(body, &errResArr) + if err == nil && len(errResArr) > 0 { + errRes = errResArr[0] + } + } + + if err != nil || errRes.Error == nil { + reqErr := RequestError{ + StatusCode: resp.StatusCode, + Err: err, + Body: body, + } + return &reqErr, true + } + return fmt.Errorf( + "error, status code: %d, message: %w", + resp.StatusCode, + errRes.Error, + ), true + } + return nil, false +} + +func (v *VertexAdapter) fullURL(baseUrl string, suffix string, model Model) string { + // replace the first slash with a colon + return fmt.Sprintf("%s/%s:%s", baseUrl, model.asVertexModel(), suffix[1:]) +} + +func (v *VertexAdapter) translateUrlSuffix(suffix string, stream bool) (string, error) { + switch suffix { + case "/messages": + if stream { + return ":streamRawPredict", nil + } else { + return ":rawPredict", nil + } + } + + return "", fmt.Errorf("unknown suffix: %s", suffix) +} + +func (v *VertexAdapter) PrepareRequest( + c *Client, + method string, + urlSuffix string, + body any, +) (string, error) { + // if the body implements the ModelGetter interface, use the model from the body + model := Model("") + if body != nil { + if vertexAISupport, ok := body.(VertexAISupport); ok { + model = vertexAISupport.GetModel() + vertexAISupport.SetAnthropicVersion(c.config.APIVersion) + + var err error + urlSuffix, err = v.translateUrlSuffix(urlSuffix, vertexAISupport.IsStreaming()) + if err != nil { + return "", err + } + } else { + return "", fmt.Errorf("this call is not supported by the Vertex AI API") + } + } + + return v.fullURL(c.config.BaseURL, urlSuffix, model), nil +} + +func (v *VertexAdapter) SetRequestHeaders(c *Client, req *http.Request) error { + req.Header.Set("Authorization", "Bearer "+c.config.GetApiKey()) + return nil +} diff --git a/vendor/github.com/liushuangls/go-anthropic/v2/vertexaisupport.go b/vendor/github.com/liushuangls/go-anthropic/v2/vertexaisupport.go new file mode 100644 index 00000000..14266c04 --- /dev/null +++ b/vendor/github.com/liushuangls/go-anthropic/v2/vertexaisupport.go @@ -0,0 +1,12 @@ +package anthropic + +// VertexAISupport is an interface that is used to configure Vertex AI requests. +// The changes are defined here: https://docs.anthropic.com/en/api/claude-on-vertex-ai +// Model needs to be in the calling URL +// The version of the API is defined in the request body +// This interface allows the vertex ai changes to be contained in the client code, and not leak to each indivdual request definition. +type VertexAISupport interface { + GetModel() Model + SetAnthropicVersion(APIVersion) + IsStreaming() bool +} diff --git a/vendor/github.com/liushuangls/go-anthropic/v2/vertexerror.go b/vendor/github.com/liushuangls/go-anthropic/v2/vertexerror.go new file mode 100644 index 00000000..9b52c94d --- /dev/null +++ b/vendor/github.com/liushuangls/go-anthropic/v2/vertexerror.go @@ -0,0 +1,35 @@ +package anthropic + +import ( + "fmt" +) + +// VertexAPIError provides error information returned by the Anthropic API. +type VertexAPIError struct { + Code int `json:"code"` + Message string `json:"message"` + Status string `json:"status"` + Details []VertexAPIErrorDetails `json:"details"` +} + +type VertexAPIErrorDetails struct { + Type string `json:"@type"` + Reason string `json:"reason"` + Metadata struct { + Method string `json:"method"` + Service string `json:"service"` + } `json:"metadata"` +} + +type VertexAIErrorResponse struct { + Error *VertexAPIError `json:"error,omitempty"` +} + +func (e *VertexAPIError) Error() string { + return fmt.Sprintf( + "vertex api error code: %d, status: %s, message: %s", + e.Code, + e.Status, + e.Message, + ) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 2c054d03..94638494 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -108,7 +108,7 @@ github.com/hashicorp/hcl/json/token # github.com/inngest/expr v0.0.0-20241106234328-863dff7deec0 ## explicit; go 1.23.2 github.com/inngest/expr -# github.com/inngest/inngest v1.3.3-0.20241214115712-303a81fc478c +# github.com/inngest/inngest v1.3.4-0.20241218202510-b750c9bf0ba6 ## explicit; go 1.23.2 github.com/inngest/inngest/pkg/connect/types github.com/inngest/inngest/pkg/connect/wsproto @@ -138,6 +138,9 @@ github.com/karlseguin/ccache/v2 # github.com/klauspost/compress v1.17.2 ## explicit; go 1.18 github.com/klauspost/compress/flate +# github.com/liushuangls/go-anthropic/v2 v2.12.2 +## explicit; go 1.21 +github.com/liushuangls/go-anthropic/v2 # github.com/magiconair/properties v1.8.5 ## explicit; go 1.13 github.com/magiconair/properties From bb935ebff1f203a2d60a3246573660ebccc80778 Mon Sep 17 00:00:00 2001 From: Bruno Scheufler Date: Wed, 18 Dec 2024 21:57:40 +0100 Subject: [PATCH 3/5] fix go sdk --- connect/connection.go | 2 ++ examples/connect/main.go | 14 ++++---------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/connect/connection.go b/connect/connection.go index 4bfe3332..e5a11a3b 100644 --- a/connect/connection.go +++ b/connect/connection.go @@ -112,6 +112,8 @@ func (h *connectHandler) prepareConnection(ctx context.Context, data connectionE return connection{}, reconnectError{fmt.Errorf("could not start connection: %w", err)} } + h.logger.Debug("handshake successful", "gateway_endpoint", startRes.GetGatewayEndpoint(), "gateway_group", startRes.GetGatewayGroup()) + gatewayHost := startRes.GetGatewayEndpoint() // Establish WebSocket connection to one of the gateways diff --git a/examples/connect/main.go b/examples/connect/main.go index 77dac6ec..40e87035 100644 --- a/examples/connect/main.go +++ b/examples/connect/main.go @@ -4,10 +4,8 @@ import ( "context" "fmt" "github.com/inngest/inngest/pkg/logger" - "os" - "strings" - "github.com/inngest/inngestgo" + "os" ) func main() { @@ -15,15 +13,11 @@ func main() { key := "signkey-test-12345678" h := inngestgo.NewHandler("connect-test", inngestgo.HandlerOpts{ + Logger: logger.StdlibLogger(ctx), SigningKey: &key, + InstanceId: nil, + BuildId: nil, Dev: inngestgo.BoolPtr(true), - Logger: logger.StdlibLogger(ctx), - ConnectURLs: []string{ - "ws://unavailable-1", - fmt.Sprintf("%s/connect", strings.Replace(inngestgo.DevServerURL(), "http", "ws", 1)), - "ws://unavailable-2", - "ws://unavailable-3", - }, }) f := inngestgo.CreateFunction( From f6a35b6ba49b0a8e2ba35da77e42d8d29c5f550b Mon Sep 17 00:00:00 2001 From: Bruno Scheufler Date: Wed, 18 Dec 2024 22:52:42 +0100 Subject: [PATCH 4/5] optionally supply env in start request --- connect/handler.go | 2 +- connect/workerapi.go | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/connect/handler.go b/connect/handler.go index a40550c0..2c4a7cf1 100644 --- a/connect/handler.go +++ b/connect/handler.go @@ -34,7 +34,7 @@ func Connect(ctx context.Context, opts Opts, invoker FunctionInvoker, logger *sl notifyConnectDoneChan: make(chan connectReport), notifyConnectedChan: make(chan struct{}), initiateConnectionChan: make(chan struct{}), - apiClient: newWorkerApiClient(opts.APIBaseUrl), + apiClient: newWorkerApiClient(opts.APIBaseUrl, opts.Env), } wp := NewWorkerPool(ctx, opts.WorkerConcurrency, ch.processExecutorRequest) diff --git a/connect/workerapi.go b/connect/workerapi.go index 01d90676..e22e27ec 100644 --- a/connect/workerapi.go +++ b/connect/workerapi.go @@ -12,12 +12,14 @@ import ( type workerApiClient struct { client http.Client + env *string apiBaseUrl string } -func newWorkerApiClient(apiBaseUrl string) *workerApiClient { +func newWorkerApiClient(apiBaseUrl string, env *string) *workerApiClient { return &workerApiClient{ apiBaseUrl: apiBaseUrl, + env: env, } } @@ -35,6 +37,10 @@ func (a *workerApiClient) start(ctx context.Context, hashedSigningKey []byte, re httpReq.Header.Set("Content-Type", "application/protobuf") httpReq.Header.Set("Authorization", fmt.Sprintf("Bearer %s", string(hashedSigningKey))) + if a.env != nil { + httpReq.Header.Add("X-Inngest-Env", *a.env) + } + httpRes, err := a.client.Do(httpReq) if err != nil { return nil, fmt.Errorf("could not send start request: %w", err) From dbaff5f1a3f944e736618fcb39c43499eaef9979 Mon Sep 17 00:00:00 2001 From: Bruno Scheufler Date: Wed, 18 Dec 2024 23:44:03 +0100 Subject: [PATCH 5/5] remove api origin --- connect/handshake.go | 7 - go.mod | 2 +- go.sum | 2 + .../proto/gen/connect/v1/connect.pb.go | 358 +++++++++--------- vendor/modules.txt | 2 +- 5 files changed, 178 insertions(+), 193 deletions(-) diff --git a/connect/handshake.go b/connect/handshake.go index cab18a87..c84ac162 100644 --- a/connect/handshake.go +++ b/connect/handshake.go @@ -48,12 +48,6 @@ func (h *connectHandler) performConnectHandshake(ctx context.Context, connection // Send connect message { - - apiOrigin := h.opts.APIBaseUrl - if h.opts.IsDev { - apiOrigin = h.opts.DevServerUrl - } - data, err := proto.Marshal(&connectproto.WorkerConnectRequestData{ SessionId: &connectproto.SessionIdentifier{ BuildId: h.opts.BuildId, @@ -68,7 +62,6 @@ func (h *connectHandler) performConnectHandshake(ctx context.Context, connection Config: &connectproto.ConfigDetails{ Capabilities: data.marshaledCapabilities, Functions: data.marshaledFns, - ApiOrigin: apiOrigin, }, SystemAttributes: &connectproto.SystemAttributes{ CpuCores: data.numCpuCores, diff --git a/go.mod b/go.mod index 10f43e4c..2b20f44b 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/google/uuid v1.6.0 github.com/gosimple/slug v1.12.0 github.com/gowebpki/jcs v1.0.0 - github.com/inngest/inngest v1.3.4-0.20241218202510-b750c9bf0ba6 + github.com/inngest/inngest v1.3.4-0.20241218224011-c98e011728d6 github.com/oklog/ulid/v2 v2.1.0 github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 github.com/sashabaranov/go-openai v1.35.6 diff --git a/go.sum b/go.sum index 96e1369e..1d5ecd80 100644 --- a/go.sum +++ b/go.sum @@ -63,6 +63,8 @@ github.com/inngest/inngest v1.3.4-0.20241218201514-632b6fe3c996 h1:vO3bLgmQd/stl github.com/inngest/inngest v1.3.4-0.20241218201514-632b6fe3c996/go.mod h1:UfL9PYy1SECtj/vG01UZXPIoEJsamNqRPtz+Uyhli5k= github.com/inngest/inngest v1.3.4-0.20241218202510-b750c9bf0ba6 h1:znR2kHI/mZhD5RInIanQCVFllzNFhRc8wdL1nOu2umI= github.com/inngest/inngest v1.3.4-0.20241218202510-b750c9bf0ba6/go.mod h1:UfL9PYy1SECtj/vG01UZXPIoEJsamNqRPtz+Uyhli5k= +github.com/inngest/inngest v1.3.4-0.20241218224011-c98e011728d6 h1:Jyu3YZfUCUBZzub+exw8qtObbZAB3l4ouhfYwvccbbQ= +github.com/inngest/inngest v1.3.4-0.20241218224011-c98e011728d6/go.mod h1:fhroKPLWcj78OST/5TAqTKuks34K7fWGma3L47ZQl7Y= github.com/karlseguin/ccache/v2 v2.0.8 h1:lT38cE//uyf6KcFok0rlgXtGFBWxkI6h/qg4tbFyDnA= github.com/karlseguin/ccache/v2 v2.0.8/go.mod h1:2BDThcfQMf/c0jnZowt16eW405XIqZPavt+HoYEtcxQ= github.com/karlseguin/expect v1.0.2-0.20190806010014-778a5f0c6003 h1:vJ0Snvo+SLMY72r5J4sEfkuE7AFbixEP2qRbEcum/wA= diff --git a/vendor/github.com/inngest/inngest/proto/gen/connect/v1/connect.pb.go b/vendor/github.com/inngest/inngest/proto/gen/connect/v1/connect.pb.go index 799ee508..9d526148 100644 --- a/vendor/github.com/inngest/inngest/proto/gen/connect/v1/connect.pb.go +++ b/vendor/github.com/inngest/inngest/proto/gen/connect/v1/connect.pb.go @@ -412,7 +412,6 @@ type ConfigDetails struct { Capabilities []byte `protobuf:"bytes,1,opt,name=capabilities,proto3" json:"capabilities,omitempty"` Functions []byte `protobuf:"bytes,2,opt,name=functions,proto3" json:"functions,omitempty"` - ApiOrigin string `protobuf:"bytes,3,opt,name=api_origin,json=apiOrigin,proto3" json:"api_origin,omitempty"` } func (x *ConfigDetails) Reset() { @@ -459,13 +458,6 @@ func (x *ConfigDetails) GetFunctions() []byte { return nil } -func (x *ConfigDetails) GetApiOrigin() string { - if x != nil { - return x.ApiOrigin - } - return "" -} - type AuthData struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1327,186 +1319,184 @@ var file_connect_v1_connect_proto_rawDesc = []byte{ 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x48, 0x61, 0x73, 0x68, 0x22, 0x70, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, + 0x6e, 0x48, 0x61, 0x73, 0x68, 0x22, 0x51, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x66, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x70, 0x69, 0x5f, - 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x70, - 0x69, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x22, 0x4e, 0x0a, 0x08, 0x41, 0x75, 0x74, 0x68, 0x44, - 0x61, 0x74, 0x61, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, - 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x79, 0x6e, 0x63, - 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x79, - 0x6e, 0x63, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xaa, 0x04, 0x0a, 0x18, 0x57, 0x6f, 0x72, 0x6b, - 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x44, 0x61, 0x74, 0x61, 0x12, 0x3c, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x49, 0x64, 0x12, 0x31, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, - 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x61, 0x75, 0x74, - 0x68, 0x44, 0x61, 0x74, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, 0x65, - 0x12, 0x31, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x06, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x3d, 0x0a, 0x1b, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x6d, 0x61, - 0x6e, 0x75, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x5f, 0x61, - 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, - 0x4d, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x52, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x41, - 0x63, 0x6b, 0x12, 0x49, 0x0a, 0x11, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, - 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, - 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x10, 0x73, 0x79, 0x73, - 0x74, 0x65, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x25, 0x0a, - 0x0b, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, - 0x74, 0x88, 0x01, 0x01, 0x12, 0x1c, 0x0a, 0x09, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, - 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, - 0x72, 0x6b, 0x12, 0x1f, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, - 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x64, 0x6b, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x64, 0x6b, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x64, 0x6b, 0x5f, 0x6c, 0x61, 0x6e, 0x67, - 0x75, 0x61, 0x67, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x64, 0x6b, 0x4c, - 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x65, 0x6e, 0x76, 0x69, - 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x6c, 0x61, 0x74, - 0x66, 0x6f, 0x72, 0x6d, 0x22, 0x48, 0x0a, 0x16, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x53, - 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x20, - 0x0a, 0x09, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x48, 0x00, 0x52, 0x08, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x49, 0x64, 0x88, 0x01, 0x01, - 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x5f, 0x69, 0x64, 0x22, 0xe1, - 0x01, 0x0a, 0x1a, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1d, 0x0a, - 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, - 0x65, 0x6e, 0x76, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6e, - 0x76, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x70, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x70, 0x70, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0c, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6c, 0x75, 0x67, 0x12, - 0x1c, 0x0a, 0x07, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, 0x65, 0x70, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x27, 0x0a, - 0x0f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, - 0x69, 0x64, 0x22, 0x9b, 0x01, 0x0a, 0x14, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x41, 0x63, 0x6b, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1d, 0x0a, 0x0a, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x70, - 0x70, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x70, 0x70, 0x49, - 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x6c, - 0x75, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1c, 0x0a, 0x07, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, - 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, 0x65, 0x70, 0x49, - 0x64, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x64, - 0x22, 0xe9, 0x01, 0x0a, 0x0b, 0x53, 0x44, 0x4b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, - 0x35, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x44, 0x4b, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x6f, - 0x5f, 0x72, 0x65, 0x74, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x6e, 0x6f, - 0x52, 0x65, 0x74, 0x72, 0x79, 0x12, 0x24, 0x0a, 0x0b, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x61, - 0x66, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x72, 0x65, - 0x74, 0x72, 0x79, 0x41, 0x66, 0x74, 0x65, 0x72, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x0b, 0x73, - 0x64, 0x6b, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x73, 0x64, 0x6b, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x0e, 0x0a, 0x0c, - 0x5f, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x22, 0xeb, 0x02, 0x0a, - 0x0c, 0x43, 0x6f, 0x6e, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, - 0x0a, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, - 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x19, 0x0a, - 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x46, - 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, - 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x48, 0x65, 0x61, 0x72, 0x74, - 0x62, 0x65, 0x61, 0x74, 0x41, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, - 0x67, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, - 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3c, 0x0a, 0x0a, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, - 0x73, 0x74, 0x65, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x0a, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x5c, 0x0a, 0x10, 0x53, 0x79, - 0x73, 0x74, 0x65, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x1b, - 0x0a, 0x09, 0x63, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x08, 0x63, 0x70, 0x75, 0x43, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, - 0x65, 0x6d, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, - 0x6d, 0x65, 0x6d, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x73, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x6f, 0x73, 0x22, 0xd4, 0x01, 0x0a, 0x09, 0x43, 0x6f, 0x6e, - 0x6e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x15, 0x0a, 0x06, 0x65, 0x6e, 0x76, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6e, 0x76, 0x49, 0x64, 0x12, 0x15, 0x0a, - 0x06, 0x61, 0x70, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, - 0x70, 0x70, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x2e, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x6e, - 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x6e, 0x73, 0x12, 0x1c, 0x0a, 0x07, 0x73, 0x79, 0x6e, 0x63, - 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x73, 0x79, 0x6e, - 0x63, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x1e, 0x0a, 0x08, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, - 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x07, 0x62, 0x75, 0x69, 0x6c, - 0x64, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, - 0x69, 0x64, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x22, - 0xa3, 0x01, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x29, 0x0a, 0x10, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x65, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x67, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, - 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0c, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x47, 0x72, 0x6f, 0x75, - 0x70, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, - 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x74, - 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x79, 0x6e, 0x63, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x39, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, - 0x5f, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x0f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, - 0x2a, 0xf0, 0x01, 0x0a, 0x12, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x41, 0x54, 0x45, 0x57, - 0x41, 0x59, 0x5f, 0x48, 0x45, 0x4c, 0x4c, 0x4f, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x57, 0x4f, - 0x52, 0x4b, 0x45, 0x52, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x10, 0x01, 0x12, 0x1c, - 0x0a, 0x18, 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, - 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x02, 0x12, 0x1c, 0x0a, 0x18, - 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x4f, 0x52, - 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x57, 0x4f, - 0x52, 0x4b, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12, - 0x57, 0x4f, 0x52, 0x4b, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x41, - 0x43, 0x4b, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x57, 0x4f, 0x52, 0x4b, 0x45, 0x52, 0x5f, 0x52, - 0x45, 0x50, 0x4c, 0x59, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x57, 0x4f, 0x52, 0x4b, 0x45, 0x52, - 0x5f, 0x50, 0x41, 0x55, 0x53, 0x45, 0x10, 0x07, 0x12, 0x14, 0x0a, 0x10, 0x57, 0x4f, 0x52, 0x4b, - 0x45, 0x52, 0x5f, 0x48, 0x45, 0x41, 0x52, 0x54, 0x42, 0x45, 0x41, 0x54, 0x10, 0x08, 0x12, 0x13, - 0x0a, 0x0f, 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x49, 0x4e, - 0x47, 0x10, 0x09, 0x2a, 0x3b, 0x0a, 0x11, 0x53, 0x44, 0x4b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x11, 0x0a, 0x0d, 0x4e, 0x4f, 0x54, 0x5f, - 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x44, - 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, - 0x2a, 0x5f, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x01, 0x12, 0x0c, - 0x0a, 0x08, 0x44, 0x52, 0x41, 0x49, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, - 0x44, 0x49, 0x53, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, - 0x10, 0x0a, 0x0c, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, - 0x04, 0x2a, 0x2d, 0x0a, 0x16, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x44, 0x69, 0x73, 0x63, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x13, 0x0a, 0x0f, 0x57, - 0x4f, 0x52, 0x4b, 0x45, 0x52, 0x5f, 0x53, 0x48, 0x55, 0x54, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x00, - 0x42, 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, - 0x6e, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x2f, 0x69, 0x6e, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x4e, 0x0a, 0x08, 0x41, 0x75, 0x74, 0x68, + 0x44, 0x61, 0x74, 0x61, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x79, 0x6e, + 0x63, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, + 0x79, 0x6e, 0x63, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xaa, 0x04, 0x0a, 0x18, 0x57, 0x6f, 0x72, + 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x3c, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x12, 0x31, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x64, 0x61, 0x74, 0x61, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x61, 0x75, + 0x74, 0x68, 0x44, 0x61, 0x74, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x31, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x06, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3d, 0x0a, 0x1b, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x6d, + 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x5f, + 0x61, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x77, 0x6f, 0x72, 0x6b, 0x65, + 0x72, 0x4d, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x52, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x65, 0x73, 0x73, + 0x41, 0x63, 0x6b, 0x12, 0x49, 0x0a, 0x11, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, + 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x73, 0x74, + 0x65, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x10, 0x73, 0x79, + 0x73, 0x74, 0x65, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x25, + 0x0a, 0x0b, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, + 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x1c, 0x0a, 0x09, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, + 0x72, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, + 0x6f, 0x72, 0x6b, 0x12, 0x1f, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, + 0x6d, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x64, 0x6b, 0x5f, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x64, 0x6b, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x64, 0x6b, 0x5f, 0x6c, 0x61, 0x6e, + 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x64, 0x6b, + 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x65, 0x6e, 0x76, + 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x6c, 0x61, + 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x22, 0x48, 0x0a, 0x16, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, + 0x20, 0x0a, 0x09, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x49, 0x64, 0x88, 0x01, + 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x5f, 0x69, 0x64, 0x22, + 0xe1, 0x01, 0x0a, 0x1a, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x45, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1d, + 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x15, 0x0a, + 0x06, 0x65, 0x6e, 0x76, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, + 0x6e, 0x76, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x70, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x70, 0x70, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x66, + 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0c, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6c, 0x75, 0x67, + 0x12, 0x1c, 0x0a, 0x07, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, 0x65, 0x70, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x27, + 0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x73, 0x74, 0x65, 0x70, + 0x5f, 0x69, 0x64, 0x22, 0x9b, 0x01, 0x0a, 0x14, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x41, 0x63, 0x6b, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1d, 0x0a, 0x0a, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x61, + 0x70, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x70, 0x70, + 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, + 0x6c, 0x75, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x75, 0x6e, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1c, 0x0a, 0x07, 0x73, 0x74, 0x65, 0x70, 0x5f, + 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, 0x65, 0x70, + 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x69, + 0x64, 0x22, 0xe9, 0x01, 0x0a, 0x0b, 0x53, 0x44, 0x4b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, + 0x12, 0x35, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x44, + 0x4b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x6e, + 0x6f, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x6e, + 0x6f, 0x52, 0x65, 0x74, 0x72, 0x79, 0x12, 0x24, 0x0a, 0x0b, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, + 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x72, + 0x65, 0x74, 0x72, 0x79, 0x41, 0x66, 0x74, 0x65, 0x72, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x0b, + 0x73, 0x64, 0x6b, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x73, 0x64, 0x6b, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x0e, 0x0a, + 0x0c, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x22, 0xeb, 0x02, + 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, + 0x0a, 0x0a, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x49, 0x64, 0x12, 0x1f, 0x0a, + 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x19, + 0x0a, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x46, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, + 0x74, 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x48, 0x65, 0x61, 0x72, + 0x74, 0x62, 0x65, 0x61, 0x74, 0x41, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, + 0x61, 0x67, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, + 0x61, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3c, 0x0a, + 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, + 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x5c, 0x0a, 0x10, 0x53, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, + 0x1b, 0x0a, 0x09, 0x63, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x08, 0x63, 0x70, 0x75, 0x43, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, + 0x6d, 0x65, 0x6d, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x08, 0x6d, 0x65, 0x6d, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x6f, 0x73, 0x22, 0xd4, 0x01, 0x0a, 0x09, 0x43, 0x6f, + 0x6e, 0x6e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x15, 0x0a, 0x06, 0x65, 0x6e, 0x76, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6e, 0x76, 0x49, 0x64, 0x12, 0x15, + 0x0a, 0x06, 0x61, 0x70, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x61, 0x70, 0x70, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x2e, 0x0a, 0x05, 0x63, 0x6f, 0x6e, + 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x6e, 0x73, 0x12, 0x1c, 0x0a, 0x07, 0x73, 0x79, 0x6e, + 0x63, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x73, 0x79, + 0x6e, 0x63, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x1e, 0x0a, 0x08, 0x62, 0x75, 0x69, 0x6c, 0x64, + 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x07, 0x62, 0x75, 0x69, + 0x6c, 0x64, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x73, 0x79, 0x6e, 0x63, + 0x5f, 0x69, 0x64, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, + 0x22, 0xa3, 0x01, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x65, 0x6e, + 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x67, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x23, 0x0a, + 0x0d, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x79, 0x6e, 0x63, 0x5f, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x79, 0x6e, + 0x63, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x39, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, + 0x65, 0x5f, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x73, 0x2a, 0xf0, 0x01, 0x0a, 0x12, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x41, 0x54, 0x45, + 0x57, 0x41, 0x59, 0x5f, 0x48, 0x45, 0x4c, 0x4c, 0x4f, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x57, + 0x4f, 0x52, 0x4b, 0x45, 0x52, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x10, 0x01, 0x12, + 0x1c, 0x0a, 0x18, 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, + 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x02, 0x12, 0x1c, 0x0a, + 0x18, 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x4f, + 0x52, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x57, + 0x4f, 0x52, 0x4b, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x04, 0x12, 0x16, 0x0a, + 0x12, 0x57, 0x4f, 0x52, 0x4b, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, + 0x41, 0x43, 0x4b, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x57, 0x4f, 0x52, 0x4b, 0x45, 0x52, 0x5f, + 0x52, 0x45, 0x50, 0x4c, 0x59, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x57, 0x4f, 0x52, 0x4b, 0x45, + 0x52, 0x5f, 0x50, 0x41, 0x55, 0x53, 0x45, 0x10, 0x07, 0x12, 0x14, 0x0a, 0x10, 0x57, 0x4f, 0x52, + 0x4b, 0x45, 0x52, 0x5f, 0x48, 0x45, 0x41, 0x52, 0x54, 0x42, 0x45, 0x41, 0x54, 0x10, 0x08, 0x12, + 0x13, 0x0a, 0x0f, 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x49, + 0x4e, 0x47, 0x10, 0x09, 0x2a, 0x3b, 0x0a, 0x11, 0x53, 0x44, 0x4b, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x11, 0x0a, 0x0d, 0x4e, 0x4f, 0x54, + 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, + 0x44, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, + 0x02, 0x2a, 0x5f, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x01, 0x12, + 0x0c, 0x0a, 0x08, 0x44, 0x52, 0x41, 0x49, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x11, 0x0a, + 0x0d, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x03, + 0x12, 0x10, 0x0a, 0x0c, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x45, 0x44, + 0x10, 0x04, 0x2a, 0x2d, 0x0a, 0x16, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x44, 0x69, 0x73, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x13, 0x0a, 0x0f, + 0x57, 0x4f, 0x52, 0x4b, 0x45, 0x52, 0x5f, 0x53, 0x48, 0x55, 0x54, 0x44, 0x4f, 0x57, 0x4e, 0x10, + 0x00, 0x42, 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x69, 0x6e, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x2f, 0x69, 0x6e, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/vendor/modules.txt b/vendor/modules.txt index 94638494..6aee2777 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -108,7 +108,7 @@ github.com/hashicorp/hcl/json/token # github.com/inngest/expr v0.0.0-20241106234328-863dff7deec0 ## explicit; go 1.23.2 github.com/inngest/expr -# github.com/inngest/inngest v1.3.4-0.20241218202510-b750c9bf0ba6 +# github.com/inngest/inngest v1.3.4-0.20241218224011-c98e011728d6 ## explicit; go 1.23.2 github.com/inngest/inngest/pkg/connect/types github.com/inngest/inngest/pkg/connect/wsproto