mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 14:24:30 +00:00
fix(routing): exclude peer-specific bindings from guild-wide matching (#15274)
* fix(routing): exclude peer-specific bindings from guild-wide matching (#14752) * fix(routing): enforce binding scope AND semantics + regressions * fix(routing): document strict binding-scope behavior (#15274) (thanks @lailoo) --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
@@ -169,6 +169,126 @@ describe("resolveAgentRoute", () => {
|
||||
expect(route.matchedBy).toBe("binding.guild");
|
||||
});
|
||||
|
||||
test("peer+guild binding does not act as guild-wide fallback when peer mismatches (#14752)", () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
bindings: [
|
||||
{
|
||||
agentId: "olga",
|
||||
match: {
|
||||
channel: "discord",
|
||||
peer: { kind: "channel", id: "CHANNEL_A" },
|
||||
guildId: "GUILD_1",
|
||||
},
|
||||
},
|
||||
{
|
||||
agentId: "main",
|
||||
match: {
|
||||
channel: "discord",
|
||||
guildId: "GUILD_1",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
const route = resolveAgentRoute({
|
||||
cfg,
|
||||
channel: "discord",
|
||||
peer: { kind: "channel", id: "CHANNEL_B" },
|
||||
guildId: "GUILD_1",
|
||||
});
|
||||
expect(route.agentId).toBe("main");
|
||||
expect(route.matchedBy).toBe("binding.guild");
|
||||
});
|
||||
|
||||
test("peer+guild binding requires guild match even when peer matches", () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
bindings: [
|
||||
{
|
||||
agentId: "wrongguild",
|
||||
match: {
|
||||
channel: "discord",
|
||||
peer: { kind: "channel", id: "c1" },
|
||||
guildId: "g1",
|
||||
},
|
||||
},
|
||||
{
|
||||
agentId: "rightguild",
|
||||
match: {
|
||||
channel: "discord",
|
||||
guildId: "g2",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
const route = resolveAgentRoute({
|
||||
cfg,
|
||||
channel: "discord",
|
||||
peer: { kind: "channel", id: "c1" },
|
||||
guildId: "g2",
|
||||
});
|
||||
expect(route.agentId).toBe("rightguild");
|
||||
expect(route.matchedBy).toBe("binding.guild");
|
||||
});
|
||||
|
||||
test("peer+team binding does not act as team-wide fallback when peer mismatches", () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
bindings: [
|
||||
{
|
||||
agentId: "roomonly",
|
||||
match: {
|
||||
channel: "slack",
|
||||
peer: { kind: "channel", id: "C_A" },
|
||||
teamId: "T1",
|
||||
},
|
||||
},
|
||||
{
|
||||
agentId: "teamwide",
|
||||
match: {
|
||||
channel: "slack",
|
||||
teamId: "T1",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
const route = resolveAgentRoute({
|
||||
cfg,
|
||||
channel: "slack",
|
||||
teamId: "T1",
|
||||
peer: { kind: "channel", id: "C_B" },
|
||||
});
|
||||
expect(route.agentId).toBe("teamwide");
|
||||
expect(route.matchedBy).toBe("binding.team");
|
||||
});
|
||||
|
||||
test("peer+team binding requires team match even when peer matches", () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
bindings: [
|
||||
{
|
||||
agentId: "wrongteam",
|
||||
match: {
|
||||
channel: "slack",
|
||||
peer: { kind: "channel", id: "C1" },
|
||||
teamId: "T1",
|
||||
},
|
||||
},
|
||||
{
|
||||
agentId: "rightteam",
|
||||
match: {
|
||||
channel: "slack",
|
||||
teamId: "T2",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
const route = resolveAgentRoute({
|
||||
cfg,
|
||||
channel: "slack",
|
||||
teamId: "T2",
|
||||
peer: { kind: "channel", id: "C1" },
|
||||
});
|
||||
expect(route.agentId).toBe("rightteam");
|
||||
expect(route.matchedBy).toBe("binding.team");
|
||||
});
|
||||
|
||||
test("missing accountId in binding matches default account only", () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
bindings: [{ agentId: "defaultAcct", match: { channel: "whatsapp" } }],
|
||||
@@ -592,4 +712,37 @@ describe("role-based agent routing", () => {
|
||||
expect(route.agentId).toBe("main");
|
||||
expect(route.matchedBy).toBe("default");
|
||||
});
|
||||
|
||||
test("peer+guild+roles binding does not act as guild+roles fallback when peer mismatches", () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
bindings: [
|
||||
{
|
||||
agentId: "peer-roles",
|
||||
match: {
|
||||
channel: "discord",
|
||||
peer: { kind: "channel", id: "c-target" },
|
||||
guildId: "g1",
|
||||
roles: ["r1"],
|
||||
},
|
||||
},
|
||||
{
|
||||
agentId: "guild-roles",
|
||||
match: {
|
||||
channel: "discord",
|
||||
guildId: "g1",
|
||||
roles: ["r1"],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
const route = resolveAgentRoute({
|
||||
cfg,
|
||||
channel: "discord",
|
||||
guildId: "g1",
|
||||
memberRoleIds: ["r1"],
|
||||
peer: { kind: "channel", id: "c-other" },
|
||||
});
|
||||
expect(route.agentId).toBe("guild-roles");
|
||||
expect(route.matchedBy).toBe("binding.guild+roles");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user