mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
274 lines
7.6 KiB
TypeScript
274 lines
7.6 KiB
TypeScript
import type { FinalizedMsgContext } from "../auto-reply/templating.js";
|
|
import type { OpenClawConfig } from "../config/config.js";
|
|
import type {
|
|
PluginHookMessageContext,
|
|
PluginHookMessageReceivedEvent,
|
|
PluginHookMessageSentEvent,
|
|
} from "../plugins/types.js";
|
|
import type {
|
|
MessagePreprocessedHookContext,
|
|
MessageReceivedHookContext,
|
|
MessageSentHookContext,
|
|
MessageTranscribedHookContext,
|
|
} from "./internal-hooks.js";
|
|
|
|
export type CanonicalInboundMessageHookContext = {
|
|
from: string;
|
|
to?: string;
|
|
content: string;
|
|
body?: string;
|
|
bodyForAgent?: string;
|
|
transcript?: string;
|
|
timestamp?: number;
|
|
channelId: string;
|
|
accountId?: string;
|
|
conversationId?: string;
|
|
messageId?: string;
|
|
senderId?: string;
|
|
senderName?: string;
|
|
senderUsername?: string;
|
|
senderE164?: string;
|
|
provider?: string;
|
|
surface?: string;
|
|
threadId?: string | number;
|
|
mediaPath?: string;
|
|
mediaType?: string;
|
|
originatingChannel?: string;
|
|
originatingTo?: string;
|
|
guildId?: string;
|
|
channelName?: string;
|
|
isGroup: boolean;
|
|
groupId?: string;
|
|
};
|
|
|
|
export type CanonicalSentMessageHookContext = {
|
|
to: string;
|
|
content: string;
|
|
success: boolean;
|
|
error?: string;
|
|
channelId: string;
|
|
accountId?: string;
|
|
conversationId?: string;
|
|
messageId?: string;
|
|
isGroup?: boolean;
|
|
groupId?: string;
|
|
};
|
|
|
|
export function deriveInboundMessageHookContext(
|
|
ctx: FinalizedMsgContext,
|
|
overrides?: {
|
|
content?: string;
|
|
messageId?: string;
|
|
},
|
|
): CanonicalInboundMessageHookContext {
|
|
const content =
|
|
overrides?.content ??
|
|
(typeof ctx.BodyForCommands === "string"
|
|
? ctx.BodyForCommands
|
|
: typeof ctx.RawBody === "string"
|
|
? ctx.RawBody
|
|
: typeof ctx.Body === "string"
|
|
? ctx.Body
|
|
: "");
|
|
const channelId = (ctx.OriginatingChannel ?? ctx.Surface ?? ctx.Provider ?? "").toLowerCase();
|
|
const conversationId = ctx.OriginatingTo ?? ctx.To ?? ctx.From ?? undefined;
|
|
const isGroup = Boolean(ctx.GroupSubject || ctx.GroupChannel);
|
|
return {
|
|
from: ctx.From ?? "",
|
|
to: ctx.To,
|
|
content,
|
|
body: ctx.Body,
|
|
bodyForAgent: ctx.BodyForAgent,
|
|
transcript: ctx.Transcript,
|
|
timestamp:
|
|
typeof ctx.Timestamp === "number" && Number.isFinite(ctx.Timestamp)
|
|
? ctx.Timestamp
|
|
: undefined,
|
|
channelId,
|
|
accountId: ctx.AccountId,
|
|
conversationId,
|
|
messageId:
|
|
overrides?.messageId ??
|
|
ctx.MessageSidFull ??
|
|
ctx.MessageSid ??
|
|
ctx.MessageSidFirst ??
|
|
ctx.MessageSidLast,
|
|
senderId: ctx.SenderId,
|
|
senderName: ctx.SenderName,
|
|
senderUsername: ctx.SenderUsername,
|
|
senderE164: ctx.SenderE164,
|
|
provider: ctx.Provider,
|
|
surface: ctx.Surface,
|
|
threadId: ctx.MessageThreadId,
|
|
mediaPath: ctx.MediaPath,
|
|
mediaType: ctx.MediaType,
|
|
originatingChannel: ctx.OriginatingChannel,
|
|
originatingTo: ctx.OriginatingTo,
|
|
guildId: ctx.GroupSpace,
|
|
channelName: ctx.GroupChannel,
|
|
isGroup,
|
|
groupId: isGroup ? conversationId : undefined,
|
|
};
|
|
}
|
|
|
|
export function buildCanonicalSentMessageHookContext(params: {
|
|
to: string;
|
|
content: string;
|
|
success: boolean;
|
|
error?: string;
|
|
channelId: string;
|
|
accountId?: string;
|
|
conversationId?: string;
|
|
messageId?: string;
|
|
isGroup?: boolean;
|
|
groupId?: string;
|
|
}): CanonicalSentMessageHookContext {
|
|
return {
|
|
to: params.to,
|
|
content: params.content,
|
|
success: params.success,
|
|
error: params.error,
|
|
channelId: params.channelId,
|
|
accountId: params.accountId,
|
|
conversationId: params.conversationId ?? params.to,
|
|
messageId: params.messageId,
|
|
isGroup: params.isGroup,
|
|
groupId: params.groupId,
|
|
};
|
|
}
|
|
|
|
export function toPluginMessageContext(
|
|
canonical: CanonicalInboundMessageHookContext | CanonicalSentMessageHookContext,
|
|
): PluginHookMessageContext {
|
|
return {
|
|
channelId: canonical.channelId,
|
|
accountId: canonical.accountId,
|
|
conversationId: canonical.conversationId,
|
|
};
|
|
}
|
|
|
|
export function toPluginMessageReceivedEvent(
|
|
canonical: CanonicalInboundMessageHookContext,
|
|
): PluginHookMessageReceivedEvent {
|
|
return {
|
|
from: canonical.from,
|
|
content: canonical.content,
|
|
timestamp: canonical.timestamp,
|
|
metadata: {
|
|
to: canonical.to,
|
|
provider: canonical.provider,
|
|
surface: canonical.surface,
|
|
threadId: canonical.threadId,
|
|
originatingChannel: canonical.originatingChannel,
|
|
originatingTo: canonical.originatingTo,
|
|
messageId: canonical.messageId,
|
|
senderId: canonical.senderId,
|
|
senderName: canonical.senderName,
|
|
senderUsername: canonical.senderUsername,
|
|
senderE164: canonical.senderE164,
|
|
guildId: canonical.guildId,
|
|
channelName: canonical.channelName,
|
|
},
|
|
};
|
|
}
|
|
|
|
export function toPluginMessageSentEvent(
|
|
canonical: CanonicalSentMessageHookContext,
|
|
): PluginHookMessageSentEvent {
|
|
return {
|
|
to: canonical.to,
|
|
content: canonical.content,
|
|
success: canonical.success,
|
|
...(canonical.error ? { error: canonical.error } : {}),
|
|
};
|
|
}
|
|
|
|
export function toInternalMessageReceivedContext(
|
|
canonical: CanonicalInboundMessageHookContext,
|
|
): MessageReceivedHookContext {
|
|
return {
|
|
from: canonical.from,
|
|
content: canonical.content,
|
|
timestamp: canonical.timestamp,
|
|
channelId: canonical.channelId,
|
|
accountId: canonical.accountId,
|
|
conversationId: canonical.conversationId,
|
|
messageId: canonical.messageId,
|
|
metadata: {
|
|
to: canonical.to,
|
|
provider: canonical.provider,
|
|
surface: canonical.surface,
|
|
threadId: canonical.threadId,
|
|
senderId: canonical.senderId,
|
|
senderName: canonical.senderName,
|
|
senderUsername: canonical.senderUsername,
|
|
senderE164: canonical.senderE164,
|
|
guildId: canonical.guildId,
|
|
channelName: canonical.channelName,
|
|
},
|
|
};
|
|
}
|
|
|
|
export function toInternalMessageTranscribedContext(
|
|
canonical: CanonicalInboundMessageHookContext,
|
|
cfg: OpenClawConfig,
|
|
): MessageTranscribedHookContext & { cfg: OpenClawConfig } {
|
|
const shared = toInternalInboundMessageHookContextBase(canonical);
|
|
return {
|
|
...shared,
|
|
transcript: canonical.transcript ?? "",
|
|
cfg,
|
|
};
|
|
}
|
|
|
|
export function toInternalMessagePreprocessedContext(
|
|
canonical: CanonicalInboundMessageHookContext,
|
|
cfg: OpenClawConfig,
|
|
): MessagePreprocessedHookContext & { cfg: OpenClawConfig } {
|
|
const shared = toInternalInboundMessageHookContextBase(canonical);
|
|
return {
|
|
...shared,
|
|
transcript: canonical.transcript,
|
|
isGroup: canonical.isGroup,
|
|
groupId: canonical.groupId,
|
|
cfg,
|
|
};
|
|
}
|
|
|
|
function toInternalInboundMessageHookContextBase(canonical: CanonicalInboundMessageHookContext) {
|
|
return {
|
|
from: canonical.from,
|
|
to: canonical.to,
|
|
body: canonical.body,
|
|
bodyForAgent: canonical.bodyForAgent,
|
|
timestamp: canonical.timestamp,
|
|
channelId: canonical.channelId,
|
|
conversationId: canonical.conversationId,
|
|
messageId: canonical.messageId,
|
|
senderId: canonical.senderId,
|
|
senderName: canonical.senderName,
|
|
senderUsername: canonical.senderUsername,
|
|
provider: canonical.provider,
|
|
surface: canonical.surface,
|
|
mediaPath: canonical.mediaPath,
|
|
mediaType: canonical.mediaType,
|
|
};
|
|
}
|
|
|
|
export function toInternalMessageSentContext(
|
|
canonical: CanonicalSentMessageHookContext,
|
|
): MessageSentHookContext {
|
|
return {
|
|
to: canonical.to,
|
|
content: canonical.content,
|
|
success: canonical.success,
|
|
...(canonical.error ? { error: canonical.error } : {}),
|
|
channelId: canonical.channelId,
|
|
accountId: canonical.accountId,
|
|
conversationId: canonical.conversationId,
|
|
messageId: canonical.messageId,
|
|
...(canonical.isGroup != null ? { isGroup: canonical.isGroup } : {}),
|
|
...(canonical.groupId ? { groupId: canonical.groupId } : {}),
|
|
};
|
|
}
|