Add task completion callback and enhance schedule command options

This commit is contained in:
Cheikh Seck committed 2026-04-19 02:03:27 +00:00
1 parent 707818daa4
commit 6bc340edd5
4 files changed
+108 -2

No files matched your search

+6 -2
View File
@@ -325,6 +325,9 @@ func main() {
if err != nil {
log.Printf("[Scheduler] Failed to initialize: %v", err)
} else {
sched.SetOnTaskFinished(func(*scheduler.ScheduledTask) {
playSound()
})
sched.SetProviderGetter(&schedulerProviderGetter{provider: provider})
var serverSlice []interface{} = make([]interface{}, len(servers))
for i, s := range servers {
@@ -1007,9 +1010,10 @@ promptLoop:
if totalToolCalls > 0 && isToolCallResponse {
prevNoTool = false
}
if !isToolCallResponse || len(toolCalls) == 0 {
if !looksLikeToolCall(resp) {
if !looksLikeToolCall(resp) && round > 0 {
go playSound()
fmt.Printf("\n\n%s\n", renderMarkdown(resp))
break
@@ -2245,7 +2249,7 @@ func runToolLoop(ctx context.Context, provider *config.Provider, servers []MCPSe
if !isToolCallResponse || len(toolCalls) == 0 {
if !hasFinal {
if !looksLikeToolCall(resp) {
if !looksLikeToolCall(resp) && round > 0 {
if nocont {
fmt.Printf("\n\n%s\n", renderMarkdown(resp))
}
+49
View File
@@ -45,7 +45,10 @@ func handleSchedule(input string) {
fmt.Println(" /schedule - List all scheduled tasks")
fmt.Println(" /schedule <id> - Show last output of a task")
fmt.Println(" /schedule stop <id> - Stop a running task by 4-char ID")
fmt.Println(" /schedule stop --all - Stop all running tasks")
fmt.Println(" /schedule remove <id> - Remove a task from the schedule by 4-char ID")
fmt.Println(" /schedule remove --all - Remove all tasks from the schedule")
fmt.Println(" /schedule clear - Stop and remove all tasks")
fmt.Println(" /schedule help - Show this help message")
fmt.Println("")
fmt.Println("LLM Tool (scheduler):")
@@ -70,7 +73,33 @@ func handleSchedule(input string) {
return
}
if len(parts) == 2 && (parts[1] == "clear" || parts[1] == "clear-all") {
tasks := sched.ListTasks()
if len(tasks) == 0 {
fmt.Println("No scheduled tasks")
return
}
sched.StopAllTasks()
removed := 0
for _, t := range tasks {
task, ok := t.(*scheduler.ScheduledTask)
if !ok || task == nil {
continue
}
if sched.RemoveTask(task.ID) {
removed++
}
}
fmt.Printf("Cleared %d task(s)\n", removed)
return
}
if len(parts) >= 3 && parts[1] == "stop" {
if parts[2] == "all" || parts[2] == "--all" || parts[2] == "*" {
sched.StopAllTasks()
fmt.Println("Stopped all running tasks")
return
}
id := strings.ToUpper(parts[2])
if len(id) != 4 {
fmt.Println("Invalid task ID. Use 4-character identifier (e.g., ABC1)")
@@ -85,6 +114,25 @@ func handleSchedule(input string) {
}
if len(parts) >= 3 && parts[1] == "remove" {
if parts[2] == "all" || parts[2] == "--all" || parts[2] == "*" {
tasks := sched.ListTasks()
if len(tasks) == 0 {
fmt.Println("No scheduled tasks")
return
}
removed := 0
for _, t := range tasks {
task, ok := t.(*scheduler.ScheduledTask)
if !ok || task == nil {
continue
}
if sched.RemoveTask(task.ID) {
removed++
}
}
fmt.Printf("Removed %d task(s)\n", removed)
return
}
id := strings.ToUpper(parts[2])
if len(id) != 4 {
fmt.Println("Invalid task ID. Use 4-character identifier (e.g., ABC1)")
@@ -123,6 +171,7 @@ func handleSchedule(input string) {
fmt.Println(" /schedule <id> - Show last output of a task")
fmt.Println(" /schedule stop <id> - Stop a task by 4-char ID")
fmt.Println(" /schedule remove <id> - Remove a task by 4-char ID")
fmt.Println(" /schedule clear - Stop and remove all tasks")
}
func listScheduledTasks() {
+12
View File
@@ -46,6 +46,7 @@ type Scheduler struct {
wg sync.WaitGroup
provider ProviderGetter
servers []ToolServer
onTaskFinished func(*ScheduledTask)
maxRounds int
toolTimeout int
wd string
@@ -251,6 +252,10 @@ func (s *Scheduler) SetServers(servers []interface{}) {
}
}
func (s *Scheduler) SetOnTaskFinished(cb func(*ScheduledTask)) {
s.onTaskFinished = cb
}
func (s *Scheduler) SetConfig(maxRounds, toolTimeout int, wd, os string) {
if maxRounds > 0 {
s.maxRounds = maxRounds
@@ -474,6 +479,13 @@ func (s *Scheduler) executeTask(task *ScheduledTask) {
task.LastRun = time.Now()
task.RunCount++
s.updateTask(task)
if s.onTaskFinished != nil {
func() {
defer func() { _ = recover() }()
s.onTaskFinished(task)
}()
}
}
func (s *Scheduler) executeWithTools(ctx context.Context, task *ScheduledTask) (string, error) {
@@ -0,0 +1,41 @@
package scheduler
import (
"sync/atomic"
"testing"
"time"
)
func TestScheduler_OnTaskFinishedCalled(t *testing.T) {
dbPath := t.TempDir() + "/scheduler.db"
s, err := New(dbPath)
if err != nil {
t.Fatalf("New: %v", err)
}
defer s.Close()
var called int32
s.SetOnTaskFinished(func(*ScheduledTask) {
atomic.AddInt32(&called, 1)
})
task := &ScheduledTask{
ID: "TEST",
Prompt: "noop",
IntervalSec: 0,
RunAt: "",
IsRepeating: false,
WorkingDir: s.wd,
CreatedAt: time.Now(),
ProviderType: "current",
ProviderName: "current",
ProviderModel: "current",
}
s.executeTask(task)
if atomic.LoadInt32(&called) != 1 {
t.Fatalf("expected callback called once, got %d", atomic.LoadInt32(&called))
}
}