From 7af40d49eb1502b62786cd7aef460374cf5d1bc5 Mon Sep 17 00:00:00 2001 From: hschne Date: Sun, 24 May 2026 20:05:03 +0200 Subject: [PATCH] fix(cron): add missing 'action' arg for command job execution CronTool.ExecuteJob was calling ExecTool.Execute without setting action='run' in the args map. ExecTool.Execute requires the action field and returns ErrorResult('action is required') immediately when it's missing. This caused all cron command jobs to silently fail. Adds a test covering the command execution happy path. --- pkg/tools/cron.go | 1 + pkg/tools/cron_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/pkg/tools/cron.go b/pkg/tools/cron.go index a9547eba9..78e581e77 100644 --- a/pkg/tools/cron.go +++ b/pkg/tools/cron.go @@ -320,6 +320,7 @@ func (t *CronTool) ExecuteJob(ctx context.Context, job *cron.CronJob) string { } args := map[string]any{ + "action": "run", "command": job.Payload.Command, "__channel": channel, "__chat_id": chatID, diff --git a/pkg/tools/cron_test.go b/pkg/tools/cron_test.go index 0e527c98a..9d9d17a00 100644 --- a/pkg/tools/cron_test.go +++ b/pkg/tools/cron_test.go @@ -329,6 +329,31 @@ func TestCronTool_ExecuteJobSkipsWhenMessageToolAlreadySent(t *testing.T) { } } +func TestCronTool_ExecuteJobRunsCommand(t *testing.T) { + tool := newTestCronToolWithConfig(t, config.DefaultConfig()) + job := &cron.CronJob{} + job.Payload.Channel = "cli" + job.Payload.To = "direct" + job.Payload.Command = "echo cron-test-ok" + + if got := tool.ExecuteJob(context.Background(), job); got != "ok" { + t.Fatalf("ExecuteJob() = %q, want ok", got) + } + + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + + var msg bus.OutboundMessage + select { + case msg = <-tool.msgBus.OutboundChan(): + case <-ctx.Done(): + t.Fatal("timeout waiting for outbound message") + } + if !strings.Contains(msg.Content, "cron-test-ok") { + t.Fatalf("expected command output containing 'cron-test-ok', got: %s", msg.Content) + } +} + func TestCronTool_ExecuteJobReturnsErrorWithoutPublish(t *testing.T) { executor := &stubJobExecutor{ response: "this response must not be published",