mirror of
https://github.com/Pull-Pal/pull-pal.git
synced 2024-11-03 01:38:33 -04:00
d92efcb7e9
improve prompt templates to get response in yaml format and make parsing easier also add debug file functionality so that exact input, prompts, and output can be easily seen for every request
183 lines
5.7 KiB
Go
183 lines
5.7 KiB
Go
package cmd
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/mobyvb/pull-pal/pullpal"
|
|
"github.com/mobyvb/pull-pal/vc"
|
|
"github.com/sashabaranov/go-openai"
|
|
"go.uber.org/zap"
|
|
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
// todo: some of this config definition/usage can be moved to other packages
|
|
type config struct {
|
|
// bot credentials + github info
|
|
selfHandle string
|
|
selfEmail string
|
|
githubToken string
|
|
openAIToken string
|
|
|
|
// remote repo info
|
|
repos []string
|
|
|
|
// local paths
|
|
localRepoPath string
|
|
|
|
// program settings
|
|
usersToListenTo []string
|
|
requiredIssueLabels []string
|
|
waitDuration time.Duration
|
|
debugDir string
|
|
}
|
|
|
|
func getConfig() config {
|
|
return config{
|
|
selfHandle: viper.GetString("handle"),
|
|
selfEmail: viper.GetString("email"),
|
|
githubToken: viper.GetString("github-token"),
|
|
openAIToken: viper.GetString("open-ai-token"),
|
|
|
|
repos: viper.GetStringSlice("repos"),
|
|
|
|
localRepoPath: viper.GetString("local-repo-path"),
|
|
|
|
usersToListenTo: viper.GetStringSlice("users-to-listen-to"),
|
|
requiredIssueLabels: viper.GetStringSlice("required-issue-labels"),
|
|
waitDuration: viper.GetDuration("wait-duration"),
|
|
debugDir: viper.GetString("debug-dir"),
|
|
}
|
|
}
|
|
|
|
func getPullPal(ctx context.Context, cfg config) (*pullpal.PullPal, error) {
|
|
// TODO figure out debug logging
|
|
log, err := zap.NewProduction()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
//log := zap.L()
|
|
|
|
author := vc.Author{
|
|
Email: cfg.selfEmail,
|
|
Handle: cfg.selfHandle,
|
|
Token: cfg.githubToken,
|
|
}
|
|
listIssueOptions := vc.ListIssueOptions{
|
|
Handles: cfg.usersToListenTo,
|
|
Labels: cfg.requiredIssueLabels,
|
|
}
|
|
// TODO make model configurable
|
|
ppCfg := pullpal.Config{
|
|
WaitDuration: cfg.waitDuration,
|
|
LocalRepoPath: cfg.localRepoPath,
|
|
Repos: cfg.repos,
|
|
Self: author,
|
|
ListIssueOptions: listIssueOptions,
|
|
// TODO configurable model
|
|
Model: openai.GPT4,
|
|
OpenAIToken: cfg.openAIToken,
|
|
DebugDir: cfg.debugDir,
|
|
}
|
|
p, err := pullpal.NewPullPal(ctx, log.Named("pullpal"), ppCfg)
|
|
|
|
return p, err
|
|
}
|
|
|
|
// rootCmd represents the base command when called without any subcommands
|
|
var rootCmd = &cobra.Command{
|
|
Short: "run an automated digital assitant to monitor and make code changes to a github repository",
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
cfg := getConfig()
|
|
|
|
p, err := getPullPal(cmd.Context(), cfg)
|
|
if err != nil {
|
|
fmt.Println("error creating new pull pal", err)
|
|
return
|
|
}
|
|
fmt.Println("Successfully initialized pull pal")
|
|
|
|
err = p.Run()
|
|
if err != nil {
|
|
fmt.Println("error running", err)
|
|
return
|
|
}
|
|
},
|
|
}
|
|
|
|
// Execute adds all child commands to the root command and sets flags appropriately.
|
|
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
|
func Execute() {
|
|
err := rootCmd.Execute()
|
|
if err != nil {
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
var cfgFile string
|
|
|
|
func init() {
|
|
cobra.OnInitialize(initConfig)
|
|
|
|
// TODO make config values requried
|
|
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.pull-pal.yaml)")
|
|
|
|
rootCmd.PersistentFlags().StringP("handle", "u", "HANDLE", "handle to use for version control actions")
|
|
rootCmd.PersistentFlags().StringP("email", "e", "EMAIL", "email to use for version control actions")
|
|
rootCmd.PersistentFlags().StringP("github-token", "t", "GITHUB TOKEN", "token for authenticating Github actions")
|
|
rootCmd.PersistentFlags().StringP("open-ai-token", "k", "OPENAI TOKEN", "token for authenticating OpenAI")
|
|
|
|
rootCmd.PersistentFlags().StringSliceP("repos", "r", []string{}, "a list of git repositories that Pull Pal will monitor")
|
|
|
|
rootCmd.PersistentFlags().StringP("local-repo-path", "l", "/tmp/pullpalrepo", "local path to check out ephemeral repository in")
|
|
|
|
rootCmd.PersistentFlags().StringSliceP("users-to-listen-to", "a", []string{}, "a list of Github users that Pull Pal will respond to")
|
|
rootCmd.PersistentFlags().StringSliceP("required-issue-labels", "i", []string{}, "a list of labels that are required for Pull Pal to select an issue")
|
|
rootCmd.PersistentFlags().Duration("wait-time", 30*time.Second, "the amount of time Pull Pal should wait when no issues or comments are found to address")
|
|
rootCmd.PersistentFlags().StringP("debug-dir", "d", "", "the path to use for the pull pal debug directory")
|
|
|
|
viper.BindPFlag("handle", rootCmd.PersistentFlags().Lookup("handle"))
|
|
viper.BindPFlag("email", rootCmd.PersistentFlags().Lookup("email"))
|
|
viper.BindPFlag("github-token", rootCmd.PersistentFlags().Lookup("github-token"))
|
|
viper.BindPFlag("open-ai-token", rootCmd.PersistentFlags().Lookup("open-ai-token"))
|
|
|
|
viper.BindPFlag("repos", rootCmd.PersistentFlags().Lookup("repos"))
|
|
|
|
viper.BindPFlag("local-repo-path", rootCmd.PersistentFlags().Lookup("local-repo-path"))
|
|
|
|
viper.BindPFlag("users-to-listen-to", rootCmd.PersistentFlags().Lookup("users-to-listen-to"))
|
|
viper.BindPFlag("required-issue-labels", rootCmd.PersistentFlags().Lookup("required-issue-labels"))
|
|
viper.BindPFlag("wait-time", rootCmd.PersistentFlags().Lookup("wait-time"))
|
|
viper.BindPFlag("debug-dir", rootCmd.PersistentFlags().Lookup("debug-dir"))
|
|
}
|
|
|
|
func initConfig() {
|
|
if cfgFile != "" {
|
|
fmt.Println("cfg file exists")
|
|
// Use config file from the flag.
|
|
viper.SetConfigFile(cfgFile)
|
|
} else {
|
|
// Find home directory.
|
|
home, err := os.UserHomeDir()
|
|
cobra.CheckErr(err)
|
|
|
|
// Search config in home directory with name ".cobra" (without extension).
|
|
viper.AddConfigPath(home)
|
|
viper.SetConfigType("yaml")
|
|
viper.SetConfigName(".pull-pal")
|
|
}
|
|
|
|
// TODO figure out how to get env variables to work
|
|
viper.SetEnvPrefix("pullpal")
|
|
viper.AutomaticEnv()
|
|
|
|
if err := viper.ReadInConfig(); err == nil {
|
|
fmt.Println("Using config file:", viper.ConfigFileUsed())
|
|
}
|
|
|
|
}
|