File size: 2,481 Bytes
fb4d8fe
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import { describe, expect, it, vi } from "vitest";
import type { SlackMonitorContext } from "../context.js";
import { prepareSlackMessage } from "./prepare.js";

describe("prepareSlackMessage sender prefix", () => {
  it("prefixes channel bodies with sender label", async () => {
    const ctx = {
      cfg: {
        agents: { defaults: { model: "anthropic/claude-opus-4-5", workspace: "/tmp/openclaw" } },
        channels: { slack: {} },
      },
      accountId: "default",
      botToken: "xoxb",
      app: { client: {} },
      runtime: {
        log: vi.fn(),
        error: vi.fn(),
        exit: (code: number): never => {
          throw new Error(`exit ${code}`);
        },
      },
      botUserId: "BOT",
      teamId: "T1",
      apiAppId: "A1",
      historyLimit: 0,
      channelHistories: new Map(),
      sessionScope: "per-sender",
      mainKey: "agent:main:main",
      dmEnabled: true,
      dmPolicy: "open",
      allowFrom: [],
      groupDmEnabled: false,
      groupDmChannels: [],
      defaultRequireMention: true,
      groupPolicy: "open",
      useAccessGroups: false,
      reactionMode: "off",
      reactionAllowlist: [],
      replyToMode: "off",
      threadHistoryScope: "channel",
      threadInheritParent: false,
      slashCommand: { command: "/openclaw", enabled: true },
      textLimit: 2000,
      ackReactionScope: "off",
      mediaMaxBytes: 1000,
      removeAckAfterReply: false,
      logger: { info: vi.fn() },
      markMessageSeen: () => false,
      shouldDropMismatchedSlackEvent: () => false,
      resolveSlackSystemEventSessionKey: () => "agent:main:slack:channel:c1",
      isChannelAllowed: () => true,
      resolveChannelName: async () => ({
        name: "general",
        type: "channel",
      }),
      resolveUserName: async () => ({ name: "Alice" }),
      setSlackThreadStatus: async () => undefined,
    } satisfies SlackMonitorContext;

    const result = await prepareSlackMessage({
      ctx,
      account: { accountId: "default", config: {} } as never,
      message: {
        type: "message",
        channel: "C1",
        channel_type: "channel",
        text: "<@BOT> hello",
        user: "U1",
        ts: "1700000000.0001",
        event_ts: "1700000000.0001",
      } as never,
      opts: { source: "message", wasMentioned: true },
    });

    expect(result).not.toBeNull();
    const body = result?.ctxPayload.Body ?? "";
    expect(body).toContain("Alice (U1): <@BOT> hello");
  });
});