refine openclaw-style background triggers and status visibility

This commit is contained in:
DBT
2026-02-23 12:24:00 +00:00
parent 3049b84244
commit 6410933877
2 changed files with 65 additions and 20 deletions

View File

@@ -61,11 +61,26 @@ func gatewayCmd() {
msgBus := bus.NewMessageBus() msgBus := bus.NewMessageBus()
cronStorePath := filepath.Join(filepath.Dir(getConfigPath()), "cron", "jobs.json") cronStorePath := filepath.Join(filepath.Dir(getConfigPath()), "cron", "jobs.json")
cronService := cron.NewCronService(cronStorePath, func(job *cron.CronJob) (string, error) { cronService := cron.NewCronService(cronStorePath, func(job *cron.CronJob) (string, error) {
if job == nil || strings.TrimSpace(job.Payload.Message) == "" { if job == nil {
return "", nil return "", nil
} }
targetChannel := strings.TrimSpace(job.Payload.Channel) targetChannel := strings.TrimSpace(job.Payload.Channel)
targetChatID := strings.TrimSpace(job.Payload.To) targetChatID := strings.TrimSpace(job.Payload.To)
message := strings.TrimSpace(job.Payload.Message)
if job.Payload.Deliver && targetChannel != "" && targetChatID != "" && message != "" {
msgBus.PublishOutbound(bus.OutboundMessage{
Channel: targetChannel,
ChatID: targetChatID,
Content: message,
})
return "delivered", nil
}
if message == "" {
return "", nil
}
if targetChannel == "" || targetChatID == "" { if targetChannel == "" || targetChatID == "" {
targetChannel = "internal" targetChannel = "internal"
targetChatID = "cron" targetChatID = "cron"
@@ -74,7 +89,7 @@ func gatewayCmd() {
Channel: "system", Channel: "system",
SenderID: "cron", SenderID: "cron",
ChatID: fmt.Sprintf("%s:%s", targetChannel, targetChatID), ChatID: fmt.Sprintf("%s:%s", targetChannel, targetChatID),
Content: job.Payload.Message, Content: message,
SessionKey: fmt.Sprintf("cron:%s", job.ID), SessionKey: fmt.Sprintf("cron:%s", job.ID),
Metadata: map[string]string{ Metadata: map[string]string{
"trigger": "cron", "trigger": "cron",
@@ -84,23 +99,7 @@ func gatewayCmd() {
return "scheduled", nil return "scheduled", nil
}) })
configureCronServiceRuntime(cronService, cfg) configureCronServiceRuntime(cronService, cfg)
hbInterval := cfg.Agents.Defaults.Heartbeat.EverySec heartbeatService := buildHeartbeatService(cfg, msgBus)
if hbInterval <= 0 {
hbInterval = 30 * 60
}
heartbeatService := heartbeat.NewHeartbeatService(cfg.WorkspacePath(), func(prompt string) (string, error) {
msgBus.PublishInbound(bus.InboundMessage{
Channel: "system",
SenderID: "heartbeat",
ChatID: "internal:heartbeat",
Content: prompt,
SessionKey: "heartbeat:default",
Metadata: map[string]string{
"trigger": "heartbeat",
},
})
return "queued", nil
}, hbInterval, cfg.Agents.Defaults.Heartbeat.Enabled)
sentinelService := sentinel.NewService( sentinelService := sentinel.NewService(
getConfigPath(), getConfigPath(),
cfg.WorkspacePath(), cfg.WorkspacePath(),
@@ -181,6 +180,11 @@ func gatewayCmd() {
applyMaximumPermissionPolicy(newCfg) applyMaximumPermissionPolicy(newCfg)
} }
configureCronServiceRuntime(cronService, newCfg) configureCronServiceRuntime(cronService, newCfg)
heartbeatService.Stop()
heartbeatService = buildHeartbeatService(newCfg, msgBus)
if err := heartbeatService.Start(); err != nil {
fmt.Printf("Error starting heartbeat service: %v\n", err)
}
if reflect.DeepEqual(cfg, newCfg) { if reflect.DeepEqual(cfg, newCfg) {
fmt.Println("✓ Config unchanged, skip reload") fmt.Println("✓ Config unchanged, skip reload")
@@ -565,3 +569,23 @@ func configureCronServiceRuntime(cs *cron.CronService, cfg *config.Config) {
MaxWorkers: cfg.Cron.MaxWorkers, MaxWorkers: cfg.Cron.MaxWorkers,
}) })
} }
func buildHeartbeatService(cfg *config.Config, msgBus *bus.MessageBus) *heartbeat.HeartbeatService {
hbInterval := cfg.Agents.Defaults.Heartbeat.EverySec
if hbInterval <= 0 {
hbInterval = 30 * 60
}
return heartbeat.NewHeartbeatService(cfg.WorkspacePath(), func(prompt string) (string, error) {
msgBus.PublishInbound(bus.InboundMessage{
Channel: "system",
SenderID: "heartbeat",
ChatID: "internal:heartbeat",
Content: prompt,
SessionKey: "heartbeat:default",
Metadata: map[string]string{
"trigger": "heartbeat",
},
})
return "queued", nil
}, hbInterval, cfg.Agents.Defaults.Heartbeat.Enabled)
}

View File

@@ -3,11 +3,11 @@ package main
import ( import (
"fmt" "fmt"
"os" "os"
"path/filepath"
"strings" "strings"
"clawgo/pkg/providers" "clawgo/pkg/providers"
) )
func statusCmd() { func statusCmd() {
cfg, err := loadConfig() cfg, err := loadConfig()
if err != nil { if err != nil {
@@ -64,5 +64,26 @@ func statusCmd() {
fmt.Printf("Log Max Size: %d MB\n", cfg.Logging.MaxSizeMB) fmt.Printf("Log Max Size: %d MB\n", cfg.Logging.MaxSizeMB)
fmt.Printf("Log Retention: %d days\n", cfg.Logging.RetentionDays) fmt.Printf("Log Retention: %d days\n", cfg.Logging.RetentionDays)
} }
fmt.Printf("Heartbeat: enabled=%v interval=%ds ackMaxChars=%d\n",
cfg.Agents.Defaults.Heartbeat.Enabled,
cfg.Agents.Defaults.Heartbeat.EverySec,
cfg.Agents.Defaults.Heartbeat.AckMaxChars,
)
fmt.Printf("Cron Runtime: workers=%d sleep=%d-%ds\n",
cfg.Cron.MaxWorkers,
cfg.Cron.MinSleepSec,
cfg.Cron.MaxSleepSec,
)
heartbeatLog := filepath.Join(workspace, "memory", "heartbeat.log")
if data, err := os.ReadFile(heartbeatLog); err == nil {
trimmed := strings.TrimSpace(string(data))
if trimmed != "" {
lines := strings.Split(trimmed, "\n")
fmt.Printf("Heartbeat Runs Logged: %d\n", len(lines))
fmt.Printf("Heartbeat Last Log: %s\n", lines[len(lines)-1])
}
}
} }
} }