summary history files

commit:eb62855a0b8aaedee15b437431fb57532e95b8d5
date:Sat May 20 22:12:22 2023 +1000
parents:cb57bd840787033cd3e1d79285f4b6481eb2e400, ce56823ac4a32ead8aa0d093a1aeee8b82927b1b
Merge pull request #4 from rene00/conversation

add initial support for conversation
diff --git a/README.md b/README.md
line changes: +10/-0
index a011305..369a4a9
--- a/README.md
+++ b/README.md
@@ -55,3 +55,13 @@ why does it rain?
 ┃ why does it rain?
 ┃ c:editor
 ```
+
+### printmessages
+`c:printmessages` prints the messages stored within the chat completion message
+```bash
+┃ why does it rain?
+┃ c:editor
+┃
+
+[]openai.ChatCompletionMessage{openai.ChatCompletionMessage{Role:"user", Content:"why does it rain?", Name:""}}
+```

diff --git a/internal/chatcompletion/chatcompletion.go b/internal/chatcompletion/chatcompletion.go
line changes: +22/-19
index ee1a68e..fc3da8c
--- a/internal/chatcompletion/chatcompletion.go
+++ b/internal/chatcompletion/chatcompletion.go
@@ -18,39 +18,39 @@ const baseDelay = 10 * time.Second
 const maxDelay = 60 * time.Second
 
 type ChatCompletion struct {
-	Opts
-	messages []openai.ChatCompletionMessage
-}
-
-type Opts struct {
 	model     string
 	maxTokens int
 	stream    bool
+	messages  []openai.ChatCompletionMessage
 }
 
-type OptFunc func(*Opts)
+type OptFunc func(*ChatCompletion)
+
+func WithMaxTokens(n int) OptFunc {
+	return func(c *ChatCompletion) {
+		c.maxTokens = n
+	}
+}
 
-func withMaxTokens(n int) OptFunc {
-	return func(opts *Opts) {
-		opts.maxTokens = n
+func WithChatCompletionMessages(m []openai.ChatCompletionMessage) OptFunc {
+	return func(c *ChatCompletion) {
+		c.messages = m
 	}
 }
 
-func defaultOpts() Opts {
-	return Opts{
+func NewChatCompletion(opts ...OptFunc) ChatCompletion {
+	c := ChatCompletion{
 		model:     openai.GPT3Dot5Turbo,
 		maxTokens: 2048,
 		stream:    true,
+		messages:  []openai.ChatCompletionMessage{},
 	}
-}
 
-func NewChatCompletion(opts ...OptFunc) ChatCompletion {
-	o := defaultOpts()
 	for _, fn := range opts {
-		fn(&o)
+		fn(&c)
 	}
 
-	return ChatCompletion{Opts: o}
+	return c
 }
 
 func (c *ChatCompletion) Message(role, content string) error {
@@ -81,12 +81,15 @@ func (c *ChatCompletion) Message(role, content string) error {
 
 func (c ChatCompletion) Request() openai.ChatCompletionRequest {
 	return openai.ChatCompletionRequest{
-		Model:     c.Opts.model,
-		MaxTokens: c.Opts.maxTokens,
-		Stream:    c.Opts.stream,
+		Model:     c.model,
+		MaxTokens: c.maxTokens,
+		Stream:    c.stream,
 		Messages:  c.messages,
 	}
+}
 
+func (c ChatCompletion) Messages() []openai.ChatCompletionMessage {
+	return c.messages
 }
 
 func getEBO(retries int) time.Duration {

diff --git a/internal/cli/chat.go b/internal/cli/chat.go
line changes: +20/-2
index 0fa6556..34d9919
--- a/internal/cli/chat.go
+++ b/internal/cli/chat.go
@@ -46,8 +46,20 @@ func chatCmd(cli *cli) *cobra.Command {
 				}
 			} else if len(args) == 0 {
 				i := ""
+
+				msgs := []openai.ChatCompletionMessage{}
 				for {
-					m := model.NewModel(i)
+
+					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
 					}
@@ -57,14 +69,20 @@ func chatCmd(cli *cli) *cobra.Command {
 					}
 
 					if m.Ready() {
-						chatCompletion := chatcompletion.NewChatCompletion()
+						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 {

diff --git a/internal/model/command.go b/internal/model/command.go
line changes: +11/-0
index 19cb206..172bfd3
--- a/internal/model/command.go
+++ b/internal/model/command.go
@@ -35,3 +35,14 @@ func (c EditorCommand) Run(m *Model) error {
 	m.UserInput.Update(content)
 	return nil
 }
+
+type PrintMessagesCommand struct{}
+
+func NewPrintMessagesCommand() Command {
+	return PrintMessagesCommand{}
+}
+
+func (c PrintMessagesCommand) Run(m *Model) error {
+	fmt.Printf("%#+v\n\n", m.Messages())
+	return nil
+}

diff --git a/internal/model/model.go b/internal/model/model.go
line changes: +57/-7
index 7893a5b..b976cdb
--- a/internal/model/model.go
+++ b/internal/model/model.go
@@ -6,6 +6,7 @@ import (
 
 	"github.com/charmbracelet/bubbles/textarea"
 	tea "github.com/charmbracelet/bubbletea"
+	"github.com/sashabaranov/go-openai"
 )
 
 type CommandMsg struct {
@@ -21,31 +22,76 @@ type errMsg error
 type Model struct {
 	textarea    textarea.Model
 	UserInput   UserInput
-	ready       bool
 	commandMsgs []CommandMsg
 	err         error
+	Opts
+}
+
+type Opts struct {
+	ready        bool
+	messages     []openai.ChatCompletionMessage
+	initialValue string
+}
+
+type OptFunc func(*Opts)
+
+func WithChatCompletionMessages(m []openai.ChatCompletionMessage) OptFunc {
+	return func(opts *Opts) {
+		opts.messages = m
+	}
+}
+
+func WithInitialValue(s string) OptFunc {
+	return func(opts *Opts) {
+		opts.initialValue = s
+	}
+}
+
+func WithReady() OptFunc {
+	return func(opts *Opts) {
+		opts.ready = true
+	}
+}
+
+func defaultOpts() Opts {
+	return Opts{
+		ready:        false,
+		messages:     nil,
+		initialValue: "",
+	}
 }
 
 var initialTextAreaHeight = 3
 
-func NewModel(s string) *Model {
+func NewModel(opts ...OptFunc) *Model {
+	o := defaultOpts()
+	for _, fn := range opts {
+		fn(&o)
+	}
+
 	t := textarea.New()
 	t.Placeholder = "press [tab] to submit prompt"
 	t.SetWidth(72)
 	t.SetHeight(initialTextAreaHeight)
 	t.ShowLineNumbers = false
 	t.Focus()
-	if s != "" {
-		t.SetValue(s)
+
+	if o.initialValue != "" {
+		t.SetValue(o.initialValue)
 	}
 
 	return &Model{
 		textarea: t,
+		Opts:     o,
 	}
 }
 
+func (m *Model) SetReady(r bool) {
+	m.Opts.ready = r
+}
+
 func (m *Model) Ready() bool {
-	return m.ready
+	return m.Opts.ready
 }
 
 func (m *Model) Init() tea.Cmd {
@@ -65,14 +111,14 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 			return m, tea.Quit
 		case tea.KeyTab:
 			m.UserInput = NewUserInput(m.textarea.Value())
-			m.ready = true
+			m.SetReady(true)
 
 			for _, command := range m.UserInput.Commands() {
 				m.commandMsgs = append(m.commandMsgs, NewCommandMsg(command))
 			}
 
 			if len(m.commandMsgs) >= 1 {
-				m.ready = false
+				m.SetReady(false)
 				return m.Update(m.commandMsgs[0])
 			}
 
@@ -116,3 +162,7 @@ func (m *Model) View() string {
 func (m *Model) Reset() {
 	m.textarea.SetValue("")
 }
+
+func (m *Model) Messages() []openai.ChatCompletionMessage {
+	return m.Opts.messages
+}

diff --git a/internal/model/userinput.go b/internal/model/userinput.go
line changes: +2/-0
index 72345f7..fdab338
--- a/internal/model/userinput.go
+++ b/internal/model/userinput.go
@@ -25,6 +25,8 @@ func NewUserInput(s string) UserInput {
 				u.commands = append(u.commands, NewEchoCommand())
 			case "editor":
 				u.commands = append(u.commands, NewEditorCommand())
+			case "printmessages":
+				u.commands = append(u.commands, NewPrintMessagesCommand())
 			default:
 			}
 		}