fix: preserve slack hook alert content

This commit is contained in:
amsminn
2026-05-02 14:38:07 +09:00
committed by Peter Steinberger
parent d7ab2c4c41
commit 177fb7e84d
4 changed files with 39 additions and 9 deletions

View File

@@ -114,7 +114,7 @@ Each event includes: `type`, `action`, `sessionKey`, `timestamp`, `messages` (pu
**Command events** (`command:new`, `command:reset`): `context.sessionEntry`, `context.previousSessionEntry`, `context.commandSource`, `context.workspaceDir`, `context.cfg`.
**Message events** (`message:received`): `context.from`, `context.content`, `context.channelId`, `context.metadata` (provider-specific data including `senderId`, `senderName`, `guildId`).
**Message events** (`message:received`): `context.from`, `context.content`, `context.channelId`, `context.metadata` (provider-specific data including `senderId`, `senderName`, `guildId`). `context.content` prefers a nonblank command body for command-like messages, then falls back to the raw inbound body and generic body; it does not include agent-only enrichment such as thread history or link summaries.
**Message events** (`message:sent`): `context.to`, `context.content`, `context.success`, `context.channelId`.

View File

@@ -536,7 +536,7 @@ describe("slack prepareSlackMessage inbound contract", () => {
subtype: "bot_message",
attachments: [
{
text: "Readiness probe failed: Get http://10.42.13.132:8000/status: context deadline exceeded",
text: "Readiness probe failed: Get https://status.example.test/readiness: context deadline exceeded",
},
],
});
@@ -545,6 +545,11 @@ describe("slack prepareSlackMessage inbound contract", () => {
expect(prepared).toBeTruthy();
expect(prepared!.ctxPayload.RawBody).toContain("Readiness probe failed");
// Slack message attachments can carry the user-visible body even when the
// top-level message text is empty.
expect(prepared!.ctxPayload.CommandBody).toBe("");
expect(prepared!.ctxPayload.BodyForCommands).toBe("");
expect(prepared!.ctxPayload.BodyForAgent).toContain("Readiness probe failed");
});
it("drops bot-authored room messages when allowBots is true but no owner is present (#59284)", async () => {

View File

@@ -97,6 +97,30 @@ describe("message hook mappers", () => {
expect(canonical.guildId).toBe("guild-1");
});
it("falls back to raw body when command body is blank", () => {
const canonical = deriveInboundMessageHookContext(
makeInboundCtx({
BodyForCommands: " \n\t",
RawBody: "Readiness probe failed",
}),
);
expect(canonical.content).toBe("Readiness probe failed");
expect(toPluginMessageReceivedEvent(canonical).content).toBe("Readiness probe failed");
expect(toInternalMessageReceivedContext(canonical).content).toBe("Readiness probe failed");
});
it("keeps nonblank command body ahead of raw body for hook content", () => {
const canonical = deriveInboundMessageHookContext(
makeInboundCtx({
BodyForCommands: "/status",
RawBody: "Readiness probe failed",
}),
);
expect(canonical.content).toBe("/status");
});
it("supports explicit content/messageId overrides", () => {
const canonical = deriveInboundMessageHookContext(makeInboundCtx(), {
content: "override-content",

View File

@@ -80,6 +80,10 @@ export type CanonicalSentMessageHookContext = {
groupId?: string;
};
function readNonBlankString(value: unknown): string | undefined {
return typeof value === "string" && value.trim().length > 0 ? value : undefined;
}
export function deriveInboundMessageHookContext(
ctx: FinalizedMsgContext,
overrides?: {
@@ -89,13 +93,10 @@ export function deriveInboundMessageHookContext(
): CanonicalInboundMessageHookContext {
const content =
overrides?.content ??
(typeof ctx.BodyForCommands === "string"
? ctx.BodyForCommands
: typeof ctx.RawBody === "string"
? ctx.RawBody
: typeof ctx.Body === "string"
? ctx.Body
: "");
readNonBlankString(ctx.BodyForCommands) ??
readNonBlankString(ctx.RawBody) ??
readNonBlankString(ctx.Body) ??
"";
const channelId = normalizeLowercaseStringOrEmpty(
ctx.OriginatingChannel ?? ctx.Surface ?? ctx.Provider ?? "",
);