mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:00:42 +00:00
fix(hooks): tighten thread ownership mention matching
This commit is contained in:
@@ -325,5 +325,49 @@ describe("thread-ownership plugin", () => {
|
||||
expect(result).toBeUndefined();
|
||||
expect(globalThis.fetch).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not treat superset handles as agent-name mentions", async () => {
|
||||
await hooks.message_received(
|
||||
{
|
||||
content: "hey @testbot2 help",
|
||||
threadId: "8888.0003",
|
||||
metadata: { channelId: "C789" },
|
||||
},
|
||||
{ channelId: "slack", conversationId: "C789" },
|
||||
);
|
||||
|
||||
vi.mocked(globalThis.fetch).mockResolvedValue(
|
||||
new Response(JSON.stringify({ owner: "test-agent" }), { status: 200 }),
|
||||
);
|
||||
|
||||
await hooks.message_sending(
|
||||
{ content: "On it!", replyToId: "8888.0003", metadata: { channelId: "C789" }, to: "C789" },
|
||||
{ channelId: "slack", conversationId: "C789" },
|
||||
);
|
||||
|
||||
expect(globalThis.fetch).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not treat email-like text as an agent-name mention", async () => {
|
||||
await hooks.message_received(
|
||||
{
|
||||
content: "send mail to foo@testbot.com",
|
||||
threadId: "8888.0004",
|
||||
metadata: { channelId: "C789" },
|
||||
},
|
||||
{ channelId: "slack", conversationId: "C789" },
|
||||
);
|
||||
|
||||
vi.mocked(globalThis.fetch).mockResolvedValue(
|
||||
new Response(JSON.stringify({ owner: "test-agent" }), { status: 200 }),
|
||||
);
|
||||
|
||||
await hooks.message_sending(
|
||||
{ content: "On it!", replyToId: "8888.0004", metadata: { channelId: "C789" }, to: "C789" },
|
||||
{ channelId: "slack", conversationId: "C789" },
|
||||
);
|
||||
|
||||
expect(globalThis.fetch).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -24,6 +24,10 @@ function resolveThreadToken(value: unknown): string {
|
||||
return typeof value === "string" || typeof value === "number" ? String(value) : "";
|
||||
}
|
||||
|
||||
function escapeRegExp(value: string): string {
|
||||
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
}
|
||||
|
||||
function resolveSlackConversationId(value: unknown): string {
|
||||
const raw = normalizeOptionalString(value) ?? "";
|
||||
if (!raw) {
|
||||
@@ -44,6 +48,14 @@ function cleanExpiredMentions(): void {
|
||||
}
|
||||
}
|
||||
|
||||
function containsAgentNameMention(text: string, agentName: string): boolean {
|
||||
const trimmedName = agentName.trim();
|
||||
if (!trimmedName) {
|
||||
return false;
|
||||
}
|
||||
return new RegExp(`(^|[^\\w])@${escapeRegExp(trimmedName)}(?=$|[^\\w])`, "i").test(text);
|
||||
}
|
||||
|
||||
function resolveOwnershipAgent(config: OpenClawConfig): { id: string; name: string } {
|
||||
const list = Array.isArray(config.agents?.list)
|
||||
? config.agents.list.filter(
|
||||
@@ -91,7 +103,6 @@ export default definePluginEntry({
|
||||
}
|
||||
|
||||
const text = event.content ?? "";
|
||||
const normalizedText = text.toLowerCase();
|
||||
const threadTs =
|
||||
resolveThreadToken(event.threadId) ||
|
||||
resolveThreadToken(event.metadata?.threadId) ||
|
||||
@@ -105,7 +116,7 @@ export default definePluginEntry({
|
||||
}
|
||||
|
||||
const mentioned =
|
||||
(agentName && normalizedText.includes(`@${agentName.toLowerCase()}`)) ||
|
||||
containsAgentNameMention(text, agentName) ||
|
||||
(botUserId && text.includes(`<@${botUserId}>`));
|
||||
if (mentioned) {
|
||||
cleanExpiredMentions();
|
||||
|
||||
Reference in New Issue
Block a user