diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..2f459d5 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index d01ea78..463e0be 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ go.work go.work.sum podscript scratch.go + +#VS Code Settings +.vscode diff --git a/README.md b/README.md index 1d06d15..8664556 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,16 @@ # podscript + podscript is a tool to generate transcripts for podcasts (and other similar audio files), using LLMs and other Speech-to-Text (STT) APIs. Currently, [ChatGPT](https://platform.openai.com/docs/overview), [Anthropic](https://docs.anthropic.com/en/api/getting-started), [Deepgram](https://playground.deepgram.com/?endpoint=listen&smart_format=true&language=en&model=nova-2) and [Groq](https://console.groq.com/playground) are supported. ## Prerequisites + You need an API key for at least one of the following services to use podscript: -* [ChatGPT API Key](https://platform.openai.com/api-keys) or [Anthropic API Key](https://console.anthropic.com/settings/keys), to clean up and transcribe YouTube autogenerated captions using either OpenAI's ChatGPT model or Anthropic's Claude model. -* [Deepgram API Key](https://developers.deepgram.com/docs/make-your-first-api-request#create-a-deepgram-api-key) to transcribe any podcast audio file. Deepgram has some excellent and cheap STT models and offers free signup and $200 in credit to get started. -* [Groq API Key](https://console.groq.com/keys) to clean up and transcribe YouTube autogenerated captions, or use Groq's `whisper-v3-large` model to transcribe an audio file. -* …_(more APIs, for e.g. OpenAI Whisper will be supported in the future. Contributions are welcome)_. + +- [ChatGPT API Key](https://platform.openai.com/api-keys) or [Anthropic API Key](https://console.anthropic.com/settings/keys), to clean up and transcribe YouTube autogenerated captions using either OpenAI's ChatGPT model or Anthropic's Claude model. +- [Deepgram API Key](https://developers.deepgram.com/docs/make-your-first-api-request#create-a-deepgram-api-key) to transcribe any podcast audio file. Deepgram has some excellent and cheap STT models and offers free signup and $200 in credit to get started. +- [Groq API Key](https://console.groq.com/keys) to clean up and transcribe YouTube autogenerated captions, or use Groq's `whisper-v3-large` model to transcribe an audio file. +- [Assembly API Key](https://www.assemblyai.com/) to use AssemblyAI's `best` model to transcribe an audio file. +- …_(more APIs, for e.g. OpenAI Whisper will be supported in the future. Contributions are welcome)_. ## Install @@ -17,7 +21,9 @@ You need an API key for at least one of the following services to use podscript: ``` ## Configure -This command displays prompts to enter API keys for supported services, and write them to `$HOME/.podscript.toml`. + +This command displays prompts to enter API keys for supported services, and write them to `$HOME/.podscript.toml`. + ```shell > podscript configure ``` @@ -25,7 +31,9 @@ This command displays prompts to enter API keys for supported services, and writ Alternatively, you can set keys in environment variable prefixed with `PODSCRIPT_`, for e.g. `PODSCRIPT_OPENAI_API_KEY` and `PODSCRIPT_DEEPGRAM_API_KEY`. ## Usage + ### Transcript from YouTube autogenerated captions + For podcasts on YouTube with autogenerated captions (e.g. [Andrew Huberman](https://www.youtube.com/watch?v=WFcYF_pxLgA) and [Cal Newport](https://www.youtube.com/watch?v=OvlfCW3Ec1g)), use the `ytt` subcommand to download the captions from the YouTube video and feed it to an LLM model to generate a clean transcript. You can customise the model used for transcription using the `--model` flag, which can be one of `gpt-4o-mini` (default if ommitted), `gpt-4o`, `claude-3-5-sonnet-20240620` or `llama-3.1-70b-versatile`. ```shell @@ -39,6 +47,7 @@ To customise the path and add a recognizable suffix to the transcripts, use the ``` Sample Output: + ```text wrote raw autogenerated captions to /Users/deepak/Downloads/raw_transcript_2024-07-05-170548_short.txt transcribed part 1/1… @@ -48,6 +57,7 @@ wrote cleaned up transcripts to /Users/deepak/Downloads/cleaned_transcript_2024- You can also customise the model used for transcription using the `--model` flag, which can be one of `gpt-4o-mini` (default if ommitted), `gpt-4o` or `claude-3-5-sonnet-20240620`. ### Transcript from Deepgram API + Use the `deepgram` subcommand to generate transcripts that are of a higher quality than YouTube autogenerated captions. Deepgram provides a [great API](https://playground.deepgram.com/?endpoint=listen&smart_format=true&language=en&model=nova-2) (with $200 free signup credit!) and excellent, fast models for transcribing audio files. Locate the audio file link for any podcast on [ListenNotes](https://www.listennotes.com/) and use the `--from-url` option @@ -57,6 +67,7 @@ Locate the audio file link for any podcast on [ListenNotes](https://www.listenno ``` Sample Output: + ```text podscript deepgram --from-url https://audio.listennotes.com/e/p/d6cc86364eb540c1a30a1cac2b77b82c/ wrote raw JSON API response to deepgram_api_response_2024-07-05-173538.json @@ -67,22 +78,41 @@ Alternatively, you can pass a local audio file to the command by setting `--from > [!TIP] > You can find the audio download link for a podcast on ListenNotes under the More menu -> +> > image ### Transcript from Groq Whisper API + Use the `groq` subcommand to generate transcripts using the `whisper-v3-large` model from [Groq's API endpoint](https://console.groq.com/docs/speech-text) (which as of Jul 2024 is in beta and free to use within your rate limits). ```shell > podscript groq huberman.mp3 ``` + Sample Output: + ```text wrote raw JSON API response to groq_whisper_api_response_2024-07-11-145154.json wrote transcript to groq_whisper_api_transcript_2024-07-11-145154.txt ``` -Use the `--verbose` flag to dump timestamps for audio segments in the raw JSON response. +Use the `--verbose` flag to dump timestamps for audio segments in the raw JSON response. + +### Transcript from Assembly AI API + +Use the `assemblyai` subcommand to generate transcripts using the `best` model from [Assembly AI's API endpoint](https://www.assemblyai.com/docs) (which as of Oct 2024 free to use within your credit limits and they provide $50 credits free on signup). + +```shell +> podscript assemblyai --from-url https://audio.listennotes.com/e/p/d6cc86364eb540c1a30a1cac2b77b82c/ +``` + +Sample Output: + +```text +Wrote transcript to assemblyai_api_transcript_2024-10-04-191551.txt +``` + +Alternatively, you can pass a url to the command by setting `--url` flag and passing the url instead of local file path. You can also customise the path and add a recognizable suffix with `--path` and `--suffix` options. ## Feedback diff --git a/cmd/assemblyai/assemblyai.go b/cmd/assemblyai/assemblyai.go new file mode 100644 index 0000000..0f9bdf8 --- /dev/null +++ b/cmd/assemblyai/assemblyai.go @@ -0,0 +1,142 @@ +package assemblyai + +import ( + "context" + "errors" + "fmt" + "net/url" + "os" + "path" + "path/filepath" + "time" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + + aai "github.com/AssemblyAI/assemblyai-go-sdk" +) + +const ( + maxLocalFileSize int64 = 2200 * 1024 * 1024 // Approximate 2.2GB in bytes +) + +func init() { + Command.Flags().StringP("path", "p", "", "save transcripts and API responses to path") + Command.Flags().StringP("suffix", "s", "", "append suffix to filenames for easier recognition") + Command.Flags().BoolP("verbose", "v", false, "fetch verbose JSON response (includes token and start/end timestamps)") + Command.Flags().StringP("from-url", "u", "", "URL of the audio file to transcribe") + Command.Flags().StringP("from-file", "f", "", "Local path to the audio file to transcribe") +} + +var Command = &cobra.Command{ + Use: "assemblyai", + Short: "Generate transcript of an audio file using Assembly AI's API.", + RunE: func(cmd *cobra.Command, args []string) error { + apiKey := viper.GetString("assemblyai_api_key") + if apiKey == "" { + return errors.New("assembly AI's API key not found. Please run 'podscript configure' or set the ASSEMBLYAI_API_KEY environment variable") + } + + folder, _ := cmd.Flags().GetString("path") + suffix, _ := cmd.Flags().GetString("suffix") + audioURL, _ := cmd.Flags().GetString("from-url") + audioFilePath, _ := cmd.Flags().GetString("from-file") + verbose, _ := cmd.Flags().GetBool("verbose") + + if folder == "" { + folder = "." // Default to current directory if no path is specified + } + + folder = filepath.Clean(folder) + if fi, err := os.Stat(folder); err != nil || !fi.IsDir() { + return fmt.Errorf("path not found: %s", folder) + } + + timestamp := time.Now().Format("2006-01-02-150405") + filenameSuffix := timestamp + if suffix != "" { + filenameSuffix = fmt.Sprintf("%s_%s", timestamp, suffix) + } + + client := aai.NewClient(apiKey) + ctx := context.Background() + + var transcript *aai.Transcript + var err error + + if audioURL != "" { + // Handle URL input + parsedURL, err := url.ParseRequestURI(audioURL) + if err != nil || (parsedURL.Scheme != "http" && parsedURL.Scheme != "https") { + return fmt.Errorf("invalid URL: %s", audioURL) + } + + params := &aai.TranscriptOptionalParams{ + SpeakerLabels: aai.Bool(true), + Punctuate: aai.Bool(true), + FormatText: aai.Bool(true), + } + transcriptValue, err := client.Transcripts.TranscribeFromURL(ctx, audioURL, params) + if err != nil { + return fmt.Errorf("failed to transcribe from URL: %w", err) + } + transcript = &transcriptValue + fmt.Printf("Generated transcript from URL %s\n", audioURL) + + } else if audioFilePath != "" { + // Handle file input + audioFilePath := filepath.Clean(audioFilePath) + fi, err := os.Stat(audioFilePath) + if err != nil || fi.IsDir() { + return fmt.Errorf("invalid audio file: %s", audioFilePath) + } + + if fi.Size() > maxLocalFileSize { + return fmt.Errorf("file size exceeds 2.2GB limit") + } + + file, err := os.Open(audioFilePath) + if err != nil { + return fmt.Errorf("error opening file: %w", err) + } + defer file.Close() + + transcriptValue, err := client.Transcripts.TranscribeFromReader(ctx, file, nil) + if err != nil { + return fmt.Errorf("failed to transcribe from file: %w", err) + } + transcript = &transcriptValue + } else { + return errors.New("please provide either a valid URL or a file path") + } + + if transcript == nil || transcript.Text == nil { + return errors.New("transcription failed: received nil transcript from AssemblyAI API") + } + + transcriptFilename := path.Join(folder, fmt.Sprintf("assemblyai_transcript_%s.txt", filenameSuffix)) + transcriptFilename = filepath.Clean(transcriptFilename) + file, err := os.Create(transcriptFilename) + if err != nil { + return fmt.Errorf("failed to create transcript file: %w", err) + } + defer file.Close() + + for _, utterance := range transcript.Utterances { + _, err := fmt.Fprintf(file, "Speaker %s: %s\n\n", + aai.ToString(utterance.Speaker), + aai.ToString(utterance.Text), + ) + if err != nil { + return fmt.Errorf("failed to write utterance to file: %w", err) + } + } + fmt.Printf("Wrote transcript to %s\n", transcriptFilename) + + if verbose { + fmt.Printf("Transcript metadata: %+v\n", transcript) + } + + return nil + }, +} diff --git a/cmd/configure/configure.go b/cmd/configure/configure.go index 0387e82..c8ac3b6 100644 --- a/cmd/configure/configure.go +++ b/cmd/configure/configure.go @@ -56,6 +56,11 @@ var Command = &cobra.Command{ return err } + // Assembly AI + if err := setViperKeyFromPrompt("AssemblyAI API key", "assemblyai_api_key"); err != nil { + return err + } + err := viper.WriteConfigAs(viper.ConfigFileUsed()) if err != nil { return fmt.Errorf("error writing config: %v", err) diff --git a/cmd/root.go b/cmd/root.go index ff86de7..6b51ad9 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -10,6 +10,7 @@ import ( "github.com/deepakjois/podscript/cmd/deepgram" "github.com/deepakjois/podscript/cmd/groq" "github.com/deepakjois/podscript/cmd/ytt" + "github.com/deepakjois/podscript/cmd/assemblyai" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -25,6 +26,7 @@ var supportedLLMKeys = []string{ "openai_api_key", "anthropic_api_key", "groq_api_key", + "assemblyai_api_key", } func init() { @@ -34,6 +36,7 @@ func init() { rootCmd.AddCommand(ytt.Command) rootCmd.AddCommand(deepgram.Command) rootCmd.AddCommand(groq.Command) + rootCmd.AddCommand(assemblyai.Command) rootCmd.CompletionOptions.DisableDefaultCmd = true rootCmd.SilenceUsage = true } diff --git a/go.mod b/go.mod index 388190c..6ff702e 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/deepakjois/podscript go 1.22.4 require ( + github.com/AssemblyAI/assemblyai-go-sdk v1.8.1 github.com/charmbracelet/huh v0.4.2 github.com/deepakjois/ytt v0.0.0-20240922124700-664221d83d24 github.com/deepgram/deepgram-go-sdk v1.3.6 @@ -12,38 +13,31 @@ require ( ) require ( + github.com/atotto/clipboard v0.1.4 // indirect + github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect + + // indirect dependencies github.com/catppuccin/go v0.2.0 // indirect + github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/charmbracelet/bubbles v0.18.0 // indirect github.com/charmbracelet/bubbletea v0.26.6 // indirect github.com/charmbracelet/lipgloss v0.11.0 // indirect - github.com/charmbracelet/x/exp/strings v0.0.0-20240524151031-ff83003bf67a // indirect - github.com/dlclark/regexp2 v1.11.0 // indirect - github.com/dustin/go-humanize v1.0.1 // indirect - github.com/go-logr/logr v1.4.1 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/schema v1.3.0 // indirect - github.com/pkoukk/tiktoken-go v0.1.6 // indirect - github.com/rogpeppe/go-internal v1.12.0 // indirect - gitlab.com/golang-commonmark/html v0.0.0-20191124015941-a22733972181 // indirect - gitlab.com/golang-commonmark/linkify v0.0.0-20191026162114-a0c2df6c8f82 // indirect - gitlab.com/golang-commonmark/markdown v0.0.0-20211110145824-bf3e522c626a // indirect - gitlab.com/golang-commonmark/mdurl v0.0.0-20191124015652-932350d1cb84 // indirect - gitlab.com/golang-commonmark/puny v0.0.0-20191124015043-9f83538fa04f // indirect - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect - k8s.io/klog/v2 v2.110.1 // indirect -) - -require ( - github.com/atotto/clipboard v0.1.4 // indirect - github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/charmbracelet/x/ansi v0.1.2 // indirect + github.com/charmbracelet/x/exp/strings v0.0.0-20240524151031-ff83003bf67a // indirect github.com/charmbracelet/x/input v0.1.1 // indirect github.com/charmbracelet/x/term v0.1.1 // indirect github.com/charmbracelet/x/windows v0.1.2 // indirect + github.com/dlclark/regexp2 v1.11.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/schema v1.4.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/klauspost/compress v1.17.6 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-isatty v0.0.20 // indirect @@ -54,7 +48,9 @@ require ( github.com/muesli/cancelreader v0.2.2 // indirect github.com/muesli/termenv v0.15.2 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/pkoukk/tiktoken-go v0.1.6 // indirect github.com/rivo/uniseg v0.4.7 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect @@ -63,11 +59,19 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect + gitlab.com/golang-commonmark/html v0.0.0-20191124015941-a22733972181 // indirect + gitlab.com/golang-commonmark/linkify v0.0.0-20191026162114-a0c2df6c8f82 // indirect + gitlab.com/golang-commonmark/markdown v0.0.0-20211110145824-bf3e522c626a // indirect + gitlab.com/golang-commonmark/mdurl v0.0.0-20191124015652-932350d1cb84 // indirect + gitlab.com/golang-commonmark/puny v0.0.0-20191124015043-9f83538fa04f // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.21.0 // indirect golang.org/x/text v0.15.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/klog/v2 v2.110.1 // indirect + nhooyr.io/websocket v1.8.7 // indirect ) diff --git a/go.sum b/go.sum index d8f5902..5954d76 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,13 @@ +github.com/AssemblyAI/assemblyai-go-sdk v1.8.1 h1:5mhpeEWEHQtuJZ7eKjoZrjvYG5tXzH2lsrJ14xnIEGM= +github.com/AssemblyAI/assemblyai-go-sdk v1.8.1/go.mod h1:ytTvsjAVL+nXZnzBfDagQ/LxDQaKL9W/eTiCo3ZuPJA= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/catppuccin/go v0.2.0 h1:ktBeIrIP42b/8FGiScP9sgrWOss3lw0Z5SktRoithGA= github.com/catppuccin/go v0.2.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/charmbracelet/bubbles v0.18.0 h1:PYv1A036luoBGroX6VWjQIE9Syf2Wby2oOl/39KLfy0= github.com/charmbracelet/bubbles v0.18.0/go.mod h1:08qhZhtIwzgrtBjAcJnij1t1H0ZRjwHyGsy6AL11PSw= github.com/charmbracelet/bubbletea v0.26.6 h1:zTCWSuST+3yZYZnVSvbXwKOPRSNZceVeqpzOLN2zq1s= @@ -43,19 +47,42 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 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/gorilla/schema v1.3.0 h1:rbciOzXAx3IB8stEFnfTwO3sYa6EWlQk79XdyustPDA= github.com/gorilla/schema v1.3.0/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM= +github.com/gorilla/schema v1.4.1 h1:jUg5hUjCSDZpNGLuXQOgIWGdlgrIdYvgQ0wZtdK1M3E= +github.com/gorilla/schema v1.4.1/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 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/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI= +github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -63,10 +90,12 @@ 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/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= @@ -75,6 +104,8 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= @@ -115,6 +146,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ 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= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= @@ -124,6 +157,8 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tmc/langchaingo v0.1.13-0.20240725041451-1975058648b5 h1:sm/byUjE0HYMSB9ihZqOJng/3tepwGkiNo52kmclMoA= github.com/tmc/langchaingo v0.1.13-0.20240725041451-1975058648b5/go.mod h1:vjzUeUsmulZ7Hwq0Ju3Ez+ZmM5aw0dA7K7K2u7wooIw= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= gitlab.com/golang-commonmark/html v0.0.0-20191124015941-a22733972181 h1:K+bMSIx9A7mLES1rtG+qKduLIXq40DAzYHtb0XuCukA= @@ -144,6 +179,7 @@ golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUF golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= @@ -151,12 +187,16 @@ golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -164,5 +204,7 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= +nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= +nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=