mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-26 07:57:40 +00:00
feat(hooks): add message:transcribed and message:preprocessed internal hooks
Adds two new internal hook events that fire after media/link processing:
- message:transcribed: fires when audio has been transcribed, providing
the transcript text alongside the original body and media metadata.
Useful for logging, analytics, or routing based on spoken content.
- message:preprocessed: fires for every message after all media + link
understanding completes. Gives hooks access to the fully enriched body
(transcripts, image descriptions, link summaries) before the agent sees it.
Both hooks are added in get-reply.ts, after applyMediaUnderstanding and
applyLinkUnderstanding. message:received and message:sent are already
in upstream (f07bb8e8) and are not duplicated here.
Typed contexts (MessageTranscribedHookContext, MessagePreprocessedHookContext)
and type guards (isMessageTranscribedEvent, isMessagePreprocessedEvent) added
to internal-hooks.ts alongside the existing received/sent types.
Test coverage in src/hooks/message-hooks.test.ts.
This commit is contained in:
committed by
Peter Steinberger
parent
44183c6eb1
commit
e0b8b80067
@@ -9,6 +9,8 @@ import { resolveAgentTimeoutMs } from "../../agents/timeout.js";
|
||||
import { DEFAULT_AGENT_WORKSPACE_DIR, ensureAgentWorkspace } from "../../agents/workspace.js";
|
||||
import { resolveChannelModelOverride } from "../../channels/model-overrides.js";
|
||||
import { type OpenClawConfig, loadConfig } from "../../config/config.js";
|
||||
import { logVerbose } from "../../globals.js";
|
||||
import { createInternalHookEvent, triggerInternalHook } from "../../hooks/internal-hooks.js";
|
||||
import { applyLinkUnderstanding } from "../../link-understanding/apply.js";
|
||||
import { applyMediaUnderstanding } from "../../media-understanding/apply.js";
|
||||
import { defaultRuntime } from "../../runtime.js";
|
||||
@@ -136,6 +138,73 @@ export async function getReplyFromConfig(
|
||||
});
|
||||
}
|
||||
|
||||
const channelId = (
|
||||
finalized.OriginatingChannel ??
|
||||
finalized.Surface ??
|
||||
finalized.Provider ??
|
||||
""
|
||||
).toLowerCase();
|
||||
|
||||
// Trigger message:transcribed hook after media understanding completes
|
||||
// Only fire if transcription actually occurred (skip in fast test mode or non-audio)
|
||||
if (finalized.Transcript) {
|
||||
void triggerInternalHook(
|
||||
createInternalHookEvent("message", "transcribed", finalized.SessionKey ?? "", {
|
||||
from: finalized.From,
|
||||
to: finalized.To,
|
||||
body: finalized.Body,
|
||||
bodyForAgent: finalized.BodyForAgent,
|
||||
transcript: finalized.Transcript,
|
||||
timestamp: finalized.Timestamp,
|
||||
channelId,
|
||||
conversationId: finalized.OriginatingTo ?? finalized.To ?? finalized.From ?? undefined,
|
||||
messageId: finalized.MessageSid,
|
||||
senderId: finalized.SenderId,
|
||||
senderName: finalized.SenderName,
|
||||
senderUsername: finalized.SenderUsername,
|
||||
provider: finalized.Provider,
|
||||
surface: finalized.Surface,
|
||||
mediaPath: finalized.MediaPath,
|
||||
mediaType: finalized.MediaType,
|
||||
cfg,
|
||||
}),
|
||||
).catch((err) => {
|
||||
logVerbose(`get-reply: message:transcribed internal hook failed: ${String(err)}`);
|
||||
});
|
||||
}
|
||||
|
||||
// Trigger message:preprocessed hook after all media + link understanding.
|
||||
// Fires for every message, giving hooks access to the fully enriched body
|
||||
// (transcripts, image descriptions, link summaries) before the agent sees it.
|
||||
void triggerInternalHook(
|
||||
createInternalHookEvent("message", "preprocessed", finalized.SessionKey ?? "", {
|
||||
from: finalized.From,
|
||||
to: finalized.To,
|
||||
body: finalized.Body,
|
||||
bodyForAgent: finalized.BodyForAgent,
|
||||
transcript: finalized.Transcript,
|
||||
timestamp: finalized.Timestamp,
|
||||
channelId,
|
||||
conversationId: finalized.OriginatingTo ?? finalized.To ?? finalized.From ?? undefined,
|
||||
messageId: finalized.MessageSid,
|
||||
senderId: finalized.SenderId,
|
||||
senderName: finalized.SenderName,
|
||||
senderUsername: finalized.SenderUsername,
|
||||
provider: finalized.Provider,
|
||||
surface: finalized.Surface,
|
||||
mediaPath: finalized.MediaPath,
|
||||
mediaType: finalized.MediaType,
|
||||
isGroup: Boolean(finalized.GroupSubject || finalized.GroupChannel),
|
||||
groupId:
|
||||
finalized.From?.includes(":group:") || finalized.From?.includes(":channel:")
|
||||
? finalized.From
|
||||
: undefined,
|
||||
cfg,
|
||||
}),
|
||||
).catch((err) => {
|
||||
logVerbose(`get-reply: message:preprocessed internal hook failed: ${String(err)}`);
|
||||
});
|
||||
|
||||
const commandAuthorized = finalized.CommandAuthorized;
|
||||
resolveCommandAuthorization({
|
||||
ctx: finalized,
|
||||
|
||||
Reference in New Issue
Block a user