mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-06-12 04:12:09 +00:00
f3f4c67b36
Multi-agent AI gateway with WebSocket RPC, HTTP API, and messaging channel integrations. Go port of OpenClaw with multi-tenant PostgreSQL, per-user isolation, security hardening, and production observability. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
102 lines
3.7 KiB
Go
102 lines
3.7 KiB
Go
// Package cron provides a lightweight cron/scheduler for recurring agent tasks.
|
|
// Jobs are persisted to JSON and executed via callback to the agent runtime.
|
|
//
|
|
// Three schedule types are supported:
|
|
// - "at": one-time execution at a specific timestamp
|
|
// - "every": recurring interval (in milliseconds)
|
|
// - "cron": standard cron expression (5-field, parsed by gronx)
|
|
package cron
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"time"
|
|
)
|
|
|
|
// Schedule defines when a job should run.
|
|
type Schedule struct {
|
|
Kind string `json:"kind"` // "at", "every", or "cron"
|
|
AtMS *int64 `json:"atMs,omitempty"` // absolute timestamp (for "at")
|
|
EveryMS *int64 `json:"everyMs,omitempty"` // interval in milliseconds (for "every")
|
|
Expr string `json:"expr,omitempty"` // cron expression (for "cron")
|
|
TZ string `json:"tz,omitempty"` // timezone (reserved)
|
|
}
|
|
|
|
// Payload describes what a job does when triggered.
|
|
type Payload struct {
|
|
Kind string `json:"kind"` // "agent_turn"
|
|
Message string `json:"message"` // content to process
|
|
Command string `json:"command,omitempty"` // optional shell command
|
|
Deliver bool `json:"deliver"` // true = direct chat, false = agent processing
|
|
Channel string `json:"channel,omitempty"` // target channel (telegram, discord, etc.)
|
|
To string `json:"to,omitempty"` // target chat ID / recipient
|
|
}
|
|
|
|
// JobState tracks runtime state for a job.
|
|
type JobState struct {
|
|
NextRunAtMS *int64 `json:"nextRunAtMs,omitempty"` // next scheduled execution
|
|
LastRunAtMS *int64 `json:"lastRunAtMs,omitempty"` // last execution timestamp
|
|
LastStatus string `json:"lastStatus,omitempty"` // "ok" or "error"
|
|
LastError string `json:"lastError,omitempty"` // error message if failed
|
|
}
|
|
|
|
// Job represents a scheduled cron job.
|
|
type Job struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
AgentID string `json:"agentId,omitempty"`
|
|
Enabled bool `json:"enabled"`
|
|
Schedule Schedule `json:"schedule"`
|
|
Payload Payload `json:"payload"`
|
|
State JobState `json:"state"`
|
|
CreatedAtMS int64 `json:"createdAtMs"`
|
|
UpdatedAtMS int64 `json:"updatedAtMs"`
|
|
DeleteAfterRun bool `json:"deleteAfterRun,omitempty"`
|
|
}
|
|
|
|
// Store is the persistent store for all cron jobs.
|
|
type Store struct {
|
|
Version int `json:"version"`
|
|
Jobs []Job `json:"jobs"`
|
|
}
|
|
|
|
// JobPatch holds optional fields for updating a job.
|
|
// Only non-zero/non-nil fields are applied. Matching TS CronJobPatch.
|
|
type JobPatch struct {
|
|
Name string `json:"name,omitempty"`
|
|
AgentID *string `json:"agentId,omitempty"`
|
|
Enabled *bool `json:"enabled,omitempty"`
|
|
Schedule *Schedule `json:"schedule,omitempty"`
|
|
Message string `json:"message,omitempty"`
|
|
Deliver *bool `json:"deliver,omitempty"`
|
|
Channel *string `json:"channel,omitempty"`
|
|
To *string `json:"to,omitempty"`
|
|
DeleteAfterRun *bool `json:"deleteAfterRun,omitempty"`
|
|
}
|
|
|
|
// RunLogEntry is an in-memory record of a job execution.
|
|
// Matching TS CronRunLogEntry.
|
|
type RunLogEntry struct {
|
|
Ts int64 `json:"ts"`
|
|
JobID string `json:"jobId"`
|
|
Status string `json:"status,omitempty"` // "ok", "error"
|
|
Error string `json:"error,omitempty"`
|
|
Summary string `json:"summary,omitempty"`
|
|
}
|
|
|
|
// JobHandler is a callback invoked when a job fires.
|
|
// Returns the execution result string and any error.
|
|
type JobHandler func(job *Job) (string, error)
|
|
|
|
// generateID creates a random 8-byte hex ID for a new job.
|
|
func generateID() string {
|
|
b := make([]byte, 8)
|
|
rand.Read(b)
|
|
return hex.EncodeToString(b)
|
|
}
|
|
|
|
// nowMS returns the current time in milliseconds.
|
|
func nowMS() int64 {
|
|
return time.Now().UnixMilli()
|
|
}
|