mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-07 05:00:44 +00:00
agents: clarify spawn peer alias lookup
This commit is contained in:
@@ -3,7 +3,10 @@ import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { resolveRequesterOriginForChild } from "./spawn-requester-origin.js";
|
||||
|
||||
describe("resolveRequesterOriginForChild", () => {
|
||||
it("keeps canonical prefixed peer ids eligible for exact binding lookup", () => {
|
||||
it.each([
|
||||
["channel:conversation-a", "channel:conversation-a"],
|
||||
["thread:conversation-a/thread-a", "thread:conversation-a/thread-a"],
|
||||
])("keeps canonical prefixed peer id %s eligible for exact binding lookup", (to, peerId) => {
|
||||
const cfg = {
|
||||
bindings: [
|
||||
{
|
||||
@@ -13,7 +16,7 @@ describe("resolveRequesterOriginForChild", () => {
|
||||
channel: "qa-channel",
|
||||
peer: {
|
||||
kind: "channel",
|
||||
id: "channel:conversation-a",
|
||||
id: peerId,
|
||||
},
|
||||
accountId: "bot-alpha-qa",
|
||||
},
|
||||
@@ -28,12 +31,12 @@ describe("resolveRequesterOriginForChild", () => {
|
||||
requesterAgentId: "main",
|
||||
requesterChannel: "qa-channel",
|
||||
requesterAccountId: "bot-beta",
|
||||
requesterTo: "channel:conversation-a",
|
||||
requesterTo: to,
|
||||
}),
|
||||
).toMatchObject({
|
||||
channel: "qa-channel",
|
||||
accountId: "bot-alpha-qa",
|
||||
to: "channel:conversation-a",
|
||||
to,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,10 +4,11 @@ import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { resolveFirstBoundAccountId } from "../routing/bound-account-read.js";
|
||||
import { normalizeDeliveryContext } from "../utils/delivery-context.js";
|
||||
|
||||
// Delivery targets carry a channel-side prefix (e.g. Matrix uses
|
||||
// `room:<roomId>`; LINE uses `line:group:<id>`), but route bindings store raw
|
||||
// peer ids on `match.peer.id`. Peel namespace and kind prefixes so the raw peer
|
||||
// id surfaces for binding lookup.
|
||||
// Delivery targets often carry a transport wrapper (e.g. Matrix `room:<id>` or
|
||||
// LINE `line:group:<id>`), while route bindings commonly store raw peer ids on
|
||||
// `match.peer.id`. Peel wrappers for those lookups, and separately pass the
|
||||
// original target as an exact-match alias for channels whose canonical peer ids
|
||||
// intentionally include prefixes such as `channel:` or `thread:`.
|
||||
const KIND_PREFIX_TO_CHAT_TYPE: Readonly<Record<string, ChatType>> = {
|
||||
"room:": "channel",
|
||||
"channel:": "channel",
|
||||
@@ -22,10 +23,7 @@ const KIND_PREFIX_TO_CHAT_TYPE: Readonly<Record<string, ChatType>> = {
|
||||
"pm:": "direct",
|
||||
};
|
||||
|
||||
// Matches any `<alpha-token>:` prefix. Real-world peer ids (Matrix `!`/`@`,
|
||||
// IRC `#`, Slack/Discord/LINE alphanumerics, numeric Telegram/WhatsApp, or
|
||||
// email-style `user@server`) never start with a lowercase-alpha token followed
|
||||
// by `:`, so this peels prefixes without risking the raw id itself.
|
||||
// Matches one leading `<alpha-token>:` wrapper at a time.
|
||||
const GENERIC_PREFIX_PATTERN = /^[a-z][a-z0-9_-]*:/i;
|
||||
|
||||
export function extractRequesterPeer(
|
||||
@@ -92,7 +90,7 @@ export function resolveRequesterOriginForChild(params: {
|
||||
channelId: params.requesterChannel,
|
||||
agentId: params.targetAgentId,
|
||||
peerId: normalizedPeerId,
|
||||
peerIdAliases:
|
||||
exactPeerIdAliases:
|
||||
rawPeerIdAlias && rawPeerIdAlias !== normalizedPeerId ? [rawPeerIdAlias] : undefined,
|
||||
peerKind: inferredPeerKind,
|
||||
})
|
||||
|
||||
@@ -340,7 +340,7 @@ describe("resolveFirstBoundAccountId", () => {
|
||||
channelId: "qa-channel",
|
||||
agentId: "bot-alpha",
|
||||
peerId: "conversation-a",
|
||||
peerIdAliases: ["channel:conversation-a"],
|
||||
exactPeerIdAliases: ["channel:conversation-a"],
|
||||
peerKind: "channel",
|
||||
}),
|
||||
).toBe("bot-alpha-conversation");
|
||||
|
||||
@@ -56,8 +56,25 @@ function peerKindMatches(a: ChatType, b: ChatType): boolean {
|
||||
if (a === b) {
|
||||
return true;
|
||||
}
|
||||
const pair = new Set([a, b]);
|
||||
return pair.has("group") && pair.has("channel");
|
||||
return (a === "group" && b === "channel") || (a === "channel" && b === "group");
|
||||
}
|
||||
|
||||
function buildExactPeerIdSet(params: {
|
||||
peerId?: string;
|
||||
exactPeerIdAliases?: string[];
|
||||
}): Set<string> {
|
||||
const exactPeerIds = new Set<string>();
|
||||
const peerId = params.peerId?.trim();
|
||||
if (peerId) {
|
||||
exactPeerIds.add(peerId);
|
||||
}
|
||||
for (const alias of params.exactPeerIdAliases ?? []) {
|
||||
const trimmed = alias.trim();
|
||||
if (trimmed) {
|
||||
exactPeerIds.add(trimmed);
|
||||
}
|
||||
}
|
||||
return exactPeerIds;
|
||||
}
|
||||
|
||||
export function resolveFirstBoundAccountId(params: {
|
||||
@@ -65,7 +82,7 @@ export function resolveFirstBoundAccountId(params: {
|
||||
channelId: string;
|
||||
agentId: string;
|
||||
peerId?: string;
|
||||
peerIdAliases?: string[];
|
||||
exactPeerIdAliases?: string[];
|
||||
peerKind?: ChatType;
|
||||
}): string | undefined {
|
||||
const normalizedChannel = normalizeBindingChannelId(params.channelId);
|
||||
@@ -74,12 +91,10 @@ export function resolveFirstBoundAccountId(params: {
|
||||
}
|
||||
const normalizedAgentId = normalizeAgentId(params.agentId);
|
||||
const normalizedPeerId = params.peerId?.trim() || undefined;
|
||||
const exactPeerIds = new Set(
|
||||
[
|
||||
normalizedPeerId,
|
||||
...(params.peerIdAliases ?? []).map((value) => value.trim()).filter(Boolean),
|
||||
].filter((value): value is string => Boolean(value)),
|
||||
);
|
||||
const exactPeerIds = buildExactPeerIdSet({
|
||||
peerId: normalizedPeerId,
|
||||
exactPeerIdAliases: params.exactPeerIdAliases,
|
||||
});
|
||||
const normalizedPeerKind = normalizeChatType(params.peerKind) ?? undefined;
|
||||
let wildcardPeerMatch: string | undefined;
|
||||
let channelOnlyFallback: string | undefined;
|
||||
|
||||
Reference in New Issue
Block a user