From 300d2c9339fcbca070ebc4538c0e878354b161a1 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 24 Jan 2026 13:11:52 +0000 Subject: [PATCH] fix: normalize agentId casing in cron/routing (#1591) (thanks @EnzeD) --- CHANGELOG.md | 2 ++ src/cli/cron-cli/register.cron-add.ts | 5 ++++- src/cli/cron-cli/register.cron-edit.ts | 3 ++- src/cron/normalize.ts | 3 ++- src/discord/monitor/provider.ts | 8 +++++++- src/routing/resolve-route.ts | 4 ++-- 6 files changed, 19 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e237baed0..f6ce70bc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Docs: https://docs.clawd.bot - Browser: add node-host proxy auto-routing for remote gateways (configurable per gateway/node). - Heartbeat: add per-channel visibility controls (OK/alerts/indicator). (#1452) Thanks @dlauer. - Plugins: add optional llm-task JSON-only tool for workflows. (#1498) Thanks @vignesh07. +- Docs: add emoji reaction guidance to AGENTS.md template. (#1591) Thanks @EnzeD. - CLI: restart the gateway by default after `clawdbot update`; add `--no-restart` to skip it. - CLI: add live auth probes to `clawdbot models status` for per-profile verification. - CLI: add `clawdbot system` for system events + heartbeat controls; remove standalone `wake`. @@ -27,6 +28,7 @@ Docs: https://docs.clawd.bot ### Fixes - Sessions: accept non-UUID sessionIds for history/send/status while preserving agent scoping. (#1518) +- Routing/Cron: normalize agentId casing for bindings and cron payloads. (#1591) - Gateway: compare Linux process start time to avoid PID recycling lock loops; keep locks unless stale. (#1572) Thanks @steipete. - Messaging: mirror outbound sends into target session keys (threads + dmScope) and create session entries on send. (#1520) - Sessions: normalize session key casing to lowercase for consistent routing. diff --git a/src/cli/cron-cli/register.cron-add.ts b/src/cli/cron-cli/register.cron-add.ts index 2fda55e98..ce7b9fa0f 100644 --- a/src/cli/cron-cli/register.cron-add.ts +++ b/src/cli/cron-cli/register.cron-add.ts @@ -2,6 +2,7 @@ import type { Command } from "commander"; import type { CronJob } from "../../cron/types.js"; import { danger } from "../../globals.js"; import { defaultRuntime } from "../../runtime.js"; +import { normalizeAgentId } from "../../routing/session-key.js"; import type { GatewayRpcOpts } from "../gateway-rpc.js"; import { addGatewayClientOptions, callGatewayFromCli } from "../gateway-rpc.js"; import { parsePositiveIntOrUndefined } from "../program/helpers.js"; @@ -138,7 +139,9 @@ export function registerCronAddCommand(cron: Command) { } const agentId = - typeof opts.agent === "string" && opts.agent.trim() ? opts.agent.trim() : undefined; + typeof opts.agent === "string" && opts.agent.trim() + ? normalizeAgentId(opts.agent) + : undefined; const payload = (() => { const systemEvent = typeof opts.systemEvent === "string" ? opts.systemEvent.trim() : ""; diff --git a/src/cli/cron-cli/register.cron-edit.ts b/src/cli/cron-cli/register.cron-edit.ts index 45eda04da..9921678ff 100644 --- a/src/cli/cron-cli/register.cron-edit.ts +++ b/src/cli/cron-cli/register.cron-edit.ts @@ -1,6 +1,7 @@ import type { Command } from "commander"; import { danger } from "../../globals.js"; import { defaultRuntime } from "../../runtime.js"; +import { normalizeAgentId } from "../../routing/session-key.js"; import { addGatewayClientOptions, callGatewayFromCli } from "../gateway-rpc.js"; import { getCronChannelOptions, @@ -90,7 +91,7 @@ export function registerCronEditCommand(cron: Command) { throw new Error("Use --agent or --clear-agent, not both"); } if (typeof opts.agent === "string" && opts.agent.trim()) { - patch.agentId = opts.agent.trim(); + patch.agentId = normalizeAgentId(opts.agent); } if (opts.clearAgent) { patch.agentId = null; diff --git a/src/cron/normalize.ts b/src/cron/normalize.ts index 3e5515ffe..44c277e9b 100644 --- a/src/cron/normalize.ts +++ b/src/cron/normalize.ts @@ -1,6 +1,7 @@ import { parseAbsoluteTimeMs } from "./parse.js"; import { migrateLegacyCronPayload } from "./payload-migration.js"; import type { CronJobCreate, CronJobPatch } from "./types.js"; +import { normalizeAgentId } from "../routing/session-key.js"; type UnknownRecord = Record; @@ -75,7 +76,7 @@ export function normalizeCronJobInput( next.agentId = null; } else if (typeof agentId === "string") { const trimmed = agentId.trim(); - if (trimmed) next.agentId = trimmed; + if (trimmed) next.agentId = normalizeAgentId(trimmed); else delete next.agentId; } } diff --git a/src/discord/monitor/provider.ts b/src/discord/monitor/provider.ts index d55e06c4c..3efc47e83 100644 --- a/src/discord/monitor/provider.ts +++ b/src/discord/monitor/provider.ts @@ -95,7 +95,13 @@ function formatDiscordDeployErrorDetails(err: unknown): string { try { bodyText = JSON.stringify(rawBody); } catch { - bodyText = String(rawBody); + if (typeof rawBody === "string") { + bodyText = rawBody; + } else if (rawBody instanceof Error) { + bodyText = rawBody.message; + } else { + bodyText = "[unserializable]"; + } } if (bodyText) { const maxLen = 800; diff --git a/src/routing/resolve-route.ts b/src/routing/resolve-route.ts index 744cac1af..3c71dd84c 100644 --- a/src/routing/resolve-route.ts +++ b/src/routing/resolve-route.ts @@ -96,9 +96,9 @@ function pickFirstExistingAgentId(cfg: ClawdbotConfig, agentId: string): string if (!trimmed) return normalizeAgentId(resolveDefaultAgentId(cfg)); const normalized = normalizeAgentId(trimmed); const agents = listAgents(cfg); - if (agents.length === 0) return trimmed; + if (agents.length === 0) return normalized; const match = agents.find((agent) => normalizeAgentId(agent.id) === normalized); - if (match?.id?.trim()) return match.id.trim(); + if (match?.id?.trim()) return normalizeAgentId(match.id); return normalizeAgentId(resolveDefaultAgentId(cfg)); }