Discord: route bound DMs to plugins
This commit is contained in:
parent
d0731c35b2
commit
eb4e96573a
@ -2110,6 +2110,73 @@ describe("dispatchReplyFromConfig", () => {
|
||||
expect(replyResolver).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("routes plugin-owned Discord DM bindings to the owning plugin before generic inbound claim broadcast", async () => {
|
||||
setNoAbort();
|
||||
hookMocks.runner.hasHooks.mockImplementation(
|
||||
((hookName?: string) =>
|
||||
hookName === "inbound_claim" || hookName === "message_received") as () => boolean,
|
||||
);
|
||||
sessionBindingMocks.resolveByConversation.mockReturnValue({
|
||||
bindingId: "binding-dm-1",
|
||||
targetSessionKey: "plugin-binding:codex:dm123",
|
||||
targetKind: "session",
|
||||
conversation: {
|
||||
channel: "discord",
|
||||
accountId: "default",
|
||||
conversationId: "user:1177378744822943744",
|
||||
},
|
||||
status: "active",
|
||||
boundAt: 1710000000000,
|
||||
metadata: {
|
||||
pluginBindingOwner: "plugin",
|
||||
pluginId: "openclaw-codex-app-server",
|
||||
pluginRoot: "/Users/huntharo/github/openclaw-app-server",
|
||||
},
|
||||
} satisfies SessionBindingRecord);
|
||||
const cfg = emptyConfig;
|
||||
const dispatcher = createDispatcher();
|
||||
const ctx = buildTestCtx({
|
||||
Provider: "discord",
|
||||
Surface: "discord",
|
||||
OriginatingChannel: "discord",
|
||||
From: "discord:1177378744822943744",
|
||||
OriginatingTo: "channel:1480574946919846079",
|
||||
To: "channel:1480574946919846079",
|
||||
AccountId: "default",
|
||||
SenderId: "user-9",
|
||||
SenderUsername: "ada",
|
||||
CommandAuthorized: true,
|
||||
WasMentioned: false,
|
||||
CommandBody: "who are you",
|
||||
RawBody: "who are you",
|
||||
Body: "who are you",
|
||||
MessageSid: "msg-claim-plugin-dm-1",
|
||||
SessionKey: "agent:main:discord:user:1177378744822943744",
|
||||
});
|
||||
const replyResolver = vi.fn(async () => ({ text: "should not run" }) satisfies ReplyPayload);
|
||||
|
||||
const result = await dispatchReplyFromConfig({ ctx, cfg, dispatcher, replyResolver });
|
||||
|
||||
expect(result).toEqual({ queuedFinal: false, counts: { tool: 0, block: 0, final: 0 } });
|
||||
expect(sessionBindingMocks.touch).toHaveBeenCalledWith("binding-dm-1");
|
||||
expect(hookMocks.runner.runInboundClaimForPlugin).toHaveBeenCalledWith(
|
||||
"openclaw-codex-app-server",
|
||||
expect.objectContaining({
|
||||
channel: "discord",
|
||||
accountId: "default",
|
||||
conversationId: "user:1177378744822943744",
|
||||
content: "who are you",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
channelId: "discord",
|
||||
accountId: "default",
|
||||
conversationId: "user:1177378744822943744",
|
||||
}),
|
||||
);
|
||||
expect(hookMocks.runner.runInboundClaim).not.toHaveBeenCalled();
|
||||
expect(replyResolver).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("marks diagnostics skipped for duplicate inbound messages", async () => {
|
||||
setNoAbort();
|
||||
const cfg = { diagnostics: { enabled: true } } as OpenClawConfig;
|
||||
|
||||
@ -116,7 +116,31 @@ describe("message hook mappers", () => {
|
||||
expect(toPluginInboundClaimContext(canonical)).toEqual({
|
||||
channelId: "discord",
|
||||
accountId: "acc-1",
|
||||
conversationId: "123456789012345678",
|
||||
conversationId: "channel:123456789012345678",
|
||||
parentConversationId: undefined,
|
||||
senderId: "sender-1",
|
||||
messageId: "msg-1",
|
||||
});
|
||||
});
|
||||
|
||||
it("normalizes Discord DM targets for inbound claim contexts", () => {
|
||||
const canonical = deriveInboundMessageHookContext(
|
||||
makeInboundCtx({
|
||||
Provider: "discord",
|
||||
Surface: "discord",
|
||||
OriginatingChannel: "discord",
|
||||
From: "discord:1177378744822943744",
|
||||
To: "channel:1480574946919846079",
|
||||
OriginatingTo: "channel:1480574946919846079",
|
||||
GroupChannel: undefined,
|
||||
GroupSubject: undefined,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(toPluginInboundClaimContext(canonical)).toEqual({
|
||||
channelId: "discord",
|
||||
accountId: "acc-1",
|
||||
conversationId: "user:1177378744822943744",
|
||||
parentConversationId: undefined,
|
||||
senderId: "sender-1",
|
||||
messageId: "msg-1",
|
||||
|
||||
@ -179,6 +179,33 @@ function deriveParentConversationId(
|
||||
}
|
||||
|
||||
function deriveConversationId(canonical: CanonicalInboundMessageHookContext): string | undefined {
|
||||
if (canonical.channelId === "discord") {
|
||||
const rawTarget = canonical.to ?? canonical.originatingTo ?? canonical.conversationId;
|
||||
const rawSender = canonical.from;
|
||||
const senderUserId = rawSender?.startsWith("discord:user:")
|
||||
? rawSender.slice("discord:user:".length)
|
||||
: rawSender?.startsWith("discord:")
|
||||
? rawSender.slice("discord:".length)
|
||||
: undefined;
|
||||
if (!canonical.isGroup && senderUserId) {
|
||||
return `user:${senderUserId}`;
|
||||
}
|
||||
if (!rawTarget) {
|
||||
return undefined;
|
||||
}
|
||||
if (rawTarget.startsWith("discord:channel:")) {
|
||||
return `channel:${rawTarget.slice("discord:channel:".length)}`;
|
||||
}
|
||||
if (rawTarget.startsWith("discord:user:")) {
|
||||
return `user:${rawTarget.slice("discord:user:".length)}`;
|
||||
}
|
||||
if (rawTarget.startsWith("discord:")) {
|
||||
return `user:${rawTarget.slice("discord:".length)}`;
|
||||
}
|
||||
if (rawTarget.startsWith("channel:") || rawTarget.startsWith("user:")) {
|
||||
return rawTarget;
|
||||
}
|
||||
}
|
||||
const baseConversationId = stripChannelPrefix(
|
||||
canonical.to ?? canonical.originatingTo ?? canonical.conversationId,
|
||||
canonical.channelId,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user