mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 13:00:45 +00:00
fix(plugins): derive hook channel ids from targets
This commit is contained in:
61
src/plugins/hook-agent-context.test.ts
Normal file
61
src/plugins/hook-agent-context.test.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
buildAgentHookContextChannelFields,
|
||||
resolveAgentHookChannelId,
|
||||
} from "./hook-agent-context.js";
|
||||
|
||||
describe("resolveAgentHookChannelId", () => {
|
||||
it("derives the conversation id from channel session keys", () => {
|
||||
expect(
|
||||
resolveAgentHookChannelId({
|
||||
sessionKey: "agent:main:discord:channel:1472750640760623226",
|
||||
messageChannel: "discord",
|
||||
messageProvider: "discord",
|
||||
currentChannelId: "channel:1472750640760623226",
|
||||
}),
|
||||
).toBe("1472750640760623226");
|
||||
});
|
||||
|
||||
it("uses target metadata when the session key is not a channel conversation", () => {
|
||||
expect(
|
||||
resolveAgentHookChannelId({
|
||||
sessionKey: "agent:main:main",
|
||||
messageProvider: "telegram",
|
||||
currentChannelId: "telegram:-1003841603622",
|
||||
}),
|
||||
).toBe("-1003841603622");
|
||||
});
|
||||
|
||||
it("uses prefixed message targets before falling back to the provider", () => {
|
||||
expect(
|
||||
resolveAgentHookChannelId({
|
||||
messageChannel: "channel:1472750640760623226",
|
||||
messageProvider: "discord",
|
||||
}),
|
||||
).toBe("1472750640760623226");
|
||||
});
|
||||
|
||||
it("falls back to legacy channel/provider values when no conversation id is available", () => {
|
||||
expect(
|
||||
resolveAgentHookChannelId({
|
||||
messageChannel: "discord",
|
||||
messageProvider: "discord",
|
||||
}),
|
||||
).toBe("discord");
|
||||
});
|
||||
});
|
||||
|
||||
describe("buildAgentHookContextChannelFields", () => {
|
||||
it("keeps provider and conversation id separate", () => {
|
||||
expect(
|
||||
buildAgentHookContextChannelFields({
|
||||
sessionKey: "agent:main:discord:channel:c1",
|
||||
messageChannel: "discord",
|
||||
messageProvider: "discord",
|
||||
}),
|
||||
).toEqual({
|
||||
messageProvider: "discord",
|
||||
channelId: "c1",
|
||||
});
|
||||
});
|
||||
});
|
||||
74
src/plugins/hook-agent-context.ts
Normal file
74
src/plugins/hook-agent-context.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { parseRawSessionConversationRef } from "../sessions/session-key-utils.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import type { PluginHookAgentContext } from "./hook-types.js";
|
||||
|
||||
const TARGET_PREFIXES = new Set(["channel", "chat", "direct", "dm", "group", "thread", "user"]);
|
||||
|
||||
function normalizeKey(value: string | undefined): string {
|
||||
return (value ?? "").trim().toLowerCase();
|
||||
}
|
||||
|
||||
function stripConversationPrefix(
|
||||
value: string | undefined,
|
||||
provider: string | undefined,
|
||||
): string | undefined {
|
||||
const text = normalizeOptionalString(value);
|
||||
if (!text) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const separatorIndex = text.indexOf(":");
|
||||
if (separatorIndex === -1) {
|
||||
return text;
|
||||
}
|
||||
|
||||
const prefix = normalizeKey(text.slice(0, separatorIndex));
|
||||
const suffix = normalizeOptionalString(text.slice(separatorIndex + 1));
|
||||
if (!suffix) {
|
||||
return text;
|
||||
}
|
||||
if (TARGET_PREFIXES.has(prefix) || (provider && prefix === normalizeKey(provider))) {
|
||||
return suffix;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
export function resolveAgentHookChannelId(params: {
|
||||
sessionKey?: string | null;
|
||||
messageChannel?: string | null;
|
||||
messageProvider?: string | null;
|
||||
currentChannelId?: string | null;
|
||||
messageTo?: string | null;
|
||||
}): string | undefined {
|
||||
const provider = normalizeOptionalString(params.messageProvider);
|
||||
const parsed = parseRawSessionConversationRef(params.sessionKey);
|
||||
if (parsed?.rawId) {
|
||||
return parsed.rawId;
|
||||
}
|
||||
|
||||
const metadataChannel =
|
||||
stripConversationPrefix(params.currentChannelId ?? undefined, provider) ??
|
||||
stripConversationPrefix(params.messageTo ?? undefined, provider);
|
||||
if (metadataChannel && normalizeKey(metadataChannel) !== normalizeKey(provider)) {
|
||||
return metadataChannel;
|
||||
}
|
||||
|
||||
const messageChannel = stripConversationPrefix(params.messageChannel ?? undefined, provider);
|
||||
if (messageChannel && normalizeKey(messageChannel) !== normalizeKey(provider)) {
|
||||
return messageChannel;
|
||||
}
|
||||
return normalizeOptionalString(params.messageChannel) ?? provider;
|
||||
}
|
||||
|
||||
export function buildAgentHookContextChannelFields(params: {
|
||||
sessionKey?: string | null;
|
||||
messageChannel?: string | null;
|
||||
messageProvider?: string | null;
|
||||
currentChannelId?: string | null;
|
||||
messageTo?: string | null;
|
||||
}): Pick<PluginHookAgentContext, "channelId" | "messageProvider"> {
|
||||
return {
|
||||
messageProvider: normalizeOptionalString(params.messageProvider),
|
||||
channelId: resolveAgentHookChannelId(params),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user