Skip to content

Commit 8f3e229

Browse files
committed
perf(cron): use narrow bound-account lookup
1 parent aa017bf commit 8f3e229

2 files changed

Lines changed: 68 additions & 8 deletions

File tree

src/cron/isolated-agent/delivery-target.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import { resolveSessionDeliveryTarget } from "../../infra/outbound/targets-sessi
1111
import type { OutboundChannel } from "../../infra/outbound/targets.js";
1212
import { readChannelAllowFromStoreEntriesSync } from "../../pairing/allow-from-store-read.js";
1313
import { mapAllowFromEntries } from "../../plugin-sdk/channel-config-helpers.js";
14-
import { buildChannelAccountBindings } from "../../routing/bindings.js";
15-
import { normalizeAccountId, normalizeAgentId } from "../../routing/session-key.js";
14+
import { resolveFirstBoundAccountId } from "../../routing/bound-account-read.js";
15+
import { normalizeAccountId } from "../../routing/session-key.js";
1616

1717
export type DeliveryTargetResolution =
1818
| {
@@ -140,12 +140,7 @@ export async function resolveDeliveryTarget(
140140
: undefined;
141141
let accountId = explicitAccountId ?? resolved.accountId;
142142
if (!accountId && channel) {
143-
const bindings = buildChannelAccountBindings(cfg);
144-
const byAgent = bindings.get(channel);
145-
const boundAccounts = byAgent?.get(normalizeAgentId(agentId));
146-
if (boundAccounts && boundAccounts.length > 0) {
147-
accountId = boundAccounts[0];
148-
}
143+
accountId = resolveFirstBoundAccountId({ cfg, channelId: channel, agentId });
149144
}
150145

151146
// job.delivery.accountId takes highest precedence — explicitly set by the job author.

src/routing/bound-account-read.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { normalizeChatChannelId } from "../channels/ids.js";
2+
import { listRouteBindings } from "../config/bindings.js";
3+
import type { AgentRouteBinding } from "../config/types.agents.js";
4+
import type { OpenClawConfig } from "../config/types.openclaw.js";
5+
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
6+
import { normalizeAccountId, normalizeAgentId } from "./session-key.js";
7+
8+
function normalizeBindingChannelId(raw?: string | null): string | null {
9+
const normalized = normalizeChatChannelId(raw);
10+
if (normalized) {
11+
return normalized;
12+
}
13+
const fallback = normalizeLowercaseStringOrEmpty(raw);
14+
return fallback || null;
15+
}
16+
17+
function resolveNormalizedBindingMatch(binding: AgentRouteBinding): {
18+
agentId: string;
19+
accountId: string;
20+
channelId: string;
21+
} | null {
22+
if (!binding || typeof binding !== "object") {
23+
return null;
24+
}
25+
const match = binding.match;
26+
if (!match || typeof match !== "object") {
27+
return null;
28+
}
29+
const channelId = normalizeBindingChannelId(match.channel);
30+
if (!channelId) {
31+
return null;
32+
}
33+
const accountId = typeof match.accountId === "string" ? match.accountId.trim() : "";
34+
if (!accountId || accountId === "*") {
35+
return null;
36+
}
37+
return {
38+
agentId: normalizeAgentId(binding.agentId),
39+
accountId: normalizeAccountId(accountId),
40+
channelId,
41+
};
42+
}
43+
44+
export function resolveFirstBoundAccountId(params: {
45+
cfg: OpenClawConfig;
46+
channelId: string;
47+
agentId: string;
48+
}): string | undefined {
49+
const normalizedChannel = normalizeBindingChannelId(params.channelId);
50+
if (!normalizedChannel) {
51+
return undefined;
52+
}
53+
const normalizedAgentId = normalizeAgentId(params.agentId);
54+
for (const binding of listRouteBindings(params.cfg)) {
55+
const resolved = resolveNormalizedBindingMatch(binding);
56+
if (
57+
resolved &&
58+
resolved.channelId === normalizedChannel &&
59+
resolved.agentId === normalizedAgentId
60+
) {
61+
return resolved.accountId;
62+
}
63+
}
64+
return undefined;
65+
}

0 commit comments

Comments
 (0)