* refactor(cli): migrate to Cobra-based command structure Refactor CLI to use Cobra instead of manual os.Args parsing. - Introduce root command and structured subcommands under cmd/picoclaw/internal - Convert agent, auth, cron, gateway, migrate, onboard, skills, status and version to Cobra commands - Replace manual flag parsing with Cobra flags - Remove direct os.Args usage from command handlers - Keep existing command behavior and output semantics This change focuses on CLI structure and maintainability. No business logic changes intended. * chore(cli): remove version2 alias and make cobra a direct dependency * test(cli): add basic command tests - Add tests for CLI command tree and flag parsing - Align LDFLAGS injection path for version info - Remove unused manual help function * test: migrate command tests to testify assertions Replace standard library testing error checks (t.Error*, t.Fatalf) with assert/require from stretchr/testify across all cobra command tests for improved readability and consistency. * fix(cli): make linter happy * test: avoid duplication in windows config path test * test: simplify allowed command checks using slices.Contains * fix(skills): register subcommands during command construction - Move subcommand registration out of PersistentPreRunE - Ensure `picoclaw skills <subcommand>` resolves correctly - Minor install command and test cleanups * refactor(cli): address review feedback and improve command clarity * fix(authLogoutCmd): rm os.Exit
64 lines
1.7 KiB
Go
64 lines
1.7 KiB
Go
package cron
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/sipeed/picoclaw/pkg/cron"
|
|
)
|
|
|
|
func newAddCommand(storePath func() string) *cobra.Command {
|
|
var (
|
|
name string
|
|
message string
|
|
every int64
|
|
cronExp string
|
|
deliver bool
|
|
channel string
|
|
to string
|
|
)
|
|
|
|
cmd := &cobra.Command{
|
|
Use: "add",
|
|
Short: "Add a new scheduled job",
|
|
Args: cobra.NoArgs,
|
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
if every <= 0 && cronExp == "" {
|
|
return fmt.Errorf("either --every or --cron must be specified")
|
|
}
|
|
|
|
var schedule cron.CronSchedule
|
|
if every > 0 {
|
|
everyMS := every * 1000
|
|
schedule = cron.CronSchedule{Kind: "every", EveryMS: &everyMS}
|
|
} else {
|
|
schedule = cron.CronSchedule{Kind: "cron", Expr: cronExp}
|
|
}
|
|
|
|
cs := cron.NewCronService(storePath(), nil)
|
|
job, err := cs.AddJob(name, schedule, message, deliver, channel, to)
|
|
if err != nil {
|
|
return fmt.Errorf("error adding job: %w", err)
|
|
}
|
|
|
|
fmt.Printf("✓ Added job '%s' (%s)\n", job.Name, job.ID)
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
cmd.Flags().StringVarP(&name, "name", "n", "", "Job name")
|
|
cmd.Flags().StringVarP(&message, "message", "m", "", "Message for agent")
|
|
cmd.Flags().Int64VarP(&every, "every", "e", 0, "Run every N seconds")
|
|
cmd.Flags().StringVarP(&cronExp, "cron", "c", "", "Cron expression (e.g. '0 9 * * *')")
|
|
cmd.Flags().BoolVarP(&deliver, "deliver", "d", false, "Deliver response to channel")
|
|
cmd.Flags().StringVar(&to, "to", "", "Recipient for delivery")
|
|
cmd.Flags().StringVar(&channel, "channel", "", "Channel for delivery")
|
|
|
|
_ = cmd.MarkFlagRequired("name")
|
|
_ = cmd.MarkFlagRequired("message")
|
|
cmd.MarkFlagsMutuallyExclusive("every", "cron")
|
|
|
|
return cmd
|
|
}
|