From 3f56161b5c9f158ee2727b7ac86ec541645ed810 Mon Sep 17 00:00:00 2001 From: Meysam Hadeli <35596795+meysamhadeli@users.noreply.github.com> Date: Fri, 29 Nov 2024 01:35:16 +0330 Subject: [PATCH 1/3] chore: add confirm prompt for adding files to context --- cmd/code.go | 69 +++++++++++-------- code_analyzer/analyzer.go | 2 - constants/lipgloss/lipgloss_color.go | 4 +- .../summarize_full_context_prompt.tmpl | 20 +++--- go.mod | 8 +-- go.sum | 12 ++-- utils/confirm_prompt.go | 26 ++++++- 7 files changed, 87 insertions(+), 54 deletions(-) diff --git a/cmd/code.go b/cmd/code.go index d21b3b3..4413351 100644 --- a/cmd/code.go +++ b/cmd/code.go @@ -75,33 +75,35 @@ func handleCodeCommand(rootDependencies *RootDependencies) { // Helper function to process and send the current chunks processEmbeddingsChunks := func() error { - if len(currentChunks) == 0 { - return nil // Nothing to process - } + if rootDependencies.Config.RAG { + if len(currentChunks) == 0 { + return nil // Nothing to process + } - // Extract the content from the currentChunks - var contents []string - for _, chunk := range currentChunks { - contents = append(contents, chunk.Content) - } + // Extract the content from the currentChunks + var contents []string + for _, chunk := range currentChunks { + contents = append(contents, chunk.Content) + } - // Delay before sending the request - time.Sleep(requestDelay) + // Delay before sending the request + time.Sleep(requestDelay) - // Make an embedding request for the current chunks - embedding, err := rootDependencies.CurrentEmbeddingProvider.EmbeddingRequest(ctx, contents) - if err != nil { - return err - } + // Make an embedding request for the current chunks + embedding, err := rootDependencies.CurrentEmbeddingProvider.EmbeddingRequest(ctx, contents) + if err != nil { + return err + } - // Save embeddings to the embedding store - for i, chunk := range currentChunks { - rootDependencies.Store.Save(chunk.RelativePath, chunk.Content, embedding[i]) - } + // Save embeddings to the embedding store + for i, chunk := range currentChunks { + rootDependencies.Store.Save(chunk.RelativePath, chunk.Content, embedding[i]) + } - // Reset the chunks and token count - currentChunks = []general_models.ChunkData{} - currentTokenCount = 0 + // Reset the chunks and token count + currentChunks = []general_models.ChunkData{} + currentTokenCount = 0 + } return nil } @@ -272,13 +274,26 @@ startLoop: // Label for the start loop if requestedContext != "" && err == nil { aiResponseBuilder.Reset() - fmt.Println(lipgloss.BlueSky.Render("\nThese files need to changes...\n")) + fmt.Print("\n") - if err := chatRequestOperation(); err != nil { - fmt.Println(lipgloss.Red.Render(fmt.Sprintf("%v", err))) - displayTokens() + contextAccepted, err := utils.ConfirmAdditinalContext() + if err != nil { + fmt.Println(lipgloss.Red.Render(fmt.Sprintf("error getting user prompt: %v", err))) continue } + + if contextAccepted { + fmt.Println(lipgloss.Green.Render("✔️ Context accepted!")) + + if err := chatRequestOperation(); err != nil { + fmt.Println(lipgloss.Red.Render(fmt.Sprintf("%v", err))) + displayTokens() + continue + } + + } else { + fmt.Println(lipgloss.Red.Render("❌ Context rejected.")) + } } } @@ -291,7 +306,7 @@ startLoop: // Label for the start loop continue } - fmt.Print("\n\n") + fmt.Print("\n") // Try to apply changes for _, change := range changes { diff --git a/code_analyzer/analyzer.go b/code_analyzer/analyzer.go index 0cf7eb9..e161cbc 100644 --- a/code_analyzer/analyzer.go +++ b/code_analyzer/analyzer.go @@ -191,8 +191,6 @@ func (analyzer *CodeAnalyzer) ProcessFile(filePath string, sourceCode []byte) [] log.Fatalf("failed to parse JSON: %v", err) } - elements = append(elements, filePath) - // Execute each query and capture results for tag, queryStr := range queries { query, err := sitter.NewQuery([]byte(queryStr), lang) // Use the appropriate language diff --git a/constants/lipgloss/lipgloss_color.go b/constants/lipgloss/lipgloss_color.go index ccb3bab..bc777a3 100644 --- a/constants/lipgloss/lipgloss_color.go +++ b/constants/lipgloss/lipgloss_color.go @@ -3,7 +3,7 @@ package lipgloss import "github.com/charmbracelet/lipgloss" var ( - BlueSky = lipgloss.NewStyle().Foreground(lipgloss.Color("#00BFFF")) + BlueSky = lipgloss.NewStyle().Foreground(lipgloss.Color("#00BFFF")).Bold(true) LightBlue = lipgloss.NewStyle().Foreground(lipgloss.Color("#2b7fec")).Bold(true) LightBlueB = lipgloss.NewStyle().Background(lipgloss.Color("#E5E7E9")).Foreground(lipgloss.Color("#2b7fec")).Bold(true) Red = lipgloss.NewStyle().Foreground(lipgloss.Color("197")) @@ -12,5 +12,5 @@ var ( Violet = lipgloss.NewStyle().Foreground(lipgloss.Color("#7F00FF")) Charm = lipgloss.NewStyle().Foreground(lipgloss.Color("205")).Bold(true) CharmB = lipgloss.NewStyle().Background(lipgloss.Color("#E5E7E9")).Foreground(lipgloss.Color("205")).Bold(true) - Gray = lipgloss.NewStyle().Foreground(lipgloss.Color("#bcbcbc")) + Gray = lipgloss.NewStyle().Foreground(lipgloss.Color("#bcbcbc")).Bold(true) ) diff --git a/embed_data/prompts/summarize_full_context_prompt.tmpl b/embed_data/prompts/summarize_full_context_prompt.tmpl index e0d2505..df162dd 100644 --- a/embed_data/prompts/summarize_full_context_prompt.tmpl +++ b/embed_data/prompts/summarize_full_context_prompt.tmpl @@ -5,21 +5,20 @@ > Your tasks are according to these steps: ## PRIORITY: Check for Specific Context in Code + - **You just have the signature of the full context and if you need a file for doing task just request full files from the user**. - **If I request the **specific context of code**, such as a **method**, **class**, or any **part of codes** that is an **empty body** or **incomplete** code, I will provide **full file of code** in the **next request** and base on that you can do your task and you **must** follow these steps:** - **These examples of context of code are incomplete**: - ```go + + --- function AddProduct(){ } - ``` - ```go + function DeleteProduct(){ - ``` - ```go + struct: Product - ``` - ```go + class: Product - ``` + --- - **I you see the incomplete code like above example just return the relative paths of the relevant files that are incomplete as a JSON array of strings in the following format:** ```json @@ -27,10 +26,7 @@ "files": ["relative path1", "relative path2"] } - **Skip all other tasks and return only this JSON response. Do not proceed to any additional prompt processing.** - -## General Instructions for Code Modifications -If the request does not fall under the above condition, proceed with the following steps: - + - **If you have requested full files for doing your task you can move forward for other prompts, otherwise just ignore other prompts.** ## Context Understanding: - Read and Analyze the code context carefully to identify where the requested changes should be added or modified. diff --git a/go.mod b/go.mod index 802c837..0cd387c 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.23.2 require ( github.com/alecthomas/chroma/v2 v2.14.0 github.com/charmbracelet/lipgloss v1.0.0 + 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 @@ -17,7 +18,7 @@ require ( atomicgo.dev/keyboard v0.2.9 // indirect atomicgo.dev/schedule v0.1.0 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect - github.com/charmbracelet/x/ansi v0.4.2 // indirect + github.com/charmbracelet/x/ansi v0.4.5 // indirect github.com/containerd/console v1.0.3 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dlclark/regexp2 v1.11.0 // indirect @@ -35,7 +36,6 @@ require ( github.com/mitchellh/mapstructure v1.5.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/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect @@ -50,8 +50,8 @@ require ( 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/sys v0.26.0 // indirect - golang.org/x/term v0.18.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/term v0.22.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 diff --git a/go.sum b/go.sum index acb8cf7..db2097a 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg= github.com/charmbracelet/lipgloss v1.0.0/go.mod h1:U5fy9Z+C38obMs+T+tJqst9VGzlOYGj4ri9reL3qUlo= -github.com/charmbracelet/x/ansi v0.4.2 h1:0JM6Aj/g/KC154/gOP4vfxun0ff6itogDYk41kof+qk= -github.com/charmbracelet/x/ansi v0.4.2/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/charmbracelet/x/ansi v0.4.5 h1:LqK4vwBNaXw2AyGIICa5/29Sbdq58GbGdFngSexTdRM= +github.com/charmbracelet/x/ansi v0.4.5/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= @@ -173,15 +173,15 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/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= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.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-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.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +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/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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= diff --git a/utils/confirm_prompt.go b/utils/confirm_prompt.go index 27a0d33..75c2124 100644 --- a/utils/confirm_prompt.go +++ b/utils/confirm_prompt.go @@ -8,7 +8,7 @@ import ( "strings" ) -// ConfirmPrompt PromptUser prompts the user to accept or reject the changes with a charming interface +// ConfirmPrompt prompts the user to accept or reject the changes in a file path func ConfirmPrompt(path string) (bool, error) { reader := bufio.NewReader(os.Stdin) @@ -31,3 +31,27 @@ func ConfirmPrompt(path string) (bool, error) { } } } + +// ConfirmAdditinalContext prompts the user to accept or reject additional context +func ConfirmAdditinalContext() (bool, error) { + reader := bufio.NewReader(os.Stdin) + + // Styled prompt message + fmt.Printf(lipgloss.Gray.Render(fmt.Sprintf("Do you want to add above files to context %s", lipgloss.Gray.Render("? (y/n): ")))) + + for { + // Read user input + input, _ := reader.ReadString('\n') + input = strings.TrimSpace(input) + + if input == "" { + continue + } + + if input == "y" || input == "Y" { + return true, nil + } else if input == "n" || input == "N" { + return false, nil + } + } +} From 4d2f7c32a93c72bbf407990c250ac5e6b984d182 Mon Sep 17 00:00:00 2001 From: Meysam Hadeli <35596795+meysamhadeli@users.noreply.github.com> Date: Fri, 29 Nov 2024 01:42:56 +0330 Subject: [PATCH 2/3] fix: fix test for processing files --- code_analyzer/analyzer_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code_analyzer/analyzer_test.go b/code_analyzer/analyzer_test.go index 999a9b8..2c3a3c0 100644 --- a/code_analyzer/analyzer_test.go +++ b/code_analyzer/analyzer_test.go @@ -54,7 +54,7 @@ func TestRunInSequence(t *testing.T) { t.Run("TestGeneratePrompt_ActualImplementation", TestGeneratePrompt_ActualImplementation) t.Run("TestNewCodeAnalyzer", TestNewCodeAnalyzer) t.Run("TestGetProjectFiles", TestGetProjectFiles) - t.Run("TestProcessFile", TestProcessFile) + t.Run("TestProcessFileWithSupportedLanguageReturnTreeSitterResult", TestProcessFileWithSupportedLanguageReturnTreeSitterResult) t.Run("TestApplyChanges_NewFile", TestApplyChanges_NewFile) t.Run("TestApplyChanges_ModifyFile", TestApplyChanges_ModifyFile) t.Run("TestApplyChanges_DeletedFile", TestApplyChanges_DeletedFile) @@ -148,13 +148,13 @@ func TestGetProjectFiles(t *testing.T) { } // Test for ProcessFile -func TestProcessFile(t *testing.T) { +func TestProcessFileWithSupportedLanguageReturnTreeSitterResult(t *testing.T) { setup(t) content := []byte("class Test {}") result := analyzer.ProcessFile("test.cs", content) - assert.Contains(t, result, "test.cs") + assert.Contains(t, result, "class: Test") assert.NotEmpty(t, result) } From e60d751d7f716b789b0653edd9ad52a2f86d5205 Mon Sep 17 00:00:00 2001 From: Meysam Hadeli <35596795+meysamhadeli@users.noreply.github.com> Date: Fri, 29 Nov 2024 01:50:32 +0330 Subject: [PATCH 3/3] refactor: refactor print file name structure --- code_analyzer/analyzer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code_analyzer/analyzer.go b/code_analyzer/analyzer.go index e161cbc..f0760b7 100644 --- a/code_analyzer/analyzer.go +++ b/code_analyzer/analyzer.go @@ -245,7 +245,7 @@ func (analyzer *CodeAnalyzer) TryGetInCompletedCodeBlocK(relativePaths string) ( continue } - codes = append(codes, fmt.Sprintf("File: %s\n\n%s", relativePath, content)) + codes = append(codes, fmt.Sprintf("**File: %s**\n\n%s", relativePath, content)) } if len(codes) == 0 {