Matt Low
0384c7cb66
This refactor splits out all conversation concerns into a new `conversation` package. There is now a split between `conversation` and `api`s representation of `Message`, the latter storing the minimum information required for interaction with LLM providers. There is necessary conversation between the two when making LLM calls.
113 lines
2.9 KiB
Go
113 lines
2.9 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"git.mlow.ca/mlow/lmcli/pkg/lmcli"
|
|
"git.mlow.ca/mlow/lmcli/pkg/util"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
const (
|
|
LS_COUNT int = 5
|
|
)
|
|
|
|
func ListCmd(ctx *lmcli.Context) *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "list",
|
|
Aliases: []string{"ls"},
|
|
Short: "List conversations",
|
|
Long: `List conversations in order of recent activity`,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
messages, err := ctx.Conversations.LatestConversationMessages()
|
|
if err != nil {
|
|
return fmt.Errorf("Could not fetch conversations: %v", err)
|
|
}
|
|
|
|
type Category struct {
|
|
name string
|
|
cutoff time.Duration
|
|
}
|
|
|
|
type ConversationLine struct {
|
|
timeSinceReply time.Duration
|
|
formatted string
|
|
}
|
|
|
|
now := time.Now()
|
|
|
|
midnight := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
|
monthStart := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
|
|
dayOfWeek := int(now.Weekday())
|
|
categories := []Category{
|
|
{"today", now.Sub(midnight)},
|
|
{"yesterday", now.Sub(midnight.AddDate(0, 0, -1))},
|
|
{"this week", now.Sub(midnight.AddDate(0, 0, -dayOfWeek))},
|
|
{"last week", now.Sub(midnight.AddDate(0, 0, -(dayOfWeek + 7)))},
|
|
{"this month", now.Sub(monthStart)},
|
|
{"last month", now.Sub(monthStart.AddDate(0, -1, 0))},
|
|
{"2 months ago", now.Sub(monthStart.AddDate(0, -2, 0))},
|
|
{"3 months ago", now.Sub(monthStart.AddDate(0, -3, 0))},
|
|
{"4 months ago", now.Sub(monthStart.AddDate(0, -4, 0))},
|
|
{"5 months ago", now.Sub(monthStart.AddDate(0, -5, 0))},
|
|
{"older", now.Sub(time.Time{})},
|
|
}
|
|
categorized := map[string][]ConversationLine{}
|
|
|
|
all, _ := cmd.Flags().GetBool("all")
|
|
|
|
for _, message := range messages {
|
|
messageAge := now.Sub(message.CreatedAt)
|
|
|
|
var category string
|
|
for _, c := range categories {
|
|
if messageAge < c.cutoff {
|
|
category = c.name
|
|
break
|
|
}
|
|
}
|
|
|
|
formatted := fmt.Sprintf(
|
|
"%s - %s - %s",
|
|
message.Conversation.ShortName.String,
|
|
util.HumanTimeElapsedSince(messageAge),
|
|
message.Conversation.Title,
|
|
)
|
|
|
|
categorized[category] = append(
|
|
categorized[category],
|
|
ConversationLine{messageAge, formatted},
|
|
)
|
|
}
|
|
|
|
count, _ := cmd.Flags().GetInt("count")
|
|
var conversationsPrinted int
|
|
outer:
|
|
for _, category := range categories {
|
|
conversationLines, ok := categorized[category.name]
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
fmt.Printf("%s:\n", category.name)
|
|
for _, conv := range conversationLines {
|
|
if conversationsPrinted >= count && !all {
|
|
fmt.Printf("%d remaining conversation(s), use --all to view.\n", len(messages)-conversationsPrinted)
|
|
break outer
|
|
}
|
|
|
|
fmt.Printf(" %s\n", conv.formatted)
|
|
conversationsPrinted++
|
|
}
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
|
|
cmd.Flags().BoolP("all", "a", false, "Show all conversations")
|
|
cmd.Flags().IntP("count", "c", LS_COUNT, "How many conversations to show")
|
|
|
|
return cmd
|
|
}
|