Implement `lmcli view [conversation]` with completions

Separate out logic to retrieve a message's "friendly" role (System,
User, Assistant)
This commit is contained in:
Matt Low 2023-11-12 23:32:12 +00:00
parent b0a1299e0b
commit b87c3ffc53
4 changed files with 65 additions and 13 deletions

View File

@ -111,11 +111,36 @@ var lsCmd = &cobra.Command{
} }
var viewCmd = &cobra.Command{ var viewCmd = &cobra.Command{
Use: "view", Use: "view [conversation]",
Short: "View messages in a conversation", Short: "View messages in a conversation",
Long: `Displays all the messages in a coversation.`, Long: `Finds a conversation by its short name and displays its contents.`,
Args: func(cmd *cobra.Command, args []string) error {
argCount := 1
if err := cobra.MinimumNArgs(argCount)(cmd, args); err != nil {
return err
}
return nil
},
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Displaying conversation messages...") shortName := args[0]
conversation, err := store.ConversationByShortName(shortName)
if conversation.ID == 0 {
Fatal("Conversation not found with short name: %s\n", shortName)
}
messages, err := store.GetMessages(conversation)
if err != nil {
Fatal("Could not retrieve messages for conversation: %s\n", conversation.Title)
}
l := len(messages)
for i, message := range messages {
message.RenderTTY(i < l-1)
}
fmt.Println()
},
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return store.ConverstionShortNameCompletions(toComplete), cobra.ShellCompDirectiveNoFileComp
}, },
} }
@ -239,6 +264,7 @@ func NewRootCmd() *cobra.Command {
lsCmd, lsCmd,
newCmd, newCmd,
promptCmd, promptCmd,
viewCmd,
) )
return rootCmd return rootCmd
} }

17
pkg/cli/conversation.go Normal file
View File

@ -0,0 +1,17 @@
package cli
// FriendlyRole returns a human friendly signifier for the message's role.
func (m *Message) FriendlyRole() string {
var friendlyRole string
switch m.Role {
case "user":
friendlyRole = "You"
case "system":
friendlyRole = "System"
case "assistant":
friendlyRole = "Assistant"
default:
friendlyRole = m.Role
}
return friendlyRole
}

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"time" "time"
sqids "github.com/sqids/sqids-go" sqids "github.com/sqids/sqids-go"
@ -95,6 +96,23 @@ func (s *Store) GetConversations() ([]Conversation, error) {
return conversations, err return conversations, err
} }
func (s *Store) ConverstionShortNameCompletions(shortName string) []string {
var completions []string
conversations, _ := s.GetConversations() // ignore error for completions
for _, conversation := range conversations {
if shortName == "" || strings.HasPrefix(conversation.ShortName.String, shortName) {
completions = append(completions, fmt.Sprintf("%s\t%s", conversation.ShortName.String, conversation.Title))
}
}
return completions
}
func (s *Store) ConversationByShortName(shortName string) (*Conversation, error) {
var conversation Conversation
err := s.db.Where("short_name = ?", shortName).Find(&conversation).Error
return &conversation, err
}
func (s *Store) GetMessages(conversation *Conversation) ([]Message, error) { func (s *Store) GetMessages(conversation *Conversation) ([]Message, error) {
var messages []Message var messages []Message
err := s.db.Where("conversation_id = ?", conversation.ID).Find(&messages).Error err := s.db.Where("conversation_id = ?", conversation.ID).Find(&messages).Error

View File

@ -59,16 +59,7 @@ func HandleDelayedResponse(response chan string) string {
} }
func (m *Message) RenderTTY(paddingDown bool) { func (m *Message) RenderTTY(paddingDown bool) {
var friendlyRole string fmt.Printf("<%s>\n\n", m.FriendlyRole())
switch m.Role {
case "user":
friendlyRole = "You"
case "system":
friendlyRole = "System"
case "assistant":
friendlyRole = "Assistant"
}
fmt.Printf("<%s>\n\n", friendlyRole)
if m.OriginalContent != "" { if m.OriginalContent != "" {
fmt.Print(m.OriginalContent) fmt.Print(m.OriginalContent)
} }