mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-23 17:48:11 +00:00
Agents: preserve role-based routing in bind key matching
This commit is contained in:
@@ -95,4 +95,47 @@ describe("agents bind/unbind commands", () => {
|
||||
expect(runtime.error).toHaveBeenCalledWith("Bindings are owned by another agent:");
|
||||
expect(runtime.exit).toHaveBeenCalledWith(1);
|
||||
});
|
||||
|
||||
it("keeps role-based bindings when removing channel-level discord binding", async () => {
|
||||
readConfigFileSnapshotMock.mockResolvedValue({
|
||||
...baseConfigSnapshot,
|
||||
config: {
|
||||
bindings: [
|
||||
{
|
||||
agentId: "main",
|
||||
match: {
|
||||
channel: "discord",
|
||||
accountId: "guild-a",
|
||||
roles: ["111", "222"],
|
||||
},
|
||||
},
|
||||
{
|
||||
agentId: "main",
|
||||
match: {
|
||||
channel: "discord",
|
||||
accountId: "guild-a",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
await agentsUnbindCommand({ bind: ["discord:guild-a"] }, runtime);
|
||||
|
||||
expect(writeConfigFileMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
bindings: [
|
||||
{
|
||||
agentId: "main",
|
||||
match: {
|
||||
channel: "discord",
|
||||
accountId: "guild-a",
|
||||
roles: ["111", "222"],
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
expect(runtime.exit).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -8,6 +8,16 @@ import type { ChannelChoice } from "./onboard-types.js";
|
||||
|
||||
function bindingMatchKey(match: AgentBinding["match"]) {
|
||||
const accountId = match.accountId?.trim() || DEFAULT_ACCOUNT_ID;
|
||||
const roles = Array.isArray(match.roles)
|
||||
? Array.from(
|
||||
new Set(
|
||||
match.roles
|
||||
.map((role) => role.trim())
|
||||
.filter(Boolean)
|
||||
.toSorted(),
|
||||
),
|
||||
)
|
||||
: [];
|
||||
return [
|
||||
match.channel,
|
||||
accountId,
|
||||
@@ -15,6 +25,7 @@ function bindingMatchKey(match: AgentBinding["match"]) {
|
||||
match.peer?.id ?? "",
|
||||
match.guildId ?? "",
|
||||
match.teamId ?? "",
|
||||
roles.join(","),
|
||||
].join("|");
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
applyAgentConfig,
|
||||
buildAgentSummaries,
|
||||
pruneAgentConfig,
|
||||
removeAgentBindings,
|
||||
} from "./agents.js";
|
||||
|
||||
describe("agents helpers", () => {
|
||||
@@ -111,6 +112,86 @@ describe("agents helpers", () => {
|
||||
expect(result.config.bindings).toHaveLength(2);
|
||||
});
|
||||
|
||||
it("applyAgentBindings treats role-based bindings as distinct routes", () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
bindings: [
|
||||
{
|
||||
agentId: "main",
|
||||
match: {
|
||||
channel: "discord",
|
||||
accountId: "guild-a",
|
||||
guildId: "123",
|
||||
roles: ["111", "222"],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const result = applyAgentBindings(cfg, [
|
||||
{
|
||||
agentId: "work",
|
||||
match: {
|
||||
channel: "discord",
|
||||
accountId: "guild-a",
|
||||
guildId: "123",
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
expect(result.added).toHaveLength(1);
|
||||
expect(result.conflicts).toHaveLength(0);
|
||||
expect(result.config.bindings).toHaveLength(2);
|
||||
});
|
||||
|
||||
it("removeAgentBindings does not remove role-based bindings when removing channel-level routes", () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
bindings: [
|
||||
{
|
||||
agentId: "main",
|
||||
match: {
|
||||
channel: "discord",
|
||||
accountId: "guild-a",
|
||||
guildId: "123",
|
||||
roles: ["111", "222"],
|
||||
},
|
||||
},
|
||||
{
|
||||
agentId: "main",
|
||||
match: {
|
||||
channel: "discord",
|
||||
accountId: "guild-a",
|
||||
guildId: "123",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const result = removeAgentBindings(cfg, [
|
||||
{
|
||||
agentId: "main",
|
||||
match: {
|
||||
channel: "discord",
|
||||
accountId: "guild-a",
|
||||
guildId: "123",
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
expect(result.removed).toHaveLength(1);
|
||||
expect(result.conflicts).toHaveLength(0);
|
||||
expect(result.config.bindings).toEqual([
|
||||
{
|
||||
agentId: "main",
|
||||
match: {
|
||||
channel: "discord",
|
||||
accountId: "guild-a",
|
||||
guildId: "123",
|
||||
roles: ["111", "222"],
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("pruneAgentConfig removes agent, bindings, and allowlist entries", () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
agents: {
|
||||
|
||||
Reference in New Issue
Block a user