scheduler

package
v1.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 20, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package scheduler implements the task scheduling system for DevClaw. Uses robfig/cron for cron expression parsing and execution, with SQLite-based persistence for surviving restarts.

Package scheduler – sqlite_storage.go implements JobStorage backed by the central devclaw.db SQLite database. It is a drop-in replacement for FileJobStorage: same interface, no changes needed in scheduler.go.

Package scheduler – storage.go provides a JSON file-based JobStorage implementation that persists scheduler jobs to disk.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AnnounceHandler

type AnnounceHandler func(channel, chatID, message string) error

AnnounceHandler is called when a job with Announce=true completes. Receives the channel, chatID, and formatted message to send.

type FileJobStorage

type FileJobStorage struct {
	// contains filtered or unexported fields
}

FileJobStorage persists jobs as a JSON file on disk.

func NewFileJobStorage

func NewFileJobStorage(path string) (*FileJobStorage, error)

NewFileJobStorage creates a file-based job storage at the given path. Creates the parent directory if it doesn't exist.

func (*FileJobStorage) Delete

func (s *FileJobStorage) Delete(id string) error

Delete removes a job from the storage file.

func (*FileJobStorage) LoadAll

func (s *FileJobStorage) LoadAll() ([]*Job, error)

LoadAll reads all persisted jobs from the storage file.

func (*FileJobStorage) Save

func (s *FileJobStorage) Save(job *Job) error

Save persists a job to the storage file.

type Job

type Job struct {
	// ID is the unique job identifier.
	ID string `json:"id" yaml:"id"`

	// Schedule is the cron expression or shorthand.
	// Supports: standard 5-field cron, @daily, @hourly, @every 5m, etc.
	Schedule string `json:"schedule" yaml:"schedule"`

	// Type is the schedule type: "cron" (recurring), "at" (one-shot), "every" (interval).
	Type string `json:"type" yaml:"type"`

	// Command is the prompt/command executed by the agent.
	Command string `json:"command" yaml:"command"`

	// Channel is the target channel (e.g., "whatsapp").
	Channel string `json:"channel" yaml:"channel"`

	// ChatID is the target chat/group.
	ChatID string `json:"chat_id" yaml:"chat_id"`

	// Enabled indicates if the job is active.
	Enabled bool `json:"enabled" yaml:"enabled"`

	// CreatedBy is the user who created the job.
	CreatedBy string `json:"created_by,omitempty" yaml:"created_by,omitempty"`

	// CreatedAt is the creation timestamp.
	CreatedAt time.Time `json:"created_at" yaml:"created_at"`

	// LastRunAt is the last execution timestamp.
	LastRunAt *time.Time `json:"last_run_at,omitempty" yaml:"last_run_at,omitempty"`

	// LastError contains the error from the last run, if any.
	LastError string `json:"last_error,omitempty" yaml:"last_error,omitempty"`

	// RunCount tracks how many times the job has executed.
	RunCount int `json:"run_count" yaml:"run_count"`

	// IsolateSession runs each job execution in its own isolated session
	// instead of sharing the channel's main session. This prevents cron
	// output from polluting the main conversation history.
	IsolateSession bool `json:"isolate_session,omitempty" yaml:"isolate_session,omitempty"`

	// Announce sends the job result to the target channel/chat after completion.
	// When false, the job runs silently (result is only logged).
	Announce bool `json:"announce,omitempty" yaml:"announce,omitempty"`

	// AsSubagent runs the job as a subagent instead of in the main agent loop.
	// This provides better isolation and prevents cron jobs from blocking
	// user-initiated agent runs.
	AsSubagent bool `json:"as_subagent,omitempty" yaml:"as_subagent,omitempty"`

	// Model overrides the LLM model for this specific job (empty = default).
	Model string `json:"model,omitempty" yaml:"model,omitempty"`

	// TimeoutSeconds overrides the global job timeout for this job.
	TimeoutSeconds int `json:"timeout_seconds,omitempty" yaml:"timeout_seconds,omitempty"`

	// Labels are arbitrary tags for filtering and organization.
	Labels []string `json:"labels,omitempty" yaml:"labels,omitempty"`

	// StaggerMs is a deterministic delay (in ms) applied before execution to
	// prevent thundering herd when multiple jobs share the same schedule.
	// Computed from job ID hash if zero and the schedule is top-of-hour.
	StaggerMs int `json:"stagger_ms,omitempty" yaml:"stagger_ms,omitempty"`

	// Exact disables stagger for this job (fire at exact schedule time).
	Exact bool `json:"exact,omitempty" yaml:"exact,omitempty"`

	// LastRunDuration is how long the last execution took.
	LastRunDuration time.Duration `json:"last_run_duration,omitempty" yaml:"last_run_duration,omitempty"`

	// LastUsage holds token usage from the last execution.
	LastUsage *JobUsage `json:"last_usage,omitempty" yaml:"last_usage,omitempty"`
}

