Add clone command

Used RunE instead of Run, make adjustments to rootCmd so that we control
how error messages are printed (in main())
This commit is contained in:
Matt Low 2024-01-03 07:32:29 +00:00
parent b3913d0027
commit 02a23b9035
1 changed files with 76 additions and 2 deletions

View File

@ -36,6 +36,7 @@ func init() {
renameCmd.Flags().Bool("generate", false, "Generate a conversation title") renameCmd.Flags().Bool("generate", false, "Generate a conversation title")
rootCmd.AddCommand( rootCmd.AddCommand(
cloneCmd,
continueCmd, continueCmd,
editCmd, editCmd,
lsCmd, lsCmd,
@ -101,6 +102,17 @@ func lookupConversation(shortName string) *Conversation {
return c return c
} }
func lookupConversationE(shortName string) (*Conversation, error) {
c, err := store.ConversationByShortName(shortName)
if err != nil {
return nil, fmt.Errorf("Could not lookup conversation: %v", err)
}
if c.ID == 0 {
return nil, fmt.Errorf("Conversation not found with short name: %s", shortName)
}
return c, nil
}
// handleConversationReply handles sending messages to an existing // handleConversationReply handles sending messages to an existing
// conversation, optionally persisting them. It displays the entire // conversation, optionally persisting them. It displays the entire
// conversation before // conversation before
@ -161,8 +173,10 @@ func inputFromArgsOrEditor(args []string, placeholder string, existingMessage st
} }
var rootCmd = &cobra.Command{ var rootCmd = &cobra.Command{
Use: "lmcli", Use: "lmcli <command> [flags]",
Long: `lmcli - command-line interface with Large Language Models.`, Long: `lmcli - Large Language Model CLI`,
SilenceErrors: true,
SilenceUsage: true,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
// execute `lm ls` by default // execute `lm ls` by default
}, },
@ -314,6 +328,66 @@ var rmCmd = &cobra.Command{
}, },
} }
var cloneCmd = &cobra.Command{
Use: "clone <conversation>",
Short: "Clone conversations.",
Long: `Clones the provided conversation.`,
Args: func(cmd *cobra.Command, args []string) error {
argCount := 1
if err := cobra.MinimumNArgs(argCount)(cmd, args); err != nil {
return err
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
shortName := args[0]
toClone, err := lookupConversationE(shortName)
if err != nil {
return err
}
messagesToCopy, err := store.Messages(toClone)
if err != nil {
return fmt.Errorf("Could not retrieve messages for conversation: %s", toClone.ShortName.String)
}
clone := &Conversation{
Title: toClone.Title + " - Clone",
}
if err := store.SaveConversation(clone); err != nil {
return fmt.Errorf("Cloud not create clone: %s", err)
}
var errors []error
messageCnt := 0
for _, message := range messagesToCopy {
newMessage := message
newMessage.ConversationID = clone.ID
newMessage.ID = 0
if err := store.SaveMessage(&newMessage); err != nil {
errors = append(errors, err)
} else {
messageCnt++
}
}
if len(errors) > 0 {
return fmt.Errorf("Messages failed to be cloned: %v", errors)
}
fmt.Printf("Cloned %d messages to: %s\n", messageCnt, clone.Title)
return nil
},
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
compMode := cobra.ShellCompDirectiveNoFileComp
if len(args) != 0 {
return nil, compMode
}
return store.ConversationShortNameCompletions(toComplete), compMode
},
}
var viewCmd = &cobra.Command{ var viewCmd = &cobra.Command{
Use: "view <conversation>", Use: "view <conversation>",
Short: "View messages in a conversation", Short: "View messages in a conversation",