mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 20:28:29 +00:00
feat(heartbeat): add accountId config option for multi-agent routing (#8702)
* feat(heartbeat): add accountId config option for multi-agent routing Add optional accountId field to heartbeat configuration, allowing multi-agent setups to explicitly specify which Telegram account should be used for heartbeat delivery. Previously, heartbeat delivery would use the accountId from the session's deliveryContext. When a session had no prior conversation history, heartbeats would default to the first/primary account instead of the agent's intended bot. Changes: - Add accountId to HeartbeatSchema (zod-schema.agent-runtime.ts) - Use heartbeat.accountId with fallback to session accountId (targets.ts) Backward compatible: if accountId is not specified, behavior is unchanged. Closes #8695 * fix: improve heartbeat accountId routing (#8702) (thanks @lsh411) * fix: harden heartbeat accountId routing (#8702) (thanks @lsh411) * fix: expose heartbeat accountId in status (#8702) (thanks @lsh411) * chore: format status + heartbeat tests (#8702) (thanks @lsh411) --------- Co-authored-by: m1 16 512 <m116512@m1ui-MacBookAir-2.local> Co-authored-by: Gustavo Madeira Santana <gumadeiras@gmail.com>
This commit is contained in:
@@ -534,6 +534,19 @@ export async function runHeartbeatOnce(opts: {
|
||||
const { entry, sessionKey, storePath } = resolveHeartbeatSession(cfg, agentId, heartbeat);
|
||||
const previousUpdatedAt = entry?.updatedAt;
|
||||
const delivery = resolveHeartbeatDeliveryTarget({ cfg, entry, heartbeat });
|
||||
const heartbeatAccountId = heartbeat?.accountId?.trim();
|
||||
if (delivery.reason === "unknown-account") {
|
||||
log.warn("heartbeat: unknown accountId", {
|
||||
accountId: delivery.accountId ?? heartbeatAccountId ?? null,
|
||||
target: heartbeat?.target ?? "last",
|
||||
});
|
||||
} else if (heartbeatAccountId) {
|
||||
log.info("heartbeat: using explicit accountId", {
|
||||
accountId: delivery.accountId ?? heartbeatAccountId,
|
||||
target: heartbeat?.target ?? "last",
|
||||
channel: delivery.channel,
|
||||
});
|
||||
}
|
||||
const visibility =
|
||||
delivery.channel !== "none"
|
||||
? resolveHeartbeatVisibility({
|
||||
@@ -569,6 +582,7 @@ export async function runHeartbeatOnce(opts: {
|
||||
reason: "alerts-disabled",
|
||||
durationMs: Date.now() - startedAt,
|
||||
channel: delivery.channel !== "none" ? delivery.channel : undefined,
|
||||
accountId: delivery.accountId,
|
||||
});
|
||||
return { status: "skipped", reason: "alerts-disabled" };
|
||||
}
|
||||
@@ -626,6 +640,7 @@ export async function runHeartbeatOnce(opts: {
|
||||
reason: opts.reason,
|
||||
durationMs: Date.now() - startedAt,
|
||||
channel: delivery.channel !== "none" ? delivery.channel : undefined,
|
||||
accountId: delivery.accountId,
|
||||
silent: !okSent,
|
||||
indicatorType: visibility.useIndicator ? resolveIndicatorType("ok-empty") : undefined,
|
||||
});
|
||||
@@ -659,6 +674,7 @@ export async function runHeartbeatOnce(opts: {
|
||||
reason: opts.reason,
|
||||
durationMs: Date.now() - startedAt,
|
||||
channel: delivery.channel !== "none" ? delivery.channel : undefined,
|
||||
accountId: delivery.accountId,
|
||||
silent: !okSent,
|
||||
indicatorType: visibility.useIndicator ? resolveIndicatorType("ok-token") : undefined,
|
||||
});
|
||||
@@ -695,6 +711,7 @@ export async function runHeartbeatOnce(opts: {
|
||||
durationMs: Date.now() - startedAt,
|
||||
hasMedia: false,
|
||||
channel: delivery.channel !== "none" ? delivery.channel : undefined,
|
||||
accountId: delivery.accountId,
|
||||
});
|
||||
return { status: "ran", durationMs: Date.now() - startedAt };
|
||||
}
|
||||
@@ -714,6 +731,7 @@ export async function runHeartbeatOnce(opts: {
|
||||
preview: previewText?.slice(0, 200),
|
||||
durationMs: Date.now() - startedAt,
|
||||
hasMedia: mediaUrls.length > 0,
|
||||
accountId: delivery.accountId,
|
||||
});
|
||||
return { status: "ran", durationMs: Date.now() - startedAt };
|
||||
}
|
||||
@@ -731,6 +749,7 @@ export async function runHeartbeatOnce(opts: {
|
||||
durationMs: Date.now() - startedAt,
|
||||
channel: delivery.channel,
|
||||
hasMedia: mediaUrls.length > 0,
|
||||
accountId: delivery.accountId,
|
||||
indicatorType: visibility.useIndicator ? resolveIndicatorType("sent") : undefined,
|
||||
});
|
||||
return { status: "ran", durationMs: Date.now() - startedAt };
|
||||
@@ -752,6 +771,7 @@ export async function runHeartbeatOnce(opts: {
|
||||
durationMs: Date.now() - startedAt,
|
||||
hasMedia: mediaUrls.length > 0,
|
||||
channel: delivery.channel,
|
||||
accountId: delivery.accountId,
|
||||
});
|
||||
log.info("heartbeat: channel not ready", {
|
||||
channel: delivery.channel,
|
||||
@@ -801,6 +821,7 @@ export async function runHeartbeatOnce(opts: {
|
||||
durationMs: Date.now() - startedAt,
|
||||
hasMedia: mediaUrls.length > 0,
|
||||
channel: delivery.channel,
|
||||
accountId: delivery.accountId,
|
||||
indicatorType: visibility.useIndicator ? resolveIndicatorType("sent") : undefined,
|
||||
});
|
||||
return { status: "ran", durationMs: Date.now() - startedAt };
|
||||
@@ -811,6 +832,7 @@ export async function runHeartbeatOnce(opts: {
|
||||
reason,
|
||||
durationMs: Date.now() - startedAt,
|
||||
channel: delivery.channel !== "none" ? delivery.channel : undefined,
|
||||
accountId: delivery.accountId,
|
||||
indicatorType: visibility.useIndicator ? resolveIndicatorType("failed") : undefined,
|
||||
});
|
||||
log.error(`heartbeat failed: ${reason}`, { error: reason });
|
||||
|
||||
Reference in New Issue
Block a user