@cored-im/openclaw-plugin 0.1.10 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,6 @@ import { describe, it, expect, beforeEach, vi } from "vitest";
5
5
  import {
6
6
  parseMessageEvent,
7
7
  checkMessageGate,
8
- isBotMentioned,
9
8
  isDuplicate,
10
9
  _resetDedup,
11
10
  buildContext,
@@ -26,15 +25,12 @@ function makeAccount(
26
25
  ): CoredAccountConfig {
27
26
  return {
28
27
  accountId: "test-account",
29
- enabled: true,
30
28
  appId: "app_test",
31
29
  appSecret: "secret",
32
30
  backendUrl: "https://your-backend-url.com",
31
+ enabled: true,
33
32
  enableEncryption: true,
34
33
  requestTimeout: 30_000,
35
- requireMention: true,
36
- botUserId: "bot_user_001",
37
- inboundWhitelist: [],
38
34
  ...overrides,
39
35
  };
40
36
  }
@@ -197,112 +193,11 @@ describe("parseMessageEvent", () => {
197
193
  describe("checkMessageGate", () => {
198
194
  it("passes a normal direct message", () => {
199
195
  const msg = parseMessageEvent(makeEvent())!;
200
- const account = makeAccount({ requireMention: false });
201
- const result = checkMessageGate(msg, account);
202
- expect(result.pass).toBe(true);
203
- });
204
-
205
- it("blocks self-messages", () => {
206
- const event = makeEvent({
207
- sender: { userId: "bot_user_001" },
208
- });
209
- const msg = parseMessageEvent(event)!;
210
196
  const account = makeAccount();
211
197
  const result = checkMessageGate(msg, account);
212
- expect(result.pass).toBe(false);
213
- expect(result.reason).toBe("self-message");
214
- });
215
-
216
- it("blocks sender not in whitelist when whitelist is set", () => {
217
- const msg = parseMessageEvent(makeEvent())!;
218
- const account = makeAccount({
219
- inboundWhitelist: ["allowed_user"],
220
- });
221
- const result = checkMessageGate(msg, account);
222
- expect(result.pass).toBe(false);
223
- expect(result.reason).toBe("sender-not-in-whitelist");
224
- });
225
-
226
- it("passes sender in whitelist", () => {
227
- const msg = parseMessageEvent(makeEvent())!;
228
- const account = makeAccount({
229
- inboundWhitelist: ["user_sender_001"],
230
- requireMention: false,
231
- });
232
- const result = checkMessageGate(msg, account);
233
198
  expect(result.pass).toBe(true);
234
199
  });
235
200
 
236
- it("blocks group message without mention when requireMention is true", () => {
237
- const event = makeEvent({ chatType: "group" });
238
- const msg = parseMessageEvent(event)!;
239
- const account = makeAccount({ requireMention: true });
240
- const result = checkMessageGate(msg, account);
241
- expect(result.pass).toBe(false);
242
- expect(result.reason).toBe("group-no-mention");
243
- });
244
-
245
- it("passes group message with mention", () => {
246
- const event = makeEvent({
247
- chatType: "group",
248
- mentionUserList: [{ userId: "bot_user_001" }],
249
- });
250
- const msg = parseMessageEvent(event)!;
251
- const account = makeAccount({ requireMention: true });
252
- const result = checkMessageGate(msg, account);
253
- expect(result.pass).toBe(true);
254
- });
255
-
256
- it("passes group message when requireMention is false", () => {
257
- const event = makeEvent({ chatType: "group" });
258
- const msg = parseMessageEvent(event)!;
259
- const account = makeAccount({ requireMention: false });
260
- const result = checkMessageGate(msg, account);
261
- expect(result.pass).toBe(true);
262
- });
263
-
264
- it("skips self-message check when botUserId is not set", () => {
265
- const event = makeEvent({
266
- sender: { userId: "any_user" },
267
- });
268
- const msg = parseMessageEvent(event)!;
269
- const account = makeAccount({ botUserId: undefined });
270
- const result = checkMessageGate(msg, account);
271
- expect(result.pass).toBe(true);
272
- });
273
- });
274
-
275
- // ---------------------------------------------------------------------------
276
- // isBotMentioned
277
- // ---------------------------------------------------------------------------
278
-
279
- describe("isBotMentioned", () => {
280
- it("returns true when bot is in mentionUserIds", () => {
281
- const event = makeEvent({
282
- mentionUserList: [{ userId: "bot_user_001" }],
283
- });
284
- const msg = parseMessageEvent(event)!;
285
- const account = makeAccount();
286
- expect(isBotMentioned(msg, account)).toBe(true);
287
- });
288
-
289
- it("returns false when bot is not mentioned", () => {
290
- const event = makeEvent({
291
- mentionUserList: [{ userId: "other_user" }],
292
- });
293
- const msg = parseMessageEvent(event)!;
294
- const account = makeAccount();
295
- expect(isBotMentioned(msg, account)).toBe(false);
296
- });
297
-
298
- it("returns false when botUserId is not set", () => {
299
- const event = makeEvent({
300
- mentionUserList: [{ userId: "bot_user_001" }],
301
- });
302
- const msg = parseMessageEvent(event)!;
303
- const account = makeAccount({ botUserId: undefined });
304
- expect(isBotMentioned(msg, account)).toBe(false);
305
- });
306
201
  });
307
202
 
308
203
  // ---------------------------------------------------------------------------
@@ -348,7 +243,7 @@ describe("buildContext", () => {
348
243
  expect(ctx.AccountId).toBe("test-account");
349
244
  expect(ctx.Body).toBe("hello world");
350
245
  expect(ctx.From).toBe("cored:user:user_sender_001");
351
- expect(ctx.To).toBe("cored:bot:bot_user_001");
246
+ expect(ctx.To).toBe("cored:bot:app_test");
352
247
  expect(ctx.SessionKey).toBe("cored:user:user_sender_001");
353
248
  expect(ctx.CommandAuthorized).toBe(true);
354
249
  expect(ctx._cored.isGroup).toBe(false);
@@ -367,12 +262,6 @@ describe("buildContext", () => {
367
262
  expect(ctx._cored.chatId).toBe("chat_group_1");
368
263
  });
369
264
 
370
- it("falls back to appId when botUserId is not set", () => {
371
- const msg = parseMessageEvent(makeEvent())!;
372
- const account = makeAccount({ botUserId: undefined });
373
- const ctx = buildContext(msg, account);
374
- expect(ctx.To).toBe("cored:bot:app_test");
375
- });
376
265
  });
377
266
 
378
267
  // ---------------------------------------------------------------------------
@@ -386,7 +275,7 @@ describe("processInboundMessage", () => {
386
275
 
387
276
  it("dispatches a valid direct message", async () => {
388
277
  const api = makeMockApi();
389
- const account = makeAccount({ requireMention: false });
278
+ const account = makeAccount();
390
279
  const event = makeEvent();
391
280
  const deliver = vi.fn().mockResolvedValue(undefined);
392
281
 
@@ -397,21 +286,9 @@ describe("processInboundMessage", () => {
397
286
  expect(api.runtime.channel.session.recordInboundSession).toHaveBeenCalledOnce();
398
287
  });
399
288
 
400
- it("filters self-messages", async () => {
401
- const api = makeMockApi();
402
- const account = makeAccount();
403
- const event = makeEvent({ sender: { userId: "bot_user_001" } });
404
- const deliver = vi.fn();
405
-
406
- const result = await processInboundMessage(api, account, event, { deliver });
407
-
408
- expect(result).toBe(false);
409
- expect(api.runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher).not.toHaveBeenCalled();
410
- });
411
-
412
289
  it("filters duplicate messages", async () => {
413
290
  const api = makeMockApi();
414
- const account = makeAccount({ requireMention: false });
291
+ const account = makeAccount();
415
292
  const msgId = "msg_dedup_test";
416
293
  const event = makeEvent({ messageId: msgId });
417
294
  const deliver = vi.fn();
@@ -423,31 +300,6 @@ describe("processInboundMessage", () => {
423
300
  expect(second).toBe(false);
424
301
  });
425
302
 
426
- it("filters group messages without mention when required", async () => {
427
- const api = makeMockApi();
428
- const account = makeAccount({ requireMention: true });
429
- const event = makeEvent({ chatType: "group" });
430
- const deliver = vi.fn();
431
-
432
- const result = await processInboundMessage(api, account, event, { deliver });
433
-
434
- expect(result).toBe(false);
435
- });
436
-
437
- it("dispatches group message with mention", async () => {
438
- const api = makeMockApi();
439
- const account = makeAccount({ requireMention: true });
440
- const event = makeEvent({
441
- chatType: "group",
442
- mentionUserList: [{ userId: "bot_user_001" }],
443
- });
444
- const deliver = vi.fn().mockResolvedValue(undefined);
445
-
446
- const result = await processInboundMessage(api, account, event, { deliver });
447
-
448
- expect(result).toBe(true);
449
- });
450
-
451
303
  it("returns false for unparseable event", async () => {
452
304
  const api = makeMockApi();
453
305
  const account = makeAccount();
@@ -463,7 +315,7 @@ describe("processInboundMessage", () => {
463
315
  const api = makeMockApi();
464
316
  // Remove dispatch function
465
317
  (api.runtime.channel.reply as Record<string, unknown>).dispatchReplyWithBufferedBlockDispatcher = undefined;
466
- const account = makeAccount({ requireMention: false });
318
+ const account = makeAccount();
467
319
  const event = makeEvent();
468
320
  const deliver = vi.fn();
469
321
 
@@ -482,7 +334,7 @@ describe("processInboundMessage", () => {
482
334
  });
483
335
  api.runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher = mockDispatch;
484
336
 
485
- const account = makeAccount({ requireMention: false });
337
+ const account = makeAccount();
486
338
  const event = makeEvent({ chatId: "chat_deliver_test" });
487
339
  const deliver = vi.fn().mockResolvedValue(undefined);
488
340
 
@@ -500,7 +352,7 @@ describe("processInboundMessage", () => {
500
352
  });
501
353
  api.runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher = mockDispatch;
502
354
 
503
- const account = makeAccount({ requireMention: false });
355
+ const account = makeAccount();
504
356
  const event = makeEvent();
505
357
  const deliver = vi.fn();
506
358
 
@@ -511,7 +363,7 @@ describe("processInboundMessage", () => {
511
363
 
512
364
  it("records session with updateLastRoute for DM", async () => {
513
365
  const api = makeMockApi();
514
- const account = makeAccount({ requireMention: false });
366
+ const account = makeAccount();
515
367
  const event = makeEvent({ chatId: "chat_dm_001" });
516
368
  const deliver = vi.fn().mockResolvedValue(undefined);
517
369
 
@@ -528,7 +380,7 @@ describe("processInboundMessage", () => {
528
380
 
529
381
  it("does not set updateLastRoute for group messages", async () => {
530
382
  const api = makeMockApi();
531
- const account = makeAccount({ requireMention: false });
383
+ const account = makeAccount();
532
384
  const event = makeEvent({ chatType: "group" });
533
385
  const deliver = vi.fn().mockResolvedValue(undefined);
534
386
 
@@ -547,7 +399,7 @@ describe("processInboundMessage", () => {
547
399
  });
548
400
  api.runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher = mockDispatch;
549
401
 
550
- const account = makeAccount({ requireMention: false });
402
+ const account = makeAccount();
551
403
  const event = makeEvent();
552
404
  const deliver = vi.fn();
553
405
 
@@ -151,41 +151,9 @@ export function checkMessageGate(
151
151
  msg: ParsedInboundMessage,
152
152
  account: CoredAccountConfig,
153
153
  ): GateResult {
154
- // 1. Self-message filter: ignore messages from the bot itself
155
- if (account.botUserId && msg.senderId === account.botUserId) {
156
- return { pass: false, reason: "self-message" };
157
- }
158
-
159
- // 2. Whitelist filter: if whitelist is non-empty, only allow listed senders
160
- if (account.inboundWhitelist.length > 0) {
161
- if (!account.inboundWhitelist.includes(msg.senderId)) {
162
- return { pass: false, reason: "sender-not-in-whitelist" };
163
- }
164
- }
165
-
166
- // 3. Group mention filter: in group chats, require @mention if configured
167
- if (
168
- msg.chatType === "group" &&
169
- account.requireMention &&
170
- !isBotMentioned(msg, account)
171
- ) {
172
- return { pass: false, reason: "group-no-mention" };
173
- }
174
-
175
154
  return { pass: true };
176
155
  }
177
156
 
178
- /**
179
- * Check if the bot was @mentioned in a message.
180
- */
181
- export function isBotMentioned(
182
- msg: ParsedInboundMessage,
183
- account: CoredAccountConfig,
184
- ): boolean {
185
- if (!account.botUserId) return false;
186
- return msg.mentionUserIds.includes(account.botUserId);
187
- }
188
-
189
157
  // ---------------------------------------------------------------------------
190
158
  // Dedup — skip already-processed message IDs
191
159
  // ---------------------------------------------------------------------------
@@ -279,7 +247,7 @@ export function buildContext(
279
247
  return {
280
248
  Body: msg.body,
281
249
  From: isGroup ? `cored:chat:${msg.chatId}` : `cored:user:${msg.senderId}`,
282
- To: `cored:bot:${account.botUserId ?? account.appId}`,
250
+ To: `cored:bot:${account.appId}`,
283
251
  SessionKey: sessionKey,
284
252
  AccountId: account.accountId,
285
253
  ChatType: isGroup ? "group" : "direct",
@@ -2,6 +2,6 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
5
- import { coredPlugin } from "./channel.js";
5
+ import { base } from "./channel.js";
6
6
 
7
- export default defineSetupPluginEntry(coredPlugin);
7
+ export default defineSetupPluginEntry(base);
package/src/types.ts CHANGED
@@ -5,39 +5,30 @@
5
5
 
6
6
  export interface CoredAccountConfig {
7
7
  accountId: string;
8
- enabled: boolean;
9
8
  appId: string;
10
9
  appSecret: string;
11
10
  backendUrl: string;
11
+ enabled: boolean;
12
12
  enableEncryption: boolean;
13
13
  requestTimeout: number;
14
- requireMention: boolean;
15
- botUserId?: string;
16
- inboundWhitelist: string[];
17
14
  }
18
15
 
19
16
  export interface CoredRawAccountConfig {
20
17
  appId?: string;
21
18
  appSecret?: string;
22
19
  backendUrl?: string;
20
+ enabled?: boolean;
23
21
  enableEncryption?: boolean;
24
22
  requestTimeout?: number;
25
- requireMention?: boolean;
26
- enabled?: boolean;
27
- botUserId?: string;
28
- inboundWhitelist?: string[];
29
23
  }
30
24
 
31
25
  export interface CoredChannelConfig {
32
26
  appId?: string;
33
27
  appSecret?: string;
34
28
  backendUrl?: string;
29
+ enabled?: boolean;
35
30
  enableEncryption?: boolean;
36
31
  requestTimeout?: number;
37
- requireMention?: boolean;
38
- enabled?: boolean;
39
- botUserId?: string;
40
- inboundWhitelist?: string[];
41
32
  accounts?: Record<string, CoredRawAccountConfig>;
42
33
  }
43
34