summary history files

internal/cli/chat.go
package cli

import (
	"blue/internal/chatcompletion"
	"blue/internal/editor"
	"blue/internal/model"
	"fmt"
	"os"
	"strings"

	tea "github.com/charmbracelet/bubbletea"
	openai "github.com/sashabaranov/go-openai"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

func chatCmd(cli *cli) *cobra.Command {
	var flags struct {
		maxTokens int
		model     string
		editor    bool
	}

	var cmd = &cobra.Command{
		Use: "chat",
		PreRun: func(cmd *cobra.Command, args []string) {
			_ = viper.BindPFlag("max-tokens", cmd.Flags().Lookup("max-tokens"))
		},
		RunE: func(cmd *cobra.Command, args []string) error {
			var content string
			var err error

			apiKey := os.Getenv("OPENAI_API_KEY")

			if apiKey == "" {
				return fmt.Errorf("set OPENAI_API_KEY")
			}

			c := openai.NewClient(apiKey)
			if len(args) == 0 && flags.editor {
				editor := editor.NewEditor()
				content, err = editor.Edit()
				if err != nil {
					return err
				}
			} else if len(args) == 0 {
				i := ""

				msgs := []openai.ChatCompletionMessage{}
				for {

					modelOpts := []model.OptFunc{}
					if i != "" {
						modelOpts = append(modelOpts, model.WithInitialValue(i))
					}

					if len(msgs) >= 1 {
						modelOpts = append(modelOpts, model.WithChatCompletionMessages(msgs))
					}

					m := model.NewModel(modelOpts...)
					if _, err := tea.NewProgram(m).Run(); err != nil {
						return err
					}

					if m.UserInput.Input() == "" {
						break
					}

					if m.Ready() {
						chatCompletionOpts := []chatcompletion.OptFunc{}
						if len(m.Messages()) >= 1 {
							chatCompletionOpts = append(chatCompletionOpts, chatcompletion.WithChatCompletionMessages(m.Messages()))
						}
						chatCompletion := chatcompletion.NewChatCompletion(chatCompletionOpts...)
						if err := chatCompletion.Message("user", m.UserInput.FilteredInput()); err != nil {
							return err
						}

						_, err := chatcompletion.StreamChatCompletion(cmd.Context(), c, chatCompletion.Request())
						if err != nil {
							return err
						}
						msgs = chatCompletion.Messages()
						fmt.Println()
						m.Reset()
					} else {
						i = m.UserInput.FilteredInput()
					}
				}
				return nil
			} else {
				content = strings.Join(args, " ")
			}

			chatCompletion := chatcompletion.NewChatCompletion()
			if err := chatCompletion.Message("user", content); err != nil {
				return err
			}
			if _, err := chatcompletion.StreamChatCompletion(cmd.Context(), c, chatCompletion.Request()); err != nil {
				return err
			}

			return nil
		},
	}

	cmd.Flags().IntVar(&flags.maxTokens, "max-tokens", 2048, "Max tokens")
	cmd.Flags().BoolVar(&flags.editor, "editor", false, "Editor")
	return cmd
}