diff --git a/README.md b/README.md index ce24ba4..258879c 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@

fabric is an open-source framework for augmenting humans using AI.

+[Updates](#updates) • [What and Why](#whatandwhy) • [Philosophy](#philosophy) • [Installation](#Installation) • @@ -28,6 +29,7 @@ ## Navigation +- [Updates](#updates) - [What and Why](#what-and-why) - [Philosophy](#philosophy) - [Breaking problems into components](#breaking-problems-into-components) @@ -46,16 +48,18 @@
+## Updates + > [!NOTE] -August 20, 2024 — We have migrated to Go, and the transition has been pretty smooth! The biggest thing to know is that **the previous installation instructions in the various Fabric videos out there will no longer work** because they were for the legacy (Python) version. Check the new [install instructions](#Installation) below. -> -> -> **The following command line options were changed during the migration to Go:** +September 15, 2024 — Lots of new stuff! +> * Fabric now supports calling the new `o1-preview` model using the `-r` switch (which stands for raw. Normal queries won't work with `o1-preview` because they disabled System access and don't allow us to set `Temperature`. +> * We have early support for Raycast! Under the `/patterns` directory there's a `raycast` directory with scripts that can be called from Raycast. If you add a scripts directory within Raycast and point it to your `~/.config/fabric/patterns/raycast` directory, you'll then be able to 1) invoke Raycast, type the name of the script, and then 2) paste in the content to be passed, and the results will return in Raycast. There's currently only one script in there but I am (Daniel) adding more. +> * **Go Migration: The following command line options were changed during the migration to Go:** > * You now need to use the -c option instead of -C to copy the result to the clipboard. > * You now need to use the -s option instead of -S to stream results in realtime. -> * The following command line options have been removed --agents (-a), --gui, --clearsession, --remoteOllamaServer, and --sessionlog options -> * You can now use --Setup (-S) to configure an Ollama server. -> * **Please be patient while our developers rewrite the gui in go** +> * The following command line options have been removed `--agents` (-a), `--gui`, `--clearsession`, `--remoteOllamaServer`, and `--sessionlog` +> * You can now use (-S) to configure an Ollama server. +> * **We're working on a GUI rewrite in Go as well** ## Intro videos @@ -195,6 +199,7 @@ Application Options: -T, --topp= Set top P (default: 0.9) -s, --stream Stream -P, --presencepenalty= Set presence penalty (default: 0.0) + -r, --raw Use the defaults of the model without sending chat options (like temperature etc.) and use the user role instead of the system role for patterns -F, --frequencypenalty= Set frequency penalty (default: 0.0) -l, --listpatterns List all patterns -L, --listmodels List all available models @@ -211,6 +216,8 @@ Application Options: --comments Grab comments from YouTube video and send to chat --dry-run Show what would be sent to the model without actually sending it -g, --language= Specify the Language Code for the chat, e.g. -g=en -g=zh + -u, --scrape_url= Scrape website URL to markdown using Jina AI + -q, --scrape_question= Search question using Jina AI Help Options: -h, --help Show this help message diff --git a/cli/cli.go b/cli/cli.go index ef2eec5..45eca36 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -121,11 +121,7 @@ func Cli() (message string, err error) { fmt.Println(transcript) - if currentFlags.Message != "" { - currentFlags.Message = currentFlags.Message + "\n" + transcript - } else { - currentFlags.Message = transcript - } + currentFlags.AppendMessage(transcript) } if currentFlags.YouTubeComments { @@ -138,11 +134,7 @@ func Cli() (message string, err error) { fmt.Println(commentsString) - if currentFlags.Message != "" { - currentFlags.Message = currentFlags.Message + "\n" + commentsString - } else { - currentFlags.Message = commentsString - } + currentFlags.AppendMessage(commentsString) } if currentFlags.Pattern == "" { @@ -151,6 +143,35 @@ func Cli() (message string, err error) { } } + if (currentFlags.ScrapeURL != "" || currentFlags.ScrapeQuestion != "") && fabric.Jina.IsConfigured() { + // Check if the scrape_url flag is set and call ScrapeURL + if currentFlags.ScrapeURL != "" { + if message, err = fabric.Jina.ScrapeURL(currentFlags.ScrapeURL); err != nil { + return + } + + fmt.Println(message) + + currentFlags.AppendMessage(message) + } + + // Check if the scrape_question flag is set and call ScrapeQuestion + if currentFlags.ScrapeQuestion != "" { + if message, err = fabric.Jina.ScrapeQuestion(currentFlags.ScrapeQuestion); err != nil { + return + } + + fmt.Println(message) + + currentFlags.AppendMessage(message) + } + + if currentFlags.Pattern == "" { + // if the pattern flag is not set, we wanted only to grab the url or get the answer to the question + return + } + } + var chatter *core.Chatter if chatter, err = fabric.GetChatter(currentFlags.Model, currentFlags.Stream, currentFlags.DryRun); err != nil { return diff --git a/cli/flags.go b/cli/flags.go index 7d60247..020d7d3 100644 --- a/cli/flags.go +++ b/cli/flags.go @@ -24,6 +24,7 @@ type Flags struct { TopP float64 `short:"T" long:"topp" description:"Set top P" default:"0.9"` Stream bool `short:"s" long:"stream" description:"Stream"` PresencePenalty float64 `short:"P" long:"presencepenalty" description:"Set presence penalty" default:"0.0"` + Raw bool `short:"r" long:"raw" description:"Use the defaults of the model without sending chat options (like temperature etc.) and use the user role instead of the system role for patterns."` FrequencyPenalty float64 `short:"F" long:"frequencypenalty" description:"Set frequency penalty" default:"0.0"` ListPatterns bool `short:"l" long:"listpatterns" description:"List all patterns"` ListAllModels bool `short:"L" long:"listmodels" description:"List all available models"` @@ -41,6 +42,8 @@ type Flags struct { YouTubeComments bool `long:"comments" description:"Grab comments from YouTube video and send to chat"` DryRun bool `long:"dry-run" description:"Show what would be sent to the model without actually sending it"` Language string `short:"g" long:"language" description:"Specify the Language Code for the chat, e.g. -g=en -g=zh" default:""` + ScrapeURL string `short:"u" long:"scrape_url" description:"Scrape website URL to markdown using Jina AI"` + ScrapeQuestion string `short:"q" long:"scrape_question" description:"Search question using Jina AI"` } // Init Initialize flags. returns a Flags struct and an error @@ -95,6 +98,7 @@ func (o *Flags) BuildChatOptions() (ret *common.ChatOptions) { TopP: o.TopP, PresencePenalty: o.PresencePenalty, FrequencyPenalty: o.FrequencyPenalty, + Raw: o.Raw, } return } @@ -115,3 +119,12 @@ func (o *Flags) BuildChatRequest() (ret *common.ChatRequest) { } return } + +func (o *Flags) AppendMessage(message string) { + if o.Message != "" { + o.Message = o.Message + "\n" + message + } else { + o.Message = message + } + return +} diff --git a/cli/flags_test.go b/cli/flags_test.go index 865a262..aba8dc3 100644 --- a/cli/flags_test.go +++ b/cli/flags_test.go @@ -60,6 +60,7 @@ func TestBuildChatOptions(t *testing.T) { TopP: 0.9, PresencePenalty: 0.1, FrequencyPenalty: 0.2, + Raw: false, } options := flags.BuildChatOptions() assert.Equal(t, expectedOptions, options) diff --git a/common/domain.go b/common/domain.go index bf566b1..33365a7 100644 --- a/common/domain.go +++ b/common/domain.go @@ -1,5 +1,7 @@ package common +import goopenai "github.com/sashabaranov/go-openai" + type Message struct { Role string `json:"role"` Content string `json:"content"` @@ -20,6 +22,7 @@ type ChatOptions struct { TopP float64 PresencePenalty float64 FrequencyPenalty float64 + Raw bool } // NormalizeMessages remove empty messages and ensure messages order user-assist-user @@ -33,8 +36,8 @@ func NormalizeMessages(msgs []*Message, defaultUserMessage string) (ret []*Messa } // Ensure, that each odd position shall be a user message - if fullMessageIndex%2 == 0 && message.Role != "user" { - ret = append(ret, &Message{Role: "user", Content: defaultUserMessage}) + if fullMessageIndex%2 == 0 && message.Role != goopenai.ChatMessageRoleUser { + ret = append(ret, &Message{Role: goopenai.ChatMessageRoleUser, Content: defaultUserMessage}) fullMessageIndex++ } ret = append(ret, message) diff --git a/common/domain_test.go b/common/domain_test.go index a4b5ffe..49dcdf3 100644 --- a/common/domain_test.go +++ b/common/domain_test.go @@ -1,23 +1,24 @@ package common import ( + goopenai "github.com/sashabaranov/go-openai" "github.com/stretchr/testify/assert" "testing" ) func TestNormalizeMessages(t *testing.T) { msgs := []*Message{ - {Role: "user", Content: "Hello"}, - {Role: "bot", Content: "Hi there!"}, - {Role: "bot", Content: ""}, - {Role: "user", Content: ""}, - {Role: "user", Content: "How are you?"}, + {Role: goopenai.ChatMessageRoleUser, Content: "Hello"}, + {Role: goopenai.ChatMessageRoleAssistant, Content: "Hi there!"}, + {Role: goopenai.ChatMessageRoleUser, Content: ""}, + {Role: goopenai.ChatMessageRoleUser, Content: ""}, + {Role: goopenai.ChatMessageRoleUser, Content: "How are you?"}, } expected := []*Message{ - {Role: "user", Content: "Hello"}, - {Role: "bot", Content: "Hi there!"}, - {Role: "user", Content: "How are you?"}, + {Role: goopenai.ChatMessageRoleUser, Content: "Hello"}, + {Role: goopenai.ChatMessageRoleAssistant, Content: "Hi there!"}, + {Role: goopenai.ChatMessageRoleUser, Content: "How are you?"}, } actual := NormalizeMessages(msgs, "default") diff --git a/core/chatter.go b/core/chatter.go index e973bc8..84f948f 100644 --- a/core/chatter.go +++ b/core/chatter.go @@ -3,10 +3,10 @@ package core import ( "context" "fmt" - "github.com/danielmiessler/fabric/common" "github.com/danielmiessler/fabric/db" "github.com/danielmiessler/fabric/vendors" + goopenai "github.com/sashabaranov/go-openai" ) type Chatter struct { @@ -26,7 +26,7 @@ func (o *Chatter) Send(request *common.ChatRequest, opts *common.ChatOptions) (m } var session *db.Session - if session, err = chatRequest.BuildChatSession(); err != nil { + if session, err = chatRequest.BuildChatSession(opts.Raw); err != nil { return } @@ -53,7 +53,7 @@ func (o *Chatter) Send(request *common.ChatRequest, opts *common.ChatOptions) (m } if chatRequest.Session != nil && message != "" { - chatRequest.Session.Append(&common.Message{Role: "system", Content: message}) + chatRequest.Session.Append(&common.Message{Role: goopenai.ChatMessageRoleAssistant, Content: message}) err = o.db.Sessions.SaveSession(chatRequest.Session) } return diff --git a/core/chatter_test.go b/core/chatter_test.go index 70966e7..3336e0d 100644 --- a/core/chatter_test.go +++ b/core/chatter_test.go @@ -10,7 +10,7 @@ func TestBuildChatSession(t *testing.T) { Pattern: "test pattern", Message: "test message", } - session, err := chat.BuildChatSession() + session, err := chat.BuildChatSession(false) if err != nil { t.Fatalf("BuildChatSession() error = %v", err) } diff --git a/core/fabric.go b/core/fabric.go index 67926ee..234f4d6 100644 --- a/core/fabric.go +++ b/core/fabric.go @@ -7,16 +7,22 @@ import ( "strconv" "strings" + "github.com/danielmiessler/fabric/vendors/groq" + "github.com/danielmiessler/fabric/vendors/mistral" + goopenai "github.com/sashabaranov/go-openai" + "github.com/atotto/clipboard" "github.com/danielmiessler/fabric/common" "github.com/danielmiessler/fabric/db" + "github.com/danielmiessler/fabric/jina" "github.com/danielmiessler/fabric/vendors/anthropic" "github.com/danielmiessler/fabric/vendors/azure" "github.com/danielmiessler/fabric/vendors/dryrun" "github.com/danielmiessler/fabric/vendors/gemini" - "github.com/danielmiessler/fabric/vendors/groc" "github.com/danielmiessler/fabric/vendors/ollama" "github.com/danielmiessler/fabric/vendors/openai" + "github.com/danielmiessler/fabric/vendors/openrouter" + "github.com/danielmiessler/fabric/vendors/siliconcloud" "github.com/danielmiessler/fabric/youtube" "github.com/pkg/errors" ) @@ -45,6 +51,7 @@ func NewFabricBase(db *db.Db) (ret *Fabric) { VendorsAll: NewVendorsManager(), PatternsLoader: NewPatternsLoader(db.Patterns), YouTube: youtube.NewYouTube(), + Jina: jina.NewClient(), } label := "Default" @@ -58,8 +65,8 @@ func NewFabricBase(db *db.Db) (ret *Fabric) { ret.DefaultModel = ret.AddSetupQuestionCustom("Model", true, "Enter the index the name of your default model") - ret.VendorsAll.AddVendors(openai.NewClient(), azure.NewClient(), ollama.NewClient(), groc.NewClient(), - gemini.NewClient(), anthropic.NewClient()) + ret.VendorsAll.AddVendors(openai.NewClient(), azure.NewClient(), ollama.NewClient(), groq.NewClient(), + gemini.NewClient(), anthropic.NewClient(), siliconcloud.NewClient(), openrouter.NewClient(), mistral.NewClient(), dryrun.NewClient()) return } @@ -70,6 +77,7 @@ type Fabric struct { VendorsAll *VendorsManager *PatternsLoader *youtube.YouTube + Jina *jina.Client Db *db.Db @@ -94,6 +102,7 @@ func (o *Fabric) SaveEnvFile() (err error) { } o.YouTube.SetupFillEnvFileContent(&envFileContent) + o.Jina.SetupFillEnvFileContent(&envFileContent) err = o.Db.SaveEnv(envFileContent.String()) return @@ -110,6 +119,10 @@ func (o *Fabric) Setup() (err error) { _ = o.YouTube.SetupOrSkip() + if err = o.Jina.SetupOrSkip(); err != nil { + return + } + if err = o.PatternsLoader.Setup(); err != nil { return } @@ -178,8 +191,9 @@ func (o *Fabric) configure() (err error) { return } - //YouTube is not mandatory, so ignore not configured error + //YouTube and Jina are not mandatory, so ignore not configured error _ = o.YouTube.Configure() + _ = o.Jina.Configure() return } @@ -234,7 +248,7 @@ func (o *Fabric) CreateOutputFile(message string, fileName string) (err error) { return } -func (o *Chat) BuildChatSession() (ret *db.Session, err error) { +func (o *Chat) BuildChatSession(raw bool) (ret *db.Session, err error) { // new messages will be appended to the session and used to send the message if o.Session != nil { ret = o.Session @@ -243,14 +257,21 @@ func (o *Chat) BuildChatSession() (ret *db.Session, err error) { } systemMessage := strings.TrimSpace(o.Context) + strings.TrimSpace(o.Pattern) - - if systemMessage != "" { - ret.Append(&common.Message{Role: "system", Content: systemMessage}) - } - userMessage := strings.TrimSpace(o.Message) - if userMessage != "" { - ret.Append(&common.Message{Role: "user", Content: userMessage}) + + if raw { + // use the user role instead of the system role in raw mode + message := systemMessage + userMessage + if message != "" { + ret.Append(&common.Message{Role: goopenai.ChatMessageRoleUser, Content: message}) + } + } else { + if systemMessage != "" { + ret.Append(&common.Message{Role: goopenai.ChatMessageRoleSystem, Content: systemMessage}) + } + if userMessage != "" { + ret.Append(&common.Message{Role: goopenai.ChatMessageRoleUser, Content: userMessage}) + } } if o.Language != "" { diff --git a/core/vendors.go b/core/vendors.go index 82f1a71..02af986 100644 --- a/core/vendors.go +++ b/core/vendors.go @@ -3,8 +3,9 @@ package core import ( "context" "fmt" - "github.com/danielmiessler/fabric/vendors" "sync" + + "github.com/danielmiessler/fabric/vendors" ) func NewVendorsManager() *VendorsManager { diff --git a/go.mod b/go.mod index eaf9962..efee3b3 100644 --- a/go.mod +++ b/go.mod @@ -2,37 +2,35 @@ module github.com/danielmiessler/fabric go 1.22.5 -toolchain go1.22.6 - require ( github.com/anaskhan96/soup v1.2.5 github.com/atotto/clipboard v0.1.4 github.com/go-git/go-git/v5 v5.12.0 - github.com/google/generative-ai-go v0.17.0 + github.com/google/generative-ai-go v0.18.0 github.com/jessevdk/go-flags v1.6.1 github.com/joho/godotenv v1.5.1 - github.com/liushuangls/go-anthropic/v2 v2.6.0 - github.com/ollama/ollama v0.3.6 + github.com/liushuangls/go-anthropic/v2 v2.8.0 + github.com/ollama/ollama v0.3.11 github.com/otiai10/copy v1.14.0 github.com/pkg/errors v0.9.1 github.com/samber/lo v1.47.0 - github.com/sashabaranov/go-openai v1.28.2 + github.com/sashabaranov/go-openai v1.30.0 github.com/stretchr/testify v1.9.0 - google.golang.org/api v0.192.0 + google.golang.org/api v0.197.0 ) require ( - cloud.google.com/go v0.115.0 // indirect - cloud.google.com/go/ai v0.8.0 // indirect - cloud.google.com/go/auth v0.8.1 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.3 // indirect - cloud.google.com/go/compute/metadata v0.5.0 // indirect - cloud.google.com/go/longrunning v0.5.7 // indirect - dario.cat/mergo v1.0.0 // indirect - github.com/Microsoft/go-winio v0.6.1 // indirect + cloud.google.com/go v0.115.1 // indirect + cloud.google.com/go/ai v0.8.2 // indirect + cloud.google.com/go/auth v0.9.4 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect + cloud.google.com/go/compute/metadata v0.5.1 // indirect + cloud.google.com/go/longrunning v0.6.1 // indirect + dario.cat/mergo v1.0.1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect github.com/ProtonMail/go-crypto v1.0.0 // indirect - github.com/cloudflare/circl v1.3.7 // indirect - github.com/cyphar/filepath-securejoin v0.2.4 // indirect + github.com/cloudflare/circl v1.4.0 // indirect + github.com/cyphar/filepath-securejoin v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect @@ -43,33 +41,31 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/google/s2a-go v0.1.8 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect github.com/googleapis/gax-go/v2 v2.13.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect - github.com/skeema/knownhosts v1.2.2 // indirect + github.com/skeema/knownhosts v1.3.0 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 // indirect - go.opentelemetry.io/otel v1.26.0 // indirect - go.opentelemetry.io/otel/metric v1.26.0 // indirect - go.opentelemetry.io/otel/trace v1.26.0 // indirect - golang.org/x/crypto v0.25.0 // indirect - golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.27.0 // indirect - golang.org/x/oauth2 v0.22.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 // indirect + go.opentelemetry.io/otel v1.30.0 // indirect + go.opentelemetry.io/otel/metric v1.30.0 // indirect + go.opentelemetry.io/otel/trace v1.30.0 // indirect + golang.org/x/crypto v0.27.0 // indirect + golang.org/x/net v0.29.0 // indirect + golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.24.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/text v0.18.0 // indirect golang.org/x/time v0.6.0 // indirect - golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240730163845-b1a4ccb954bf // indirect - google.golang.org/grpc v1.64.1 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/grpc v1.66.2 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 2339d12..bdc2ed9 100644 --- a/go.sum +++ b/go.sum @@ -1,22 +1,22 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14= -cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU= -cloud.google.com/go/ai v0.8.0 h1:rXUEz8Wp2OlrM8r1bfmpF2+VKqc1VJpafE3HgzRnD/w= -cloud.google.com/go/ai v0.8.0/go.mod h1:t3Dfk4cM61sytiggo2UyGsDVW3RF1qGZaUKDrZFyqkE= -cloud.google.com/go/auth v0.8.1 h1:QZW9FjC5lZzN864p13YxvAtGUlQ+KgRL+8Sg45Z6vxo= -cloud.google.com/go/auth v0.8.1/go.mod h1:qGVp/Y3kDRSDZ5gFD/XPUfYQ9xW1iI7q8RIRoCyBbJc= -cloud.google.com/go/auth/oauth2adapt v0.2.3 h1:MlxF+Pd3OmSudg/b1yZ5lJwoXCEaeedAguodky1PcKI= -cloud.google.com/go/auth/oauth2adapt v0.2.3/go.mod h1:tMQXOfZzFuNuUxOypHlQEXgdfX5cuhwU+ffUuXRJE8I= -cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= -cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= -cloud.google.com/go/longrunning v0.5.7 h1:WLbHekDbjK1fVFD3ibpFFVoyizlLRl73I7YKuAKilhU= -cloud.google.com/go/longrunning v0.5.7/go.mod h1:8GClkudohy1Fxm3owmBGid8W0pSgodEMwEAztp38Xng= -dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= -dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +cloud.google.com/go v0.115.1 h1:Jo0SM9cQnSkYfp44+v+NQXHpcHqlnRJk2qxh6yvxxxQ= +cloud.google.com/go v0.115.1/go.mod h1:DuujITeaufu3gL68/lOFIirVNJwQeyf5UXyi+Wbgknc= +cloud.google.com/go/ai v0.8.2 h1:LEaQwqBv+k2ybrcdTtCTc9OPZXoEdcQaGrfvDYS6Bnk= +cloud.google.com/go/ai v0.8.2/go.mod h1:Wb3EUUGWwB6yHBaUf/+oxUq/6XbCaU1yh0GrwUS8lr4= +cloud.google.com/go/auth v0.9.4 h1:DxF7imbEbiFu9+zdKC6cKBko1e8XeJnipNqIbWZ+kDI= +cloud.google.com/go/auth v0.9.4/go.mod h1:SHia8n6//Ya940F1rLimhJCjjx7KE17t0ctFEci3HkA= +cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY= +cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc= +cloud.google.com/go/compute/metadata v0.5.1 h1:NM6oZeZNlYjiwYje+sYFjEpP0Q0zCan1bmQW/KmIrGs= +cloud.google.com/go/compute/metadata v0.5.1/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= +cloud.google.com/go/longrunning v0.6.1 h1:lOLTFxYpr8hcRtcwWir5ITh1PAKUD/sG2lKrTSYjyMc= +cloud.google.com/go/longrunning v0.6.1/go.mod h1:nHISoOZpBcmlwbJmiVk5oDRz0qG/ZxPynEGs1iZ79s0= +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78= github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/anaskhan96/soup v1.2.5 h1:V/FHiusdTrPrdF4iA1YkVxsOpdNcgvqT1hG+YtcZ5hM= @@ -31,11 +31,11 @@ github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7N github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= -github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= -github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= +github.com/cloudflare/circl v1.4.0 h1:BV7h5MgrktNzytKmWjpOtdYrf0lkkbF8YMlBGPhJQrY= +github.com/cloudflare/circl v1.4.0/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= -github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/cyphar/filepath-securejoin v0.3.2 h1:QhZu5AxQ+o1XZH0Ye05YzvJ0kAdK6VQc0z9NNMek7gc= +github.com/cyphar/filepath-securejoin v0.3.2/go.mod h1:F7i41x/9cBF7lzCrVsYs9fuzwRZm4NQsGTBdpp6mETc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -80,8 +80,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/generative-ai-go v0.17.0 h1:kUmCXUIwJouD7I7ev3OmxzzQVICyhIWAxaXk2yblCMY= -github.com/google/generative-ai-go v0.17.0/go.mod h1:JYolL13VG7j79kM5BtHz4qwONHkeJQzOCkKXnpqtS/E= +github.com/google/generative-ai-go v0.18.0 h1:6ybg9vOCLcI/UpBBYXOTVgvKmcUKFRNj+2Cj3GnebSo= +github.com/google/generative-ai-go v0.18.0/go.mod h1:JYolL13VG7j79kM5BtHz4qwONHkeJQzOCkKXnpqtS/E= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -95,8 +95,8 @@ github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= -github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= +github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= @@ -114,10 +114,10 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 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.6.0 h1:hkgLQPD04wL4lFrV5ZoGlIyy4f6P+brIuRlzn2S8K9s= -github.com/liushuangls/go-anthropic/v2 v2.6.0/go.mod h1:8BKv/fkeTaL5R9R9bGkaknYBueyw2WxY20o7bImbOek= -github.com/ollama/ollama v0.3.6 h1:nA/N0AmjP327po5cZDGLqI40nl+aeei0pD0dLa92ypE= -github.com/ollama/ollama v0.3.6/go.mod h1:YrWoNkFnPOYsnDvsf/Ztb1wxU9/IXrNsQHqcxbY2r94= +github.com/liushuangls/go-anthropic/v2 v2.8.0 h1:0zH2jDNycbrlszxnLrG+Gx8vVT0yJAPWU4s3ZTkWzgI= +github.com/liushuangls/go-anthropic/v2 v2.8.0/go.mod h1:8BKv/fkeTaL5R9R9bGkaknYBueyw2WxY20o7bImbOek= +github.com/ollama/ollama v0.3.11 h1:Fs1B5WjXYUvr5bkMZZpUJfiqIAxrymujRidFABwMeV8= +github.com/ollama/ollama v0.3.11/go.mod h1:YrWoNkFnPOYsnDvsf/Ztb1wxU9/IXrNsQHqcxbY2r94= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= @@ -135,13 +135,13 @@ github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDN github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc= github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU= -github.com/sashabaranov/go-openai v1.28.2 h1:Q3pi34SuNYNN7YrqpHlHbpeYlf75ljgHOAVM/r1yun0= -github.com/sashabaranov/go-openai v1.28.2/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= +github.com/sashabaranov/go-openai v1.30.0 h1:fHv9urGxABfm885xGWsXFSk5cksa+8dJ4jGli/UQQcI= +github.com/sashabaranov/go-openai v1.30.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= -github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= +github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY= +github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -158,32 +158,30 @@ github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 h1:A3SayB3rNyt+1S6qpI9mHPkeHTZbD7XILEqWnYZb2l0= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0/go.mod h1:27iA5uvhuRNmalO+iEUdVn5ZMj2qy10Mm+XRIpRmyuU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 h1:Xs2Ncz0gNihqu9iosIZ5SkBbWo5T8JhhLJFMQL1qmLI= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0/go.mod h1:vy+2G/6NvVMpwGX/NyLqcC41fxepnuKHk16E6IZUcJc= -go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= -go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= -go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= -go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= -go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= -go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0 h1:hCq2hNMwsegUvPzI7sPOvtO9cqyy5GbWt/Ybp2xrx8Q= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0/go.mod h1:LqaApwGx/oUmzsbqxkzuBvyoPpkxk3JQWnqfVrJ3wCA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 h1:ZIg3ZT/aQ7AfKqdwp7ECpOK6vHqquXXuyTjIO8ZdmPs= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0/go.mod h1:DQAwmETtZV00skUwgD6+0U89g80NKsJE3DCKeLLPQMI= +go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts= +go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc= +go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w= +go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ= +go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc= +go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -198,11 +196,11 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= -golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= +golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -226,15 +224,15 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -242,8 +240,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -254,28 +252,26 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.192.0 h1:PljqpNAfZaaSpS+TnANfnNAXKdzHM/B9bKhwRlo7JP0= -google.golang.org/api v0.192.0/go.mod h1:9VcphjvAxPKLmSxVSzPlSRXy/5ARMEw5bf58WoVXafQ= +google.golang.org/api v0.197.0 h1:x6CwqQLsFiA5JKAiGyGBjc2bNtHtLddhJCE2IKuhhcQ= +google.golang.org/api v0.197.0/go.mod h1:AuOuo20GoQ331nq7DquGHlU6d+2wN2fZ8O0ta60nRNw= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d h1:kHjw/5UfflP/L5EbledDrcG4C2597RtymmGRZvHiCuY= -google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240730163845-b1a4ccb954bf h1:liao9UHurZLtiEwBgT9LMOnKYsHze6eA6w1KQCMVN2Q= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc= +google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= -google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= +google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= +google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/jina/jina.go b/jina/jina.go new file mode 100644 index 0000000..41e7d90 --- /dev/null +++ b/jina/jina.go @@ -0,0 +1,70 @@ +package jina + +// see https://jina.ai for more information + +import ( + "fmt" + "io" + "net/http" + + "github.com/danielmiessler/fabric/common" +) + +type Client struct { + *common.Configurable + ApiKey *common.SetupQuestion +} + +func NewClient() (ret *Client) { + + label := "Jina AI" + + ret = &Client{ + Configurable: &common.Configurable{ + Label: label, + EnvNamePrefix: common.BuildEnvVariablePrefix(label), + }, + } + + ret.ApiKey = ret.AddSetupQuestion("API Key", false) + + return +} + +// ScrapeURL return the main content of a webpage in clean, LLM-friendly text. +func (jc *Client) ScrapeURL(url string) (ret string, err error) { + return jc.request(fmt.Sprintf("https://r.jina.ai/%s", url)) +} + +func (jc *Client) ScrapeQuestion(question string) (ret string, err error) { + return jc.request(fmt.Sprintf("https://s.jina.ai/%s", question)) +} + +func (jc *Client) request(requestURL string) (ret string, err error) { + var req *http.Request + if req, err = http.NewRequest("GET", requestURL, nil); err != nil { + err = fmt.Errorf("error creating request: %w", err) + return + } + + // if api keys exist, set the header + if jc.ApiKey.Value != "" { + req.Header.Set("Authorization", "Bearer "+jc.ApiKey.Value) + } + + client := &http.Client{} + var resp *http.Response + if resp, err = client.Do(req); err != nil { + err = fmt.Errorf("error sending request: %w", err) + return + } + defer resp.Body.Close() + + var body []byte + if body, err = io.ReadAll(resp.Body); err != nil { + err = fmt.Errorf("error reading response body: %w", err) + return + } + ret = string(body) + return +} diff --git a/vendors/anthropic/anthropic.go b/vendors/anthropic/anthropic.go index 5f62ac0..18461cc 100644 --- a/vendors/anthropic/anthropic.go +++ b/vendors/anthropic/anthropic.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + goopenai "github.com/sashabaranov/go-openai" "github.com/danielmiessler/fabric/common" "github.com/liushuangls/go-anthropic/v2" @@ -25,9 +26,9 @@ func NewClient() (ret *Client) { ret.maxTokens = 4096 ret.defaultRequiredUserMessage = "Hi" ret.models = []string{ - anthropic.ModelClaude3Haiku20240307, anthropic.ModelClaude3Opus20240229, - anthropic.ModelClaude3Opus20240229, anthropic.ModelClaude2Dot0, anthropic.ModelClaude2Dot1, - anthropic.ModelClaudeInstant1Dot2, "claude-3-5-sonnet-20240620", + string(anthropic.ModelClaude3Haiku20240307), string(anthropic.ModelClaude3Opus20240229), + string(anthropic.ModelClaude3Opus20240229), string(anthropic.ModelClaude2Dot0), string(anthropic.ModelClaude2Dot1), + string(anthropic.ModelClaudeInstant1Dot2), "claude-3-5-sonnet-20240620", } return @@ -104,7 +105,7 @@ func (an *Client) buildMessagesRequest(msgs []*common.Message, opts *common.Chat messages := an.toMessages(msgs) ret = anthropic.MessagesRequest{ - Model: opts.Model, + Model: anthropic.Model(opts.Model), Temperature: &temperature, TopP: &topP, Messages: messages, @@ -121,10 +122,8 @@ func (an *Client) toMessages(msgs []*common.Message) (ret []anthropic.Message) { for _, msg := range normalizedMessages { var message anthropic.Message switch msg.Role { - case "user": + case goopenai.ChatMessageRoleUser: message = anthropic.NewUserTextMessage(msg.Content) - case "system": - message = anthropic.NewAssistantTextMessage(msg.Content) default: message = anthropic.NewAssistantTextMessage(msg.Content) } diff --git a/vendors/dryrun/dryrun.go b/vendors/dryrun/dryrun.go index c13350c..5d3d077 100644 --- a/vendors/dryrun/dryrun.go +++ b/vendors/dryrun/dryrun.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "fmt" + goopenai "github.com/sashabaranov/go-openai" "github.com/danielmiessler/fabric/common" ) @@ -35,9 +36,11 @@ func (c *Client) SendStream(msgs []*common.Message, opts *common.ChatOptions, ch for _, msg := range msgs { switch msg.Role { - case "system": + case goopenai.ChatMessageRoleSystem: output += fmt.Sprintf("System:\n%s\n\n", msg.Content) - case "user": + case goopenai.ChatMessageRoleAssistant: + output += fmt.Sprintf("Assistant:\n%s\n\n", msg.Content) + case goopenai.ChatMessageRoleUser: output += fmt.Sprintf("User:\n%s\n\n", msg.Content) default: output += fmt.Sprintf("%s:\n%s\n\n", msg.Role, msg.Content) @@ -56,14 +59,16 @@ func (c *Client) SendStream(msgs []*common.Message, opts *common.ChatOptions, ch return nil } -func (c *Client) Send(ctx context.Context, msgs []*common.Message, opts *common.ChatOptions) (string, error) { +func (c *Client) Send(_ context.Context, msgs []*common.Message, opts *common.ChatOptions) (string, error) { fmt.Println("Dry run: Would send the following request:") for _, msg := range msgs { switch msg.Role { - case "system": + case goopenai.ChatMessageRoleSystem: fmt.Printf("System:\n%s\n\n", msg.Content) - case "user": + case goopenai.ChatMessageRoleAssistant: + fmt.Printf("Assistant:\n%s\n\n", msg.Content) + case goopenai.ChatMessageRoleUser: fmt.Printf("User:\n%s\n\n", msg.Content) default: fmt.Printf("%s:\n%s\n\n", msg.Role, msg.Content) @@ -84,6 +89,6 @@ func (c *Client) Setup() error { return nil } -func (c *Client) SetupFillEnvFileContent(buffer *bytes.Buffer) { +func (c *Client) SetupFillEnvFileContent(_ *bytes.Buffer) { // No environment variables needed for dry run } diff --git a/vendors/groc/groq.go b/vendors/groq/groq.go similarity index 95% rename from vendors/groc/groq.go rename to vendors/groq/groq.go index bfb18ad..4d5722c 100644 --- a/vendors/groc/groq.go +++ b/vendors/groq/groq.go @@ -1,4 +1,4 @@ -package groc +package groq import ( "github.com/danielmiessler/fabric/vendors/openai" diff --git a/vendors/mistral/mistral.go b/vendors/mistral/mistral.go new file mode 100644 index 0000000..551881a --- /dev/null +++ b/vendors/mistral/mistral.go @@ -0,0 +1,15 @@ +package mistral + +import ( + "github.com/danielmiessler/fabric/vendors/openai" +) + +func NewClient() (ret *Client) { + ret = &Client{} + ret.Client = openai.NewClientCompatible("Mistral", "https://api.mistral.ai/v1", nil) + return +} + +type Client struct { + *openai.Client +} diff --git a/vendors/openai/openai.go b/vendors/openai/openai.go index e9c9755..bb81b90 100644 --- a/vendors/openai/openai.go +++ b/vendors/openai/openai.go @@ -82,7 +82,13 @@ func (o *Client) SendStream( for { var response openai.ChatCompletionStreamResponse if response, err = stream.Recv(); err == nil { - channel <- response.Choices[0].Delta.Content + if len(response.Choices) > 0 { + channel <- response.Choices[0].Delta.Content + } else { + channel <- "\n" + close(channel) + break + } } else if errors.Is(err, io.EOF) { channel <- "\n" close(channel) @@ -103,7 +109,9 @@ func (o *Client) Send(ctx context.Context, msgs []*common.Message, opts *common. if resp, err = o.ApiClient.CreateChatCompletion(ctx, req); err != nil { return } - ret = resp.Choices[0].Message.Content + if len(resp.Choices) > 0 { + ret = resp.Choices[0].Message.Content + } return } @@ -111,26 +119,23 @@ func (o *Client) buildChatCompletionRequest( msgs []*common.Message, opts *common.ChatOptions, ) (ret goopenai.ChatCompletionRequest) { messages := lo.Map(msgs, func(message *common.Message, _ int) goopenai.ChatCompletionMessage { - var role string - - switch message.Role { - case "user": - role = goopenai.ChatMessageRoleUser - case "system": - role = goopenai.ChatMessageRoleSystem - default: - role = goopenai.ChatMessageRoleSystem - } - return goopenai.ChatCompletionMessage{Role: role, Content: message.Content} + return goopenai.ChatCompletionMessage{Role: message.Role, Content: message.Content} }) - ret = goopenai.ChatCompletionRequest{ - Model: opts.Model, - Temperature: float32(opts.Temperature), - TopP: float32(opts.TopP), - PresencePenalty: float32(opts.PresencePenalty), - FrequencyPenalty: float32(opts.FrequencyPenalty), - Messages: messages, + if opts.Raw { + ret = goopenai.ChatCompletionRequest{ + Model: opts.Model, + Messages: messages, + } + } else { + ret = goopenai.ChatCompletionRequest{ + Model: opts.Model, + Temperature: float32(opts.Temperature), + TopP: float32(opts.TopP), + PresencePenalty: float32(opts.PresencePenalty), + FrequencyPenalty: float32(opts.FrequencyPenalty), + Messages: messages, + } } return } diff --git a/vendors/openrouter/openrouter.go b/vendors/openrouter/openrouter.go new file mode 100644 index 0000000..2c653cd --- /dev/null +++ b/vendors/openrouter/openrouter.go @@ -0,0 +1,16 @@ +package openrouter + +import ( + "github.com/danielmiessler/fabric/vendors/openai" +) + +func NewClient() (ret *Client) { + ret = &Client{} + ret.Client = openai.NewClientCompatible("OpenRouter", "https://openrouter.ai/api/v1", nil) + + return +} + +type Client struct { + *openai.Client +} diff --git a/vendors/siliconcloud/siliconcloud.go b/vendors/siliconcloud/siliconcloud.go new file mode 100644 index 0000000..754a28a --- /dev/null +++ b/vendors/siliconcloud/siliconcloud.go @@ -0,0 +1,15 @@ +package siliconcloud + +import ( + "github.com/danielmiessler/fabric/vendors/openai" +) + +func NewClient() (ret *Client) { + ret = &Client{} + ret.Client = openai.NewClientCompatible("SiliconCloud", "https://api.siliconflow.cn/v1", nil) + return +} + +type Client struct { + *openai.Client +}