-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
178 lines (145 loc) · 6.04 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
package main
import (
"fmt"
"log/slog"
"os"
"os/exec"
"regexp"
"strings"
u "github.com/rostrovsky/sourceprompt/pkg/utils"
"github.com/spf13/cobra"
)
const DEFAULT_PROMPT = `You will be provided with a markdown text (under the "---" separator) containing the contents of a codebase. Each code snippet will be enclosed in code fences, along with the corresponding file name. Your task is to analyze the codebase and gain a comprehensive understanding of its structure, functionality, and key features.
Please follow these steps:
1. Read through the entire codebase carefully, paying attention to the file names and the code within each code fence.
2. Identify the main components, modules, or classes of the codebase and their responsibilities. Summarize the purpose and functionality of each significant component.
3. Analyze the relationships and dependencies between different parts of the codebase. Identify any important interactions, data flow, or control flow between the components.
4. Extract the most important features and functionalities implemented in the codebase. Highlight any critical algorithms, data structures, or design patterns used.
5. Consider the overall architecture and design of the codebase. Identify any architectural patterns or principles followed, such as MVC, MVVM, or microservices.
6. Evaluate the code quality, readability, and maintainability. Note any areas that could be improved or any potential issues or vulnerabilities.
7. Provide a summary of your analysis, including the key insights, strengths, and weaknesses of the codebase. Offer suggestions for improvements or optimizations, if applicable.
8. Based on your understanding of the codebase, provide guidance on how AI agents can effectively operate across the entire codebase. Identify the entry points, important functions, or APIs that the agents should focus on for interaction and manipulation.
9. Discuss any specific considerations or challenges that AI agents may face when working with this codebase, such as dependencies, external libraries, or platform-specific requirements.
10. Conclude your analysis by providing a high-level overview of the codebase's functionality, architecture, and potential use cases. Highlight any notable features or aspects that make this codebase unique or valuable.
Your analysis should be thorough, insightful, and aimed at enabling AI agents to effectively understand and operate within the given codebase. Provide clear explanations and examples to support your findings and recommendations.
---
`
const (
version = "1.0.5"
)
var (
rFlag bool
vFlag bool
eFlags []string
iFlags []string
oFlag string
pFlag string
)
var rootCmd = &cobra.Command{
Use: "sourceprompt [path]",
Short: "Converts your codebase into LLM prompt.\nAccepts local directory path or git repo URL as an argument.",
Args: cobra.ExactArgs(1),
Run: run,
}
var versionCmd = &cobra.Command{
Use: "version",
Short: "Prints the version of sourceprompt",
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("sourceprompt version %s\n", version)
},
}
var programLevel *slog.LevelVar
func init() {
rootCmd.Flags().BoolVarP(&rFlag, "raw", "r", false, "Return just file contents without LLM prompt")
rootCmd.Flags().BoolVarP(&vFlag, "verbose", "v", false, "Enable verbose output")
rootCmd.Flags().StringVarP(&oFlag, "output", "o", "", "Output file path")
rootCmd.Flags().StringVarP(&pFlag, "prompt", "p", "", "Prompt file path or URL")
rootCmd.Flags().StringSliceVarP(&eFlags, "exclude", "e", []string{}, "Regular expressions of filename patterns to exclude")
rootCmd.Flags().StringSliceVarP(&iFlags, "include", "i", []string{}, "Regular expressions of filename patterns to include")
rootCmd.AddCommand(versionCmd)
programLevel = new(slog.LevelVar)
h := slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: programLevel})
slog.SetDefault(slog.New(h))
}
func run(cmd *cobra.Command, args []string) {
if vFlag {
programLevel.Set(slog.LevelDebug)
}
path := args[0]
if !u.IsURL(path) && !u.IsFilePath(path) {
u.LogErrAndExit(fmt.Errorf("argument must be a valid git URL or file path"))
}
sb := strings.Builder{}
if rFlag {
slog.Debug("Raw mode - skipping LLM prompt")
} else {
if pFlag != "" {
slog.Debug("Using custom prompt")
promptContent, err := u.GetCustomPromptContent(pFlag)
if err != nil {
u.LogErrAndExit(err)
}
sb.Write(promptContent)
sb.WriteString("\n\n")
} else {
sb.WriteString(DEFAULT_PROMPT + "\n\n")
}
}
prefixToRemove := path
if u.IsURL(path) {
slog.Debug("Cloning using git", "url", path)
tempDir, err := os.MkdirTemp("", "sourceprompt-git-clone-")
if err != nil {
u.LogErrAndExit(fmt.Errorf("failed to create temporary directory: %v", err))
}
defer func() {
os.RemoveAll(tempDir)
slog.Debug("Temporary directory removed", "tempDir", tempDir)
}()
cmd := exec.Command("git", "clone", path, tempDir)
err = cmd.Run()
if err != nil {
u.LogErrAndExit(fmt.Errorf("failed to clone Git repository: %v", err))
}
slog.Debug("Repository cloned succesfully", "tempDir", tempDir)
path = tempDir
prefixToRemove = tempDir
}
var includeRes []*regexp.Regexp
var excludeRes []*regexp.Regexp
for _, pattern := range iFlags {
re, err := regexp.Compile(pattern)
if err != nil {
u.LogErrAndExit(fmt.Errorf("invalid include pattern '%s': %v", pattern, err))
}
includeRes = append(includeRes, re)
}
for _, pattern := range eFlags {
re, err := regexp.Compile(pattern)
if err != nil {
u.LogErrAndExit(fmt.Errorf("invalid exclude pattern '%s': %v", pattern, err))
}
excludeRes = append(excludeRes, re)
}
err := u.ProcessPath(path, prefixToRemove, includeRes, excludeRes, &sb)
if err != nil {
u.LogErrAndExit(err)
}
slog.Debug("Processing done")
if oFlag != "" {
slog.Debug("Saving output", "file", oFlag)
err := u.WriteToFile(oFlag, []byte(sb.String()))
if err != nil {
u.LogErrAndExit(err)
}
slog.Debug("File saved sucessfully")
} else {
fmt.Println(sb.String())
}
}
func main() {
if err := rootCmd.Execute(); err != nil {
slog.Error(err.Error())
os.Exit(1)
}
}