diff --git a/cmd/claw-api/scheduler.go b/cmd/claw-api/scheduler.go index 553ed12..1298bae 100644 --- a/cmd/claw-api/scheduler.go +++ b/cmd/claw-api/scheduler.go @@ -72,6 +72,7 @@ type dispatchOptions struct { const defaultWakeExecTimeout = 30 * time.Second const openclawWakeExecTimeout = schedulepkg.MaxWakeExecTimeout +const hermesWakeExecTimeout = schedulepkg.MaxWakeExecTimeout var errScheduleInvocationInFlight = errors.New("schedule invocation already in flight") @@ -610,6 +611,8 @@ func wakeExecTimeout(adapter string) time.Duration { switch strings.TrimSpace(adapter) { case "openclaw-exec": return openclawWakeExecTimeout + case "hermes-exec": + return hermesWakeExecTimeout default: return defaultWakeExecTimeout } diff --git a/cmd/claw-api/scheduler_test.go b/cmd/claw-api/scheduler_test.go index e795877..9236326 100644 --- a/cmd/claw-api/scheduler_test.go +++ b/cmd/claw-api/scheduler_test.go @@ -39,11 +39,14 @@ func TestShouldAttemptDegradedThrottlesToRoughlyTenPercent(t *testing.T) { } } -func TestWakeExecTimeoutUsesOpenClawBudget(t *testing.T) { +func TestWakeExecTimeoutUsesRunnerSpecificBudgets(t *testing.T) { if got := wakeExecTimeout("openclaw-exec"); got != openclawWakeExecTimeout { t.Fatalf("expected openclaw wake timeout %v, got %v", openclawWakeExecTimeout, got) } - if got := wakeExecTimeout("hermes-exec"); got != defaultWakeExecTimeout { + if got := wakeExecTimeout("hermes-exec"); got != hermesWakeExecTimeout { + t.Fatalf("expected hermes wake timeout %v, got %v", hermesWakeExecTimeout, got) + } + if got := wakeExecTimeout("nanobot-exec"); got != defaultWakeExecTimeout { t.Fatalf("expected default wake timeout %v, got %v", defaultWakeExecTimeout, got) } } diff --git a/site/changelog.md b/site/changelog.md index 5df2d78..4573ffd 100644 --- a/site/changelog.md +++ b/site/changelog.md @@ -31,6 +31,7 @@ outline: deep - **Slow scheduled wakes no longer block unrelated targets** -- claw-api dispatches due targets concurrently while serializing wakes per runner, coalesces overlapping slots without regressing next-fire state, rejects duplicate manual fires with a conflict, and drains active scheduler dispatches cleanly on shutdown. Coalesced slots are now recorded in schedule state (`suppressed_slots`, `last_suppressed_at`) and surfaced on the clawdash schedule card, so a schedule whose wake outruns its own cadence no longer reads as perfectly healthy. Closes [#347](https://github.com/mostlydev/clawdapus/issues/347). - **Manual schedule fires honor runner wake budgets** -- `claw api schedule fire` now gives the in-container request 2 minutes 5 seconds and its outer compose transport 2 minutes 10 seconds, enough to return the final result of the longest supported runner wake. Other schedule operations retain their short defaults, and an explicit `--exec-timeout` still overrides the outer transport. Closes [#348](https://github.com/mostlydev/clawdapus/issues/348). +- **Hermes scheduled wakes get a runner-sized timeout** -- claw-api now gives `hermes-exec` the same two-minute wake budget as other runner-native cron paths, preventing a successfully triggered Hermes job from being recorded as `exec timed out` solely because the runner took longer than the generic 30-second transport budget. Closes [#345](https://github.com/mostlydev/clawdapus/issues/345). ## v0.27.0 {#v0-27-0}