From 82e86bcce17403503f84912fb7057e740e73d331 Mon Sep 17 00:00:00 2001 From: Thieu Nguyen <79964592+thieung@users.noreply.github.com> Date: Mon, 30 Mar 2026 11:45:54 +0700 Subject: [PATCH] fix(cron): resolve default agent from DB and fix update payload (#549) (#562) - Backend: resolve real default agent UUID from DB when cron job has no agent_id, instead of using literal "default" string that fails lookup - UI: replace free-text agent input with dropdown in create form - UI: wrap update params in `patch` object matching backend expectation - UI: send empty string for agentId to explicitly clear agent selection - UI: add name attribute to Select elements to fix form field warning --- cmd/gateway_cron.go | 10 +++++++++- .../cron/cron-detail/cron-overview-tab.tsx | 4 ++-- ui/web/src/pages/cron/cron-form-dialog.tsx | 17 ++++++++++++++++- ui/web/src/pages/cron/hooks/use-cron.ts | 2 +- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/cmd/gateway_cron.go b/cmd/gateway_cron.go index 8bb4d920..3e60482a 100644 --- a/cmd/gateway_cron.go +++ b/cmd/gateway_cron.go @@ -27,7 +27,15 @@ var cronHeartbeatWakeFn func(agentID string) func makeCronJobHandler(sched *scheduler.Scheduler, msgBus *bus.MessageBus, cfg *config.Config, channelMgr *channels.Manager, sessionMgr store.SessionStore, agentStore store.AgentStore) func(job *store.CronJob) (*store.CronJobResult, error) { return func(job *store.CronJob) (*store.CronJobResult, error) { agentID := job.AgentID - if agentID == "" { + if agentID == "" && agentStore != nil { + // Resolve real default agent from DB instead of using literal "default" string. + tenantCtx := store.WithTenantID(context.Background(), job.TenantID) + if defaultAgent, err := agentStore.GetDefault(tenantCtx); err == nil { + agentID = defaultAgent.AgentKey + } else { + agentID = cfg.ResolveDefaultAgentID() + } + } else if agentID == "" { agentID = cfg.ResolveDefaultAgentID() } else if id, err := uuid.Parse(agentID); err == nil && agentStore != nil { // Resolve agentKey from UUID so session key uses agentKey diff --git a/ui/web/src/pages/cron/cron-detail/cron-overview-tab.tsx b/ui/web/src/pages/cron/cron-detail/cron-overview-tab.tsx index 7d8b214a..df461ddd 100644 --- a/ui/web/src/pages/cron/cron-detail/cron-overview-tab.tsx +++ b/ui/web/src/pages/cron/cron-detail/cron-overview-tab.tsx @@ -57,7 +57,7 @@ export function CronOverviewTab({ job, onUpdate }: CronOverviewTabProps) { await onUpdate(job.id, { schedule, message: message.trim(), - agentId: agentId.trim() || undefined, + agentId: agentId.trim() || "", enabled, }); setEditingMessage(false); @@ -176,7 +176,7 @@ export function CronOverviewTab({ job, onUpdate }: CronOverviewTabProps) {
- setAgentId(v === "__default__" ? "" : v)} disabled={readonly}> diff --git a/ui/web/src/pages/cron/cron-form-dialog.tsx b/ui/web/src/pages/cron/cron-form-dialog.tsx index 056a201e..47a9710a 100644 --- a/ui/web/src/pages/cron/cron-form-dialog.tsx +++ b/ui/web/src/pages/cron/cron-form-dialog.tsx @@ -11,8 +11,10 @@ import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import type { CronSchedule } from "./hooks/use-cron"; import { slugify, isValidSlug } from "@/lib/slug"; +import { useAgents } from "@/pages/agents/hooks/use-agents"; interface CronFormDialogProps { open: boolean; @@ -29,6 +31,7 @@ type ScheduleKind = "every" | "cron" | "at"; export function CronFormDialog({ open, onOpenChange, onSubmit }: CronFormDialogProps) { const { t } = useTranslation("cron"); + const { agents } = useAgents(); const [name, setName] = useState(""); const [message, setMessage] = useState(""); const [agentId, setAgentId] = useState(""); @@ -81,7 +84,19 @@ export function CronFormDialog({ open, onOpenChange, onSubmit }: CronFormDialogP
- setAgentId(e.target.value)} placeholder={t("create.agentIdPlaceholder")} /> +
diff --git a/ui/web/src/pages/cron/hooks/use-cron.ts b/ui/web/src/pages/cron/hooks/use-cron.ts index 46e0fef4..2c97671f 100644 --- a/ui/web/src/pages/cron/hooks/use-cron.ts +++ b/ui/web/src/pages/cron/hooks/use-cron.ts @@ -152,7 +152,7 @@ export function useCron() { const updateJob = useCallback( async (jobId: string, params: Record) => { try { - await ws.call(Methods.CRON_UPDATE, { jobId, ...params }); + await ws.call(Methods.CRON_UPDATE, { jobId, patch: params }); await invalidate(); toast.success(i18next.t("cron:toast.updated")); } catch (err) {