## Rename - Module path: github.com/sipeed/picoclaw -> github.com/sipeed/piconomous - All binary names: picoclaw* -> piconomous* - Config/data paths: ~/.picoclaw -> ~/.piconomous - Env vars: PICOCLAW_* -> PICONOMOUS_* - Directory renames: cmd/picoclaw -> cmd/piconomous, cmd/picoclaw-launcher-tui -> cmd/piconomous-launcher-tui - Asset renames, desktop file, docker services ## Fully Autonomous Mode (new feature) Adds `autonomous` config section with: - `enabled`: activates goal-driven autonomous operation - `interval_minutes`: heartbeat frequency (default 5 min in autonomous mode) - `allow_self_schedule`: agent can create cron jobs for itself without command_confirm - `max_goals`: cap on concurrent active goals (default 20) ### New: Goal Management Tool (pkg/tools/goal.go) - `goal` tool with actions: set/list/complete/update/drop - Goals persist in GOALS.md (human-readable) + goals.json (machine-readable) - Priority levels P1-P5, status lifecycle: active -> completed/dropped ### Enhanced Heartbeat Service - SetAutonomous(bool) activates goal-driven prompt mode - In autonomous mode: reads GOALS.md each cycle, builds a rich prompt that instructs the agent to run the full software dev lifecycle: write code, run tests, fix failures, commit progress, schedule next steps - Creates default GOALS.md template on first run - Autonomous interval overrides heartbeat interval (5 min default vs 30 min) ### Cron Tool - In autonomous mode, agent can self-schedule on internal channels without requiring explicit command_confirm=true (GHSA-pv8c-p6jf-3fpp exception) ### Goal Tool Registration - Registered in AgentLoop.registerSharedTools when autonomous.enabled=true or when tools.goal is explicitly enabled in config https://claude.ai/code/session_0118WWK5KLRM7ZBUoC8EMgKS
64 lines
1.7 KiB
Go
64 lines
1.7 KiB
Go
package cron
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/sipeed/piconomous/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
|
|
}
|