onetime.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. package cmd
  2. import (
  3. "fmt"
  4. "os"
  5. "github.com/fatih/color"
  6. "github.com/letta/letta-schedules-cli/internal/client"
  7. "github.com/letta/letta-schedules-cli/internal/config"
  8. "github.com/letta/letta-schedules-cli/internal/parser"
  9. "github.com/olekukonko/tablewriter"
  10. "github.com/spf13/cobra"
  11. )
  12. var onetimeCmd = &cobra.Command{
  13. Use: "onetime",
  14. Aliases: []string{"send", "message"},
  15. Short: "Send messages to agents",
  16. Long: "Send one-time messages to Letta agents immediately or scheduled for later",
  17. }
  18. var onetimeCreateCmd = &cobra.Command{
  19. Use: "create",
  20. Aliases: []string{"send"},
  21. Short: "Send a message to an agent",
  22. Long: "Send a message to an agent immediately or scheduled for later",
  23. RunE: func(cmd *cobra.Command, args []string) error {
  24. agentID, _ := cmd.Flags().GetString("agent-id")
  25. message, _ := cmd.Flags().GetString("message")
  26. role, _ := cmd.Flags().GetString("role")
  27. executeAt, _ := cmd.Flags().GetString("execute-at")
  28. if agentID == "" || message == "" {
  29. return fmt.Errorf("agent-id and message are required")
  30. }
  31. // Default to "now" if no time specified
  32. if executeAt == "" {
  33. executeAt = "now"
  34. }
  35. // Parse natural language time to ISO 8601
  36. parsedTime, err := parser.ParseTime(executeAt)
  37. if err != nil {
  38. return fmt.Errorf("failed to parse execute-at: %w", err)
  39. }
  40. cfg, err := config.Load()
  41. if err != nil {
  42. return err
  43. }
  44. if err := cfg.Validate(); err != nil {
  45. return err
  46. }
  47. apiClient := client.NewClient(cfg.BaseURL, cfg.APIKey)
  48. schedule, err := apiClient.CreateOneTimeSchedule(client.OneTimeScheduleCreate{
  49. AgentID: agentID,
  50. Message: message,
  51. Role: role,
  52. ExecuteAt: parsedTime,
  53. })
  54. if err != nil {
  55. return fmt.Errorf("failed to create schedule: %w", err)
  56. }
  57. if executeAt == "now" {
  58. color.Green("✓ Message sent successfully (executing immediately)")
  59. } else {
  60. color.Green("✓ Message scheduled successfully")
  61. }
  62. fmt.Printf("\nSchedule ID: %s\n", schedule.ID)
  63. fmt.Printf("Agent ID: %s\n", schedule.AgentID)
  64. fmt.Printf("Execute At: %s\n", schedule.ExecuteAt)
  65. fmt.Printf("Message: %s\n", schedule.Message)
  66. return nil
  67. },
  68. }
  69. var onetimeListCmd = &cobra.Command{
  70. Use: "list",
  71. Short: "List all one-time schedules",
  72. RunE: func(cmd *cobra.Command, args []string) error {
  73. cfg, err := config.Load()
  74. if err != nil {
  75. return err
  76. }
  77. if err := cfg.Validate(); err != nil {
  78. return err
  79. }
  80. apiClient := client.NewClient(cfg.BaseURL, cfg.APIKey)
  81. schedules, err := apiClient.ListOneTimeSchedules()
  82. if err != nil {
  83. return fmt.Errorf("failed to list schedules: %w", err)
  84. }
  85. if len(schedules) == 0 {
  86. fmt.Println("No one-time schedules found")
  87. return nil
  88. }
  89. table := tablewriter.NewWriter(os.Stdout)
  90. table.SetHeader([]string{"Schedule ID", "Agent ID", "Execute At", "Message"})
  91. table.SetAutoWrapText(false)
  92. table.SetAutoFormatHeaders(true)
  93. table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
  94. table.SetAlignment(tablewriter.ALIGN_LEFT)
  95. table.SetCenterSeparator("")
  96. table.SetColumnSeparator("")
  97. table.SetRowSeparator("")
  98. table.SetHeaderLine(false)
  99. table.SetBorder(false)
  100. table.SetTablePadding("\t")
  101. table.SetNoWhiteSpace(true)
  102. for _, s := range schedules {
  103. table.Append([]string{
  104. s.ID,
  105. s.AgentID,
  106. s.ExecuteAt,
  107. truncate(s.Message, 50),
  108. })
  109. }
  110. table.Render()
  111. return nil
  112. },
  113. }
  114. var onetimeGetCmd = &cobra.Command{
  115. Use: "get [schedule-id]",
  116. Short: "Get details of a one-time schedule",
  117. Args: cobra.ExactArgs(1),
  118. RunE: func(cmd *cobra.Command, args []string) error {
  119. scheduleID := args[0]
  120. cfg, err := config.Load()
  121. if err != nil {
  122. return err
  123. }
  124. if err := cfg.Validate(); err != nil {
  125. return err
  126. }
  127. apiClient := client.NewClient(cfg.BaseURL, cfg.APIKey)
  128. schedule, err := apiClient.GetOneTimeSchedule(scheduleID)
  129. if err != nil {
  130. return fmt.Errorf("failed to get schedule: %w", err)
  131. }
  132. fmt.Printf("Schedule ID: %s\n", schedule.ID)
  133. fmt.Printf("Agent ID: %s\n", schedule.AgentID)
  134. fmt.Printf("Execute At: %s\n", schedule.ExecuteAt)
  135. fmt.Printf("Message: %s\n", schedule.Message)
  136. fmt.Printf("Role: %s\n", schedule.Role)
  137. fmt.Printf("Created At: %s\n", schedule.CreatedAt.Format("2006-01-02 15:04:05"))
  138. return nil
  139. },
  140. }
  141. var onetimeDeleteCmd = &cobra.Command{
  142. Use: "delete [schedule-id]",
  143. Short: "Delete a one-time schedule",
  144. Args: cobra.ExactArgs(1),
  145. RunE: func(cmd *cobra.Command, args []string) error {
  146. scheduleID := args[0]
  147. cfg, err := config.Load()
  148. if err != nil {
  149. return err
  150. }
  151. if err := cfg.Validate(); err != nil {
  152. return err
  153. }
  154. apiClient := client.NewClient(cfg.BaseURL, cfg.APIKey)
  155. if err := apiClient.DeleteOneTimeSchedule(scheduleID); err != nil {
  156. return fmt.Errorf("failed to delete schedule: %w", err)
  157. }
  158. color.Green("✓ Schedule deleted successfully")
  159. return nil
  160. },
  161. }
  162. func init() {
  163. rootCmd.AddCommand(onetimeCmd)
  164. onetimeCmd.AddCommand(onetimeCreateCmd)
  165. onetimeCreateCmd.Flags().String("agent-id", "", "Agent ID (required)")
  166. onetimeCreateCmd.Flags().String("message", "", "Message to send (required)")
  167. onetimeCreateCmd.Flags().String("role", "user", "Message role (default: user)")
  168. onetimeCreateCmd.Flags().String("execute-at", "", "When to send (optional, defaults to now)\n Examples: 'in 5 minutes', 'tomorrow at 9am', 'next monday at 3pm', '2025-11-07T10:00:00Z', or omit for immediate delivery")
  169. onetimeCmd.AddCommand(onetimeListCmd)
  170. onetimeCmd.AddCommand(onetimeGetCmd)
  171. onetimeCmd.AddCommand(onetimeDeleteCmd)
  172. }