mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:30:42 +00:00
fix(qa): restore release channel reply checks
This commit is contained in:
9
extensions/qa-channel/setup-entry.test.ts
Normal file
9
extensions/qa-channel/setup-entry.test.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import setupEntry from "./setup-entry.js";
|
||||
|
||||
describe("qa-channel setup entry", () => {
|
||||
it("exposes the bundled setup-entry contract", () => {
|
||||
expect(setupEntry.kind).toBe("bundled-channel-setup-entry");
|
||||
expect(setupEntry.loadSetupPlugin().id).toBe("qa-channel");
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,13 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { qaChannelPlugin } from "./src/channel.js";
|
||||
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export default defineSetupPluginEntry(qaChannelPlugin);
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./channel-plugin-api.js",
|
||||
exportName: "qaChannelPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./api.js",
|
||||
exportName: "setQaChannelRuntime",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { isHttpMediaUrl } from "./inbound.js";
|
||||
import { createPluginRuntimeMock } from "openclaw/plugin-sdk/channel-test-helpers";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { setQaChannelRuntime } from "../api.js";
|
||||
import { handleQaInbound, isHttpMediaUrl } from "./inbound.js";
|
||||
|
||||
const dispatchInboundReplyWithBaseMock = vi.hoisted(() => vi.fn());
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/inbound-reply-dispatch", () => ({
|
||||
dispatchInboundReplyWithBase: dispatchInboundReplyWithBaseMock,
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
dispatchInboundReplyWithBaseMock.mockReset();
|
||||
});
|
||||
|
||||
describe("isHttpMediaUrl", () => {
|
||||
it("accepts only http and https urls", () => {
|
||||
@@ -10,3 +22,45 @@ describe("isHttpMediaUrl", () => {
|
||||
expect(isHttpMediaUrl("data:text/plain;base64,SGVsbG8=")).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("handleQaInbound", () => {
|
||||
it("marks group messages that match configured mention patterns", async () => {
|
||||
const runtime = createPluginRuntimeMock();
|
||||
vi.mocked(runtime.channel.mentions.buildMentionRegexes).mockReturnValue([/\b@?openclaw\b/i]);
|
||||
setQaChannelRuntime(runtime);
|
||||
|
||||
await handleQaInbound({
|
||||
channelId: "qa-channel",
|
||||
channelLabel: "QA Channel",
|
||||
account: {
|
||||
accountId: "default",
|
||||
enabled: true,
|
||||
configured: true,
|
||||
baseUrl: "http://127.0.0.1:43123",
|
||||
botUserId: "openclaw",
|
||||
botDisplayName: "OpenClaw QA",
|
||||
pollTimeoutMs: 250,
|
||||
config: {},
|
||||
},
|
||||
config: {},
|
||||
message: {
|
||||
id: "msg-1",
|
||||
accountId: "default",
|
||||
direction: "inbound",
|
||||
conversation: {
|
||||
kind: "channel",
|
||||
id: "qa-room",
|
||||
title: "QA Room",
|
||||
},
|
||||
senderId: "alice",
|
||||
senderName: "Alice",
|
||||
text: "@openclaw ping",
|
||||
timestamp: 1_777_000_000_000,
|
||||
reactions: [],
|
||||
},
|
||||
});
|
||||
|
||||
expect(dispatchInboundReplyWithBaseMock).toHaveBeenCalledTimes(1);
|
||||
expect(dispatchInboundReplyWithBaseMock.mock.calls[0]?.[0].ctxPayload.WasMentioned).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -81,6 +81,16 @@ export async function handleQaInbound(params: {
|
||||
id: target,
|
||||
},
|
||||
});
|
||||
const isGroup = inbound.conversation.kind !== "direct";
|
||||
const wasMentioned = isGroup
|
||||
? runtime.channel.mentions.matchesMentionPatterns(
|
||||
inbound.text,
|
||||
runtime.channel.mentions.buildMentionRegexes(
|
||||
params.config as OpenClawConfig,
|
||||
route.agentId,
|
||||
),
|
||||
)
|
||||
: undefined;
|
||||
const storePath = runtime.channel.session.resolveStorePath(params.config.session?.store, {
|
||||
agentId: route.agentId,
|
||||
});
|
||||
@@ -111,6 +121,7 @@ export async function handleQaInbound(params: {
|
||||
SessionKey: route.sessionKey,
|
||||
AccountId: route.accountId ?? params.account.accountId,
|
||||
ChatType: inbound.conversation.kind === "direct" ? "direct" : "group",
|
||||
WasMentioned: wasMentioned,
|
||||
ConversationLabel:
|
||||
inbound.threadTitle ||
|
||||
inbound.conversation.title ||
|
||||
|
||||
@@ -134,6 +134,7 @@ describe("discord live qa runtime", () => {
|
||||
|
||||
expect(next.plugins?.allow).toContain("discord");
|
||||
expect(next.plugins?.entries?.discord).toEqual({ enabled: true });
|
||||
expect(next.messages?.groupChat?.visibleReplies).toBe("automatic");
|
||||
expect(next.channels?.discord).toEqual({
|
||||
enabled: true,
|
||||
defaultAccount: "sut",
|
||||
|
||||
@@ -287,6 +287,13 @@ function buildDiscordQaConfig(
|
||||
allow: pluginAllow,
|
||||
entries: pluginEntries,
|
||||
},
|
||||
messages: {
|
||||
...baseCfg.messages,
|
||||
groupChat: {
|
||||
...baseCfg.messages?.groupChat,
|
||||
visibleReplies: "automatic",
|
||||
},
|
||||
},
|
||||
channels: {
|
||||
...baseCfg.channels,
|
||||
discord: {
|
||||
|
||||
@@ -165,6 +165,7 @@ describe("telegram live qa runtime", () => {
|
||||
expect(next.agents?.defaults?.skipBootstrap).toBe(true);
|
||||
expect(next.plugins?.allow).toContain("telegram");
|
||||
expect(next.plugins?.entries?.telegram).toEqual({ enabled: true });
|
||||
expect(next.messages?.groupChat?.visibleReplies).toBe("automatic");
|
||||
expect(next.channels?.telegram).toEqual({
|
||||
enabled: true,
|
||||
defaultAccount: "sut",
|
||||
|
||||
@@ -486,6 +486,13 @@ function buildTelegramQaConfig(
|
||||
allow: pluginAllow,
|
||||
entries: pluginEntries,
|
||||
},
|
||||
messages: {
|
||||
...baseCfg.messages,
|
||||
groupChat: {
|
||||
...baseCfg.messages?.groupChat,
|
||||
visibleReplies: "automatic",
|
||||
},
|
||||
},
|
||||
channels: {
|
||||
...baseCfg.channels,
|
||||
telegram: {
|
||||
|
||||
@@ -24,6 +24,7 @@ describe("qa channel transport", () => {
|
||||
messages: {
|
||||
groupChat: {
|
||||
mentionPatterns: ["\\b@?openclaw\\b"],
|
||||
visibleReplies: "automatic",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -90,6 +90,7 @@ export function createQaChannelGatewayConfig(params: {
|
||||
messages: {
|
||||
groupChat: {
|
||||
mentionPatterns: ["\\b@?openclaw\\b"],
|
||||
visibleReplies: "automatic",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -23,6 +23,7 @@ function createQaChannelTransportParams(baseUrl = "http://127.0.0.1:43124") {
|
||||
messages: {
|
||||
groupChat: {
|
||||
mentionPatterns: ["\\b@?openclaw\\b"],
|
||||
visibleReplies: "automatic",
|
||||
},
|
||||
},
|
||||
} satisfies QaTransportGatewayConfig,
|
||||
@@ -77,7 +78,10 @@ describe("buildQaGatewayConfig", () => {
|
||||
baseUrl: "http://127.0.0.1:43124",
|
||||
pollTimeoutMs: 250,
|
||||
});
|
||||
expect(cfg.messages?.groupChat?.mentionPatterns).toEqual(["\\b@?openclaw\\b"]);
|
||||
expect(cfg.messages?.groupChat).toMatchObject({
|
||||
mentionPatterns: ["\\b@?openclaw\\b"],
|
||||
visibleReplies: "automatic",
|
||||
});
|
||||
});
|
||||
|
||||
it("maps provider-qualified openai and anthropic refs through the mock provider lane", () => {
|
||||
|
||||
@@ -148,6 +148,7 @@ describe("matrix live qa runtime", () => {
|
||||
|
||||
expect(next.plugins?.allow).toContain("matrix");
|
||||
expect(next.plugins?.entries?.matrix).toEqual({ enabled: true });
|
||||
expect(next.messages?.groupChat?.visibleReplies).toBe("automatic");
|
||||
expect(next.channels?.matrix).toEqual({
|
||||
enabled: true,
|
||||
defaultAccount: "sut",
|
||||
|
||||
@@ -76,6 +76,7 @@ describe("matrix qa config", () => {
|
||||
replyToMode: "off",
|
||||
threadReplies: "inbound",
|
||||
});
|
||||
expect(next.messages?.groupChat?.visibleReplies).toBe("automatic");
|
||||
});
|
||||
|
||||
it("applies room-keyed Matrix QA config overrides", () => {
|
||||
|
||||
@@ -640,6 +640,13 @@ export function buildMatrixQaConfig(
|
||||
matrix: { enabled: true },
|
||||
},
|
||||
},
|
||||
messages: {
|
||||
...baseCfg.messages,
|
||||
groupChat: {
|
||||
...baseCfg.messages?.groupChat,
|
||||
visibleReplies: "automatic",
|
||||
},
|
||||
},
|
||||
channels: {
|
||||
...baseCfg.channels,
|
||||
matrix: {
|
||||
|
||||
Reference in New Issue
Block a user