Job represents a scheduled task.

func (*Job) ToJSON

func (j *Job) ToJSON() string

ToJSON serializes a job to JSON (for tool output).

type JobHandler

type JobHandler func(ctx context.Context, job *Job) (string, error)

JobHandler is called when a job fires. Returns the agent response or error. For backward compatibility, the handler may return just a string via the legacy signature, or a JobResult with usage telemetry.

type JobResult

type JobResult struct {
	Output string
	Usage  *JobUsage
}

JobResult holds the outcome of a job execution, including usage telemetry.

type JobStorage

type JobStorage interface {
	Save(job *Job) error
	Delete(id string) error
	LoadAll() ([]*Job, error)
}

JobStorage defines the persistence interface for jobs.

type JobUsage

type JobUsage struct {
	InputTokens      int `json:"input_tokens"`
	OutputTokens     int `json:"output_tokens"`
	TotalTokens      int `json:"total_tokens"`
	CacheReadTokens  int `json:"cache_read_tokens,omitempty"`
	CacheWriteTokens int `json:"cache_write_tokens,omitempty"`
}

JobUsage tracks token usage from the LLM during a cron job execution.

type SQLiteJobStorage

type SQLiteJobStorage struct {
	// contains filtered or unexported fields
}

SQLiteJobStorage persists jobs in the central devclaw.db "jobs" table.

func NewSQLiteJobStorage

func NewSQLiteJobStorage(db *sql.DB) *SQLiteJobStorage

NewSQLiteJobStorage creates a SQLite-backed job storage using the shared DB. The "jobs" table must already exist (created by copilot.OpenDatabase).

func (*SQLiteJobStorage) Delete

func (s *SQLiteJobStorage) Delete(id string) error

Delete removes a job by ID.

func (*SQLiteJobStorage) LoadAll

func (s *SQLiteJobStorage) LoadAll() ([]*Job, error)

LoadAll reads all persisted jobs.

func (*SQLiteJobStorage) Save

func (s *SQLiteJobStorage) Save(job *Job) error

Save persists a job (insert or update).

type Scheduler

type Scheduler struct {
	// contains filtered or unexported fields
}

Scheduler manages scheduled tasks using cron expressions.

func New

func New(storage JobStorage, handler JobHandler, logger *slog.Logger) *Scheduler

New creates a new Scheduler with the given storage and handler.

func (*Scheduler) Add

func (s *Scheduler) Add(job *Job) error

Add registers a new job in the scheduler.

func (*Scheduler) Get

func (s *Scheduler) Get(jobID string) (*Job, bool)

Get returns a job by ID.

func (*Scheduler) List

func (s *Scheduler) List() []*Job

List returns all registered jobs.

func (*Scheduler) Remove

func (s *Scheduler) Remove(jobID string) error

Remove deletes a job by ID.

func (*Scheduler) SetAnnounceHandler

func (s *Scheduler) SetAnnounceHandler(h AnnounceHandler)

SetAnnounceHandler registers a callback for announce-enabled jobs.

func (*Scheduler) Start

func (s *Scheduler) Start(ctx context.Context) error

Start initializes the cron scheduler and loads persisted jobs.

func (*Scheduler) Stop

func (s *Scheduler) Stop()

Stop gracefully shuts down the scheduler.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL