From 735a5d02a29df2275ad5104c3736e6b7b65d48a0 Mon Sep 17 00:00:00 2001 From: Meysam Hadeli <35596795+meysamhadeli@users.noreply.github.com> Date: Thu, 31 Oct 2024 16:10:31 +0330 Subject: [PATCH] feat: add new style code and text with chroma --- .github/release-drafter.yml | 97 +++++++++++++++++++ .github/workflows/ci.yml | 32 ++++++ .github/workflows/release-drafter-labeler.yml | 21 ++++ .github/workflows/release-drafter.yml | 17 ++++ .gitignore | 3 + README.md | 4 +- cmd/code.go | 15 ++- cmd/root.go | 11 ++- config/config.go | 11 +-- embed_data/prompts/code_block_prompt.tmpl | 9 +- go.mod | 23 ++--- go.sum | 77 ++------------- providers/ollama/ollama_provider.go | 59 +++++------ providers/openai/openai_provider.go | 75 +++++--------- utils/check_language.go | 35 ++++++- utils/confirm_prompt.go | 10 +- utils/markdown_generator.go | 16 ++- 17 files changed, 312 insertions(+), 203 deletions(-) create mode 100644 .github/release-drafter.yml create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/release-drafter-labeler.yml create mode 100644 .github/workflows/release-drafter.yml diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 0000000..75fef51 --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,97 @@ +# This release drafter follows the conventions + +name-template: 'v$RESOLVED_VERSION' +tag-template: 'v$RESOLVED_VERSION' +template: | + ## What Changed ๐Ÿ‘€ + $CHANGES + **Full Changelog**: https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION +categories: + - title: ๐Ÿš€ Features + labels: + - feature + - title: ๐Ÿ› Bug Fixes + labels: + - fix + - bug + - title: ๐Ÿงช Test + labels: + - test + - title: ๐Ÿ‘ท CI + labels: + - ci + - title: โ™ป๏ธ Refactor + labels: + - changed + - enhancement + - refactor + - title: โ›”๏ธ Deprecated + labels: + - deprecated + - title: ๐Ÿ” Security + labels: + - security + - title: ๐Ÿ“„ Documentation + labels: + - docs + - documentation + - title: ๐Ÿงฉ Dependency Updates + labels: + - deps + - dependencies + - title: ๐Ÿงฐ Maintenance + label: 'chore' + - title: ๐Ÿ“ Other changes +## putting no labels pr to `Other Changes` category with no label + +# Using regex for defining rules +autolabeler: + - label: 'chore' + branch: + - '/(chore)\/.*/' + - label: 'security' + branch: + - '/(security)\/.*/' + - label: 'refactor' + branch: + - '/(refactor)\/.*/' + - label: 'docs' + branch: + - '/(docs)\/.*/' + - label: 'ci' + branch: + - '/(ci)\/.*/' + - label: 'test' + branch: + - '/(test)\/.*/' + - label: 'bug' + branch: + - '/(fix)\/.*/' + - label: 'feature' + branch: + - '/(feat)\/.*/' + - label: 'minor' + branch: + - '/(feat)\/.*/' + - label: 'patch' + branch: + - '/(fix)\/.*/' + body: + - '/JIRA-[0-9]{1,4}/' + +change-template: '- $TITLE @$AUTHOR (#$NUMBER)' +change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. +version-resolver: + major: + labels: + - major + minor: + labels: + - minor + patch: + labels: + - patch + default: patch + +exclude-labels: + - skip-changelog diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..c77a261 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,32 @@ +# This workflow will build and test golang project + +name: CI + +on: + push: + branches: ["main"] + paths-ignore: + - "README.md" + - "CHANGELOG.md" + pull_request: + branches: ["main"] + +jobs: + + ci: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: 1.23 + + - name: build + working-directory: ./ + run: go build -v ./... + + - name: test + working-directory: ./ + run: go test -v ./... diff --git a/.github/workflows/release-drafter-labeler.yml b/.github/workflows/release-drafter-labeler.yml new file mode 100644 index 0000000..960bec7 --- /dev/null +++ b/.github/workflows/release-drafter-labeler.yml @@ -0,0 +1,21 @@ +name: Release Drafter Auto Labeler + +on: + pull_request: + types: + - opened + - synchronize + - reopened + - labeled + - unlabeled + +jobs: + auto-labeler: + runs-on: ubuntu-latest + steps: + - uses: release-drafter/release-drafter@v5 + with: + config-name: release-drafter.yml + disable-releaser: true # only run auto-labeler for PRs + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml new file mode 100644 index 0000000..f8cc7cb --- /dev/null +++ b/.github/workflows/release-drafter.yml @@ -0,0 +1,17 @@ + name: Release Drafter + + on: + push: + branches: + - main + + jobs: + update_release_draft: + name: Release drafter + runs-on: ubuntu-latest + + steps: + - name: Update Release Draft + uses: release-drafter/release-drafter@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 7425aa3..c0161b0 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,6 @@ README.md # License LICENSE + +# Config +config.yml diff --git a/README.md b/README.md index c4db27a..21f0f61 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,8 @@ codai code --provider_name openapi --temperature 0.8 ``` This flexibility allows you to customize config of codai on the fly. +> Note: We use [Chroma](https://github.com/alecthomas/chroma) for `style` of our `text` and `code block`, and you can find more theme here in [Chroma Style Gallery](https://xyproto.github.io/splash/docs/) and use it as a `buffering theme` in `codai`. + How to Run To use **codai** as your code assistant, navigate to the directory where you want to apply codai and run the following command: @@ -121,4 +123,4 @@ Thanks a bunch for supporting me! Thanks to all [contributors](https://github.com/meysamhadeli/codai/graphs/contributors), you're awesome and this wouldn't be possible without you! The goal is to build a categorized, community-driven collection of very well-known resources. -Please follow this [contribution guideline](./CONTRIBUTION.md) to submit a pull request or create the issue. +Please follow this [contribution guideline](./CONTRIBUTION.md) to submit a pull request or create the issue. \ No newline at end of file diff --git a/cmd/code.go b/cmd/code.go index 8e8ba6d..c0bffc0 100644 --- a/cmd/code.go +++ b/cmd/code.go @@ -202,11 +202,24 @@ func handleCodeCommand(rootDependencies *RootDependencies) { for _, change := range changes { // Prompt the user to accept or reject the changes - err := utils.ConfirmPrompt(change.RelativePath) + promptAccepted, err := utils.ConfirmPrompt(change.RelativePath) if err != nil { fmt.Println(lipgloss_color.Red.Render(fmt.Sprintf("Error getting user prompt: %v", err))) continue } + + if promptAccepted { + err := rootDependencies.Analyzer.ApplyChanges(change.RelativePath) + if err != nil { + fmt.Println(lipgloss_color.Red.Render(fmt.Sprintf("Error applying changes: %v", err))) + continue + } + fmt.Println(lipgloss_color.Green.Render("โœ”๏ธ Changes accepted!")) + + } else { + fmt.Println(lipgloss_color.Red.Render("โŒ Changes rejected.")) + } + } // Display token usage details in a boxed format after each AI request diff --git a/cmd/root.go b/cmd/root.go index 4512dbd..174504a 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -31,7 +31,16 @@ var rootCmd = &cobra.Command{ Short: "codai CLI for coding and chatting", Long: `codai is a CLI tool that assists developers by providing intelligent code suggestions, refactoring, and code reviews based on the full context of your project. It operates in a session-based manner, allowing for continuous context throughout interactions. Codai supports multiple LLMs, including GPT-3.5, GPT-4, and Ollama, to streamline daily development tasks.`, Run: func(cmd *cobra.Command, args []string) { - handleRootCommand(cmd) + // Check if any arguments or subcommands were provided + if len(args) == 0 { + err := cmd.Help() // Display help if no subcommand or argument is provided + if err != nil { + return + } + } else { + // Run the handleRootCommand if arguments are provided + handleRootCommand(cmd) + } }, } diff --git a/config/config.go b/config/config.go index e8e6866..78302d8 100644 --- a/config/config.go +++ b/config/config.go @@ -69,11 +69,6 @@ func LoadConfigs(rootCmd *cobra.Command, cwd string) *Config { fmt.Println(lipgloss_color.Red.Render(fmt.Sprintf("Error reading config file: %v", err))) os.Exit(1) } - } - - // Check if the user provided a config file via CLI - if cfgFile != "" { - viper.SetConfigFile(cfgFile) } else { // Automatically look for 'config.yml' in the working directory if no CLI file is provided viper.SetConfigName("config") // name of config file (without extension) @@ -82,8 +77,10 @@ func LoadConfigs(rootCmd *cobra.Command, cwd string) *Config { } // Read the configuration file if available - err := viper.ReadInConfig() - if err != nil { + if err := viper.ReadInConfig(); err == nil { + + } else if cfgFile != "" { + // If a specific config file was set but not found, show error and exit fmt.Println(lipgloss_color.Red.Render(fmt.Sprintf("Error reading config file: %v", err))) os.Exit(1) } diff --git a/embed_data/prompts/code_block_prompt.tmpl b/embed_data/prompts/code_block_prompt.tmpl index f4461ca..b7b66e1 100644 --- a/embed_data/prompts/code_block_prompt.tmpl +++ b/embed_data/prompts/code_block_prompt.tmpl @@ -1,6 +1,6 @@ # You are a ai code assistant. I will provide you with a description of the change or feature I want to implement, along with the current code context of my project. Use the latest language feature and technology for your assistant. -Your tasks are according these steps: +> Your tasks are according these steps: ## Understand the context: - Read the code context carefully. @@ -9,8 +9,7 @@ Your tasks are according these steps: ## Return Code Block for Changes and Response Format - For each file that requires changes, give the code modifications in `Code BLOCK` format. - Do not combine multiple files into a single `Code BLOCK`. -- Put `relative path` of each file top of specific `Code Block` that you are modifying. -- Separate multiple `CodeBlock` with `dividers`. +- Put `relative path` of each file `top` of specific `Code Block` that you are `adding` or `modifying`. - You MUST use this `CodeBlock format` for every modified or new file like below example: File: relative path here. @@ -34,4 +33,6 @@ File: relative path here. - For each file you modify, provide a separate CodeBlock. **Do not** combine multiple files into one CodeBlock. - If you create a new file, follow the same format, making sure the relative path is correct. - **Avoid** using comments like "... rest of the code..." or "unchanged lines", always return the **full file content**. -- If you delete a file, use the same format but specify an `empty CodeBlock` with the file path. \ No newline at end of file +- If you delete a file, use the same format but specify an `empty CodeBlock` with the file path. + +### IMPORTANT: ALWAYS ADD `RELATIVE PATH` `TOP` OF EACH `CODE BLOCK`. diff --git a/go.mod b/go.mod index 74440e0..7327d36 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,10 @@ module github.com/meysamhadeli/codai go 1.23.2 require ( + github.com/alecthomas/chroma/v2 v2.14.0 github.com/cenkalti/backoff/v4 v4.3.0 - github.com/charmbracelet/glamour v0.8.0 github.com/charmbracelet/lipgloss v0.13.1 + github.com/pkoukk/tiktoken-go v0.1.7 github.com/pterm/pterm v0.12.79 github.com/smacker/go-tree-sitter v0.0.0-20240827094217-dd81d9e9be82 github.com/spf13/cobra v1.8.1 @@ -16,20 +17,14 @@ require ( atomicgo.dev/cursor v0.2.0 // indirect atomicgo.dev/keyboard v0.2.9 // indirect atomicgo.dev/schedule v0.1.0 // indirect - github.com/alecthomas/chroma/v2 v2.14.0 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect - github.com/aymerick/douceur v0.2.0 // indirect - github.com/charmbracelet/x/ansi v0.3.2 // indirect + github.com/charmbracelet/x/ansi v0.4.0 // indirect github.com/containerd/console v1.0.3 // indirect github.com/dlclark/regexp2 v1.11.0 // indirect - github.com/dop251/goja v0.0.0-20230304130813-e2f543bf4b4c // indirect - github.com/dop251/goja_nodejs v0.0.0-20230226152057-060fa99b809f // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect - github.com/google/pprof v0.0.0-20230309165930-d61513b1440d // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/google/uuid v1.4.0 // indirect github.com/gookit/color v1.5.4 // indirect - github.com/gorilla/css v1.0.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/lithammer/fuzzysearch v1.1.8 // indirect @@ -37,12 +32,9 @@ require ( github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect - github.com/microcosm-cc/bluemonday v1.0.27 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/muesli/reflow v0.3.0 // indirect github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect - github.com/pkoukk/tiktoken-go v0.1.7 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect @@ -51,17 +43,14 @@ require ( github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/tiktoken-go/tokenizer v0.2.0 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - github.com/yuin/goldmark v1.7.4 // indirect - github.com/yuin/goldmark-emoji v1.0.3 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/net v0.27.0 // indirect golang.org/x/sys v0.26.0 // indirect golang.org/x/term v0.25.0 // indirect - golang.org/x/text v0.18.0 // indirect + golang.org/x/text v0.19.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 ) diff --git a/go.sum b/go.sum index b3bf634..567eb7f 100644 --- a/go.sum +++ b/go.sum @@ -24,71 +24,37 @@ github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW5 github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= 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/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= -github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= -github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= -github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/charmbracelet/glamour v0.8.0 h1:tPrjL3aRcQbn++7t18wOpgLyl8wrOHUEDS7IZ68QtZs= -github.com/charmbracelet/glamour v0.8.0/go.mod h1:ViRgmKkf3u5S7uakt2czJ272WSg2ZenlYEZXT2x7Bjw= -github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw= -github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY= github.com/charmbracelet/lipgloss v0.13.1 h1:Oik/oqDTMVA01GetT4JdEC033dNzWoQHdWnHnQmXE2A= github.com/charmbracelet/lipgloss v0.13.1/go.mod h1:zaYVJ2xKSKEnTEEbX6uAHabh2d975RJ+0yfkFpRBz5U= -github.com/charmbracelet/x/ansi v0.2.3 h1:VfFN0NUpcjBRd4DnKfRaIRo53KRgey/nhOoEqosGDEY= -github.com/charmbracelet/x/ansi v0.2.3/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= -github.com/charmbracelet/x/ansi v0.3.2 h1:wsEwgAN+C9U06l9dCVMX0/L3x7ptvY1qmjMwyfE6USY= -github.com/charmbracelet/x/ansi v0.3.2/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= -github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a h1:G99klV19u0QnhiizODirwVksQB91TJKV/UaTnACcG30= -github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= -github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= -github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= -github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/charmbracelet/x/ansi v0.4.0 h1:NqwHA4B23VwsDn4H3VcNX1W1tOmgnvY1NDx5tOXdnOU= +github.com/charmbracelet/x/ansi v0.4.0/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja v0.0.0-20221118162653-d4bf6fde1b86/go.mod h1:yRkwfj0CBpOGre+TwBsqPV0IH0Pk73e4PXJOeNDboGs= -github.com/dop251/goja v0.0.0-20230304130813-e2f543bf4b4c h1:/utv6nmTctV6OVgfk5+O6lEMEWL+6KJy4h9NZ5fnkQQ= -github.com/dop251/goja v0.0.0-20230304130813-e2f543bf4b4c/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= -github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= -github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= -github.com/dop251/goja_nodejs v0.0.0-20230226152057-060fa99b809f h1:mmnNidRg3cMfcgyeNtIBSDZgjf/85lA/2pplccwSxYg= -github.com/dop251/goja_nodejs v0.0.0-20230226152057-060fa99b809f/go.mod h1:0tlktQL7yHfYEtjcRGi/eiOkbDR5XF7gyFFvbC5//E0= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= 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/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= -github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= -github.com/google/pprof v0.0.0-20230309165930-d61513b1440d h1:um9/pc7tKMINFfP1eE7Wv6PRGXlcCSJkVajF7KJw3uQ= -github.com/google/pprof v0.0.0-20230309165930-d61513b1440d/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= +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/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= -github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= -github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= 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/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= -github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -98,7 +64,6 @@ github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y7 github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -113,20 +78,13 @@ github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0V github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= 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-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= -github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= 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/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= -github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a h1:2MaM6YC3mGu54x+RKAA6JiFFHlHDY1UbkxqppT7wYOg= github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a/go.mod h1:hxSnBBYLK21Vtq/PHd0S2FYCxBXzBua8ov5s1RobyRQ= -github.com/pandodao/tokenizer-go v0.2.0 h1:NhfI8fGvQkDld2cZCag6NEU3pJ/ugU9zoY1R/zi9YCs= -github.com/pandodao/tokenizer-go v0.2.0/go.mod h1:t6qFbaleKxbv0KNio2XUN/mfGM5WKv4haPXDQWVDG00= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pkoukk/tiktoken-go v0.1.7 h1:qOBHXX4PHtvIvmOtyg1EeKlwFRiMKAcoMp4Q+bLQDmw= @@ -143,11 +101,9 @@ github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5b github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s= github.com/pterm/pterm v0.12.79 h1:lH3yrYMhdpeqX9y5Ep1u7DejyHy7NSQg9qrBjF9dFT4= github.com/pterm/pterm v0.12.79/go.mod h1:1v/gzOF1N0FsjbgTHZ1wVycRkKiatFvJSJC4IGaQAAo= -github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -186,17 +142,10 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/tiktoken-go/tokenizer v0.2.0 h1:MqBlDeE5LRIEpapZk5s7COS9taGtRRIwM8bPxq13rI8= -github.com/tiktoken-go/tokenizer v0.2.0/go.mod h1:7SZW3pZUKWLJRilTvWCa86TOVIiiJhYj3FQ5V3alWcg= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= 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= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= -github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg= -github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= -github.com/yuin/goldmark-emoji v1.0.3 h1:aLRkLHOuBR2czCY4R8olwMjID+tENfhyFDMCRhbIQY4= -github.com/yuin/goldmark-emoji v1.0.3/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= @@ -210,10 +159,7 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -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/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -223,11 +169,9 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/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.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= @@ -236,36 +180,29 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= 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= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.5.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.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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/xerrors v0.0.0-20190717185122-a985d3407aa7/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-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 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.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -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= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/providers/ollama/ollama_provider.go b/providers/ollama/ollama_provider.go index ad541a5..8383545 100644 --- a/providers/ollama/ollama_provider.go +++ b/providers/ollama/ollama_provider.go @@ -14,7 +14,6 @@ import ( "io" "io/ioutil" "net/http" - "regexp" "strings" ) @@ -179,10 +178,8 @@ func (ollamaProvider *OllamaConfig) ChatCompletionRequest(ctx context.Context, u } reader := bufio.NewReader(resp.Body) - var sectionBuilder strings.Builder // Accumulate content for each section - var resultBuilder strings.Builder // Accumulate full result for return - - inCodeBlock := false // Track if we are inside a code block + var resultBuilder strings.Builder + var markdownBuffer strings.Builder // Buffer for accumulating chunks // Process each chunk as it arrives for { @@ -194,59 +191,49 @@ func (ollamaProvider *OllamaConfig) ChatCompletionRequest(ctx context.Context, u return "", fmt.Errorf("error reading stream: %v", err) } - // Check for end of the stream if line == "data: [DONE]\n" { break } if strings.HasPrefix(line, "data: ") { - // Trim the "data: " prefix + // Trim the "data: " prefix and parse JSON jsonPart := strings.TrimPrefix(line, "data: ") - - // Parse JSON response var response models.ChatCompletionResponse if err := json.Unmarshal([]byte(jsonPart), &response); err != nil { return "", fmt.Errorf("error unmarshalling chunk: %v", err) } - var codeBlockRegex = regexp.MustCompile("(?m)^```[a-zA-Z]*$") - - // Extract content from the response if len(response.Choices) > 0 { content := response.Choices[0].Delta.Content - resultBuilder.WriteString(content) // Accumulate full result for return - - // Check for triple backtick boundaries - if strings.Contains(content, fmt.Sprintf("```%s", codeBlockRegex)) { - // Toggle inCodeBlock status when we detect backticks - inCodeBlock = !inCodeBlock - sectionBuilder.WriteString(content) // Add the boundary marker - - // If we just finished a code block, render and print the section - if !inCodeBlock { - section := sectionBuilder.String() - sectionBuilder.Reset() // Reset for the next section - - // Render and print markdown for the current section - if err := utils.RenderAndPrintMarkdown(section, ollamaProvider.BufferingTheme); err != nil { - return "", err - } + resultBuilder.WriteString(content) // Gather full result for final return + + // Accumulate content in the markdown buffer + markdownBuffer.WriteString(content) + + // Process complete Markdown blocks (indicated by double newlines) + if strings.Contains(content, "\n") { + blockContent := markdownBuffer.String() + markdownBuffer.Reset() + + language := utils.DetectLanguageFromCodeBlock(blockContent) + err := utils.RenderAndPrintMarkdown(blockContent, language, ollamaProvider.BufferingTheme) + if err != nil { + return "", err } - } else { - // Continue accumulating content within the section - sectionBuilder.WriteString(content) } } } } - // Render any remaining content in the section builder - if sectionBuilder.Len() > 0 { - if err := utils.RenderAndPrintMarkdown(sectionBuilder.String(), ollamaProvider.BufferingTheme); err != nil { + // Flush remaining content in the buffer + if markdownBuffer.Len() > 0 { + blockContent := markdownBuffer.String() + language := utils.DetectLanguageFromCodeBlock(blockContent) + err := utils.RenderAndPrintMarkdown(blockContent, language, ollamaProvider.BufferingTheme) + if err != nil { return "", err } } - // Return the accumulated full result return resultBuilder.String(), nil } diff --git a/providers/openai/openai_provider.go b/providers/openai/openai_provider.go index 273a323..0c4116f 100644 --- a/providers/openai/openai_provider.go +++ b/providers/openai/openai_provider.go @@ -14,7 +14,6 @@ import ( "io" "io/ioutil" "net/http" - "regexp" "strings" ) @@ -121,7 +120,6 @@ func (openAIProvider *OpenAIConfig) EmbeddingRequest(ctx context.Context, prompt } func (openAIProvider *OpenAIConfig) ChatCompletionRequest(ctx context.Context, userInput string, prompt string) (string, error) { - // Count tokens for the user input and prompt totalChatTokens, err := openAIProvider.TokenManagement.CountTokens(fmt.Sprintf("%s%s", prompt, userInput), openAIProvider.ChatCompletionModel) if err != nil { @@ -137,16 +135,10 @@ func (openAIProvider *OpenAIConfig) ChatCompletionRequest(ctx context.Context, u reqBody := models.ChatCompletionRequest{ Model: openAIProvider.ChatCompletionModel, Messages: []models.Message{ - { - Role: "system", - Content: prompt, - }, - { - Role: "user", - Content: userInput, - }, + {Role: "system", Content: prompt}, + {Role: "user", Content: userInput}, }, - Stream: true, // Enable streaming + Stream: true, Temperature: &openAIProvider.Temperature, } @@ -161,11 +153,9 @@ func (openAIProvider *OpenAIConfig) ChatCompletionRequest(ctx context.Context, u return "", fmt.Errorf("error creating request: %v", err) } - // Set headers req.Header.Set("Content-Type", "application/json") req.Header.Set("api-key", openAIProvider.ApiKey) - // Create an HTTP client and send the request client := &http.Client{} resp, err := client.Do(req) if err != nil { @@ -176,16 +166,13 @@ func (openAIProvider *OpenAIConfig) ChatCompletionRequest(ctx context.Context, u } defer resp.Body.Close() - // Check if the response status is not 200 if resp.StatusCode != http.StatusOK { return "", fmt.Errorf("API request failed with status: %d", resp.StatusCode) } reader := bufio.NewReader(resp.Body) - var sectionBuilder strings.Builder // Accumulate content for each section - var resultBuilder strings.Builder // Accumulate full result for return - - inCodeBlock := false // Track if we are inside a code block + var resultBuilder strings.Builder + var markdownBuffer strings.Builder // Buffer for accumulating chunks // Process each chunk as it arrives for { @@ -197,59 +184,49 @@ func (openAIProvider *OpenAIConfig) ChatCompletionRequest(ctx context.Context, u return "", fmt.Errorf("error reading stream: %v", err) } - // Check for end of the stream if line == "data: [DONE]\n" { break } if strings.HasPrefix(line, "data: ") { - // Trim the "data: " prefix + // Trim the "data: " prefix and parse JSON jsonPart := strings.TrimPrefix(line, "data: ") - - // Parse JSON response var response models.ChatCompletionResponse if err := json.Unmarshal([]byte(jsonPart), &response); err != nil { return "", fmt.Errorf("error unmarshalling chunk: %v", err) } - var codeBlockRegex = regexp.MustCompile("(?m)^```[a-zA-Z]*$") - - // Extract content from the response if len(response.Choices) > 0 { content := response.Choices[0].Delta.Content - resultBuilder.WriteString(content) // Accumulate full result for return - - // Check for triple backtick boundaries - if strings.Contains(content, fmt.Sprintf("```%s", codeBlockRegex)) { - // Toggle inCodeBlock status when we detect backticks - inCodeBlock = !inCodeBlock - sectionBuilder.WriteString(content) // Add the boundary marker - - // If we just finished a code block, render and print the section - if !inCodeBlock { - section := sectionBuilder.String() - sectionBuilder.Reset() // Reset for the next section - - // Render and print markdown for the current section - if err := utils.RenderAndPrintMarkdown(section, openAIProvider.BufferingTheme); err != nil { - return "", err - } + resultBuilder.WriteString(content) // Gather full result for final return + + // Accumulate content in the markdown buffer + markdownBuffer.WriteString(content) + + // Process complete Markdown blocks (indicated by double newlines) + if strings.Contains(content, "\n") { + blockContent := markdownBuffer.String() + markdownBuffer.Reset() + + language := utils.DetectLanguageFromCodeBlock(blockContent) + err := utils.RenderAndPrintMarkdown(blockContent, language, openAIProvider.BufferingTheme) + if err != nil { + return "", err } - } else { - // Continue accumulating content within the section - sectionBuilder.WriteString(content) } } } } - // Render any remaining content in the section builder - if sectionBuilder.Len() > 0 { - if err := utils.RenderAndPrintMarkdown(sectionBuilder.String(), openAIProvider.BufferingTheme); err != nil { + // Flush remaining content in the buffer + if markdownBuffer.Len() > 0 { + blockContent := markdownBuffer.String() + language := utils.DetectLanguageFromCodeBlock(blockContent) + err := utils.RenderAndPrintMarkdown(blockContent, language, openAIProvider.BufferingTheme) + if err != nil { return "", err } } - // Return the accumulated full result return resultBuilder.String(), nil } diff --git a/utils/check_language.go b/utils/check_language.go index 7482820..378e813 100644 --- a/utils/check_language.go +++ b/utils/check_language.go @@ -1,6 +1,39 @@ package utils -import "strings" +import ( + "regexp" + "strings" +) + +var languageBuilder strings.Builder +var isInCodeBlock bool + +func DetectLanguageFromCodeBlock(content string) string { + + codeBlockRegex := regexp.MustCompile("^```([a-zA-Z]+)?\\s*$") + + if codeBlockRegex.MatchString(content) { + isInCodeBlock = !isInCodeBlock + languageBuilder.Reset() + } + + if isInCodeBlock && languageBuilder.Len() <= 15 { + languageBuilder.WriteString(content) + } + + // Define the regular expression to capture characters before the first newline + lanRegex := regexp.MustCompile("(?m)^```([a-zA-Z]+)(?:\\s*\\n)?") + + // Find the substring before the first newline + match := lanRegex.FindStringSubmatch(languageBuilder.String()) + + // Check if there was a match and print the result + if len(match) > 1 { + return match[1] + } + + return "plain-text" +} func GetSupportedLanguage(path string) string { // Use a switch statement to check for file extensions diff --git a/utils/confirm_prompt.go b/utils/confirm_prompt.go index e998f09..4615d55 100644 --- a/utils/confirm_prompt.go +++ b/utils/confirm_prompt.go @@ -9,11 +9,11 @@ import ( ) // ConfirmPrompt PromptUser prompts the user to accept or reject the changes with a charming interface -func ConfirmPrompt(path string) error { +func ConfirmPrompt(path string) (bool, error) { reader := bufio.NewReader(os.Stdin) // Styled prompt message - fmt.Printf(lipgloss_color.BlueSky.Render(fmt.Sprintf("Do you want to accept the change for file %v%v", lipgloss_color.LightBlueB.Render(path), lipgloss_color.BlueSky.Render(" ? (y/n): ")))) + fmt.Printf(lipgloss_color.BlueSky.Render(fmt.Sprintf("Do you want to accept the change for file `%v`%v", lipgloss_color.LightBlueB.Render(path), lipgloss_color.BlueSky.Render(" ? (y/n): ")))) for { // Read user input @@ -25,11 +25,9 @@ func ConfirmPrompt(path string) error { } if input == "y" || input == "Y" { - fmt.Println(lipgloss_color.Green.Render("โœ”๏ธ Changes accepted!")) - return nil + return true, nil } else if input == "n" || input == "N" { - fmt.Println(lipgloss_color.Red.Render("โŒ Changes rejected.")) - return nil + return false, nil } } } diff --git a/utils/markdown_generator.go b/utils/markdown_generator.go index f2215ec..174d98e 100644 --- a/utils/markdown_generator.go +++ b/utils/markdown_generator.go @@ -1,20 +1,16 @@ package utils import ( - "fmt" - "github.com/charmbracelet/glamour" + "github.com/alecthomas/chroma/v2/quick" + "os" ) // RenderAndPrintMarkdown handles the rendering of markdown content, -func RenderAndPrintMarkdown(content string, theme string) error { - // Render markdown using Glamour - md, err := glamour.Render(content, theme) +func RenderAndPrintMarkdown(content string, language string, theme string) error { + + err := quick.Highlight(os.Stdout, content, language, "terminal256", theme) if err != nil { - return fmt.Errorf("error rendering markdown: %v", err) + return err } - - // Print the rendered markdown - fmt.Print(md) - return nil }