| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- package cmd
- import (
- "fmt"
- "os"
- "github.com/fatih/color"
- "github.com/letta/letta-schedules-cli/internal/client"
- "github.com/letta/letta-schedules-cli/internal/config"
- "github.com/letta/letta-schedules-cli/internal/parser"
- "github.com/olekukonko/tablewriter"
- "github.com/spf13/cobra"
- )
- var recurringCmd = &cobra.Command{
- Use: "recurring",
- Short: "Manage recurring schedules",
- Long: "Create, list, view, and delete recurring schedules for Letta agents",
- }
- var recurringCreateCmd = &cobra.Command{
- Use: "create",
- Short: "Create a new recurring schedule",
- RunE: func(cmd *cobra.Command, args []string) error {
- agentID, _ := cmd.Flags().GetString("agent-id")
- message, _ := cmd.Flags().GetString("message")
- role, _ := cmd.Flags().GetString("role")
- cronString, _ := cmd.Flags().GetString("cron")
- if agentID == "" || message == "" || cronString == "" {
- return fmt.Errorf("agent-id, message, and cron are required")
- }
- // Parse natural language to cron expression
- parsedCron, err := parser.ParseCron(cronString)
- if err != nil {
- return fmt.Errorf("failed to parse cron: %w", err)
- }
- cfg, err := config.Load()
- if err != nil {
- return err
- }
- if err := cfg.Validate(); err != nil {
- return err
- }
- apiClient := client.NewClient(cfg.BaseURL, cfg.APIKey)
- schedule, err := apiClient.CreateRecurringSchedule(client.RecurringScheduleCreate{
- AgentID: agentID,
- Message: message,
- Role: role,
- CronString: parsedCron,
- })
- if err != nil {
- return fmt.Errorf("failed to create schedule: %w", err)
- }
- color.Green("✓ Recurring schedule created successfully")
- fmt.Printf("\nSchedule ID: %s\n", schedule.ID)
- fmt.Printf("Agent ID: %s\n", schedule.AgentID)
- fmt.Printf("Cron: %s\n", schedule.CronString)
- fmt.Printf("Message: %s\n", schedule.Message)
- return nil
- },
- }
- var recurringListCmd = &cobra.Command{
- Use: "list",
- Short: "List all recurring schedules",
- RunE: func(cmd *cobra.Command, args []string) error {
- cfg, err := config.Load()
- if err != nil {
- return err
- }
- if err := cfg.Validate(); err != nil {
- return err
- }
- apiClient := client.NewClient(cfg.BaseURL, cfg.APIKey)
- schedules, err := apiClient.ListRecurringSchedules()
- if err != nil {
- return fmt.Errorf("failed to list schedules: %w", err)
- }
- if len(schedules) == 0 {
- fmt.Println("No recurring schedules found")
- return nil
- }
- table := tablewriter.NewWriter(os.Stdout)
- table.SetHeader([]string{"Schedule ID", "Agent ID", "Cron", "Message", "Last Run"})
- table.SetAutoWrapText(false)
- table.SetAutoFormatHeaders(true)
- table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
- table.SetAlignment(tablewriter.ALIGN_LEFT)
- table.SetCenterSeparator("")
- table.SetColumnSeparator("")
- table.SetRowSeparator("")
- table.SetHeaderLine(false)
- table.SetBorder(false)
- table.SetTablePadding("\t")
- table.SetNoWhiteSpace(true)
- for _, s := range schedules {
- lastRun := "never"
- if s.LastRun != nil && *s.LastRun != "" {
- lastRun = *s.LastRun
- }
- table.Append([]string{
- s.ID,
- s.AgentID,
- s.CronString,
- truncate(s.Message, 50),
- lastRun,
- })
- }
- table.Render()
- return nil
- },
- }
- var recurringGetCmd = &cobra.Command{
- Use: "get [schedule-id]",
- Short: "Get details of a recurring schedule",
- Args: cobra.ExactArgs(1),
- RunE: func(cmd *cobra.Command, args []string) error {
- scheduleID := args[0]
- cfg, err := config.Load()
- if err != nil {
- return err
- }
- if err := cfg.Validate(); err != nil {
- return err
- }
- apiClient := client.NewClient(cfg.BaseURL, cfg.APIKey)
- schedule, err := apiClient.GetRecurringSchedule(scheduleID)
- if err != nil {
- return fmt.Errorf("failed to get schedule: %w", err)
- }
- fmt.Printf("Schedule ID: %s\n", schedule.ID)
- fmt.Printf("Agent ID: %s\n", schedule.AgentID)
- fmt.Printf("Cron: %s\n", schedule.CronString)
- fmt.Printf("Message: %s\n", schedule.Message)
- fmt.Printf("Role: %s\n", schedule.Role)
- if schedule.LastRun != nil {
- fmt.Printf("Last Run: %s\n", *schedule.LastRun)
- } else {
- fmt.Printf("Last Run: never\n")
- }
- fmt.Printf("Created At: %s\n", schedule.CreatedAt.Format("2006-01-02 15:04:05"))
- return nil
- },
- }
- var recurringDeleteCmd = &cobra.Command{
- Use: "delete [schedule-id]",
- Short: "Delete a recurring schedule",
- Args: cobra.ExactArgs(1),
- RunE: func(cmd *cobra.Command, args []string) error {
- scheduleID := args[0]
- cfg, err := config.Load()
- if err != nil {
- return err
- }
- if err := cfg.Validate(); err != nil {
- return err
- }
- apiClient := client.NewClient(cfg.BaseURL, cfg.APIKey)
- if err := apiClient.DeleteRecurringSchedule(scheduleID); err != nil {
- return fmt.Errorf("failed to delete schedule: %w", err)
- }
- color.Green("✓ Schedule deleted successfully")
- return nil
- },
- }
- func init() {
- rootCmd.AddCommand(recurringCmd)
- recurringCmd.AddCommand(recurringCreateCmd)
- recurringCreateCmd.Flags().String("agent-id", "", "Agent ID (required)")
- recurringCreateCmd.Flags().String("message", "", "Message to send (required)")
- recurringCreateCmd.Flags().String("role", "user", "Message role (default: user)")
- recurringCreateCmd.Flags().String("cron", "", "Schedule pattern (required)\n Examples: 'every 5 minutes', 'daily at 9am', 'every monday at 3pm', '*/5 * * * *'")
- recurringCmd.AddCommand(recurringListCmd)
- recurringCmd.AddCommand(recurringGetCmd)
- recurringCmd.AddCommand(recurringDeleteCmd)
- }
- func truncate(s string, maxLen int) string {
- if len(s) <= maxLen {
- return s
- }
- return s[:maxLen-3] + "..."
- }
|