




















@@ -26,6 +26,14 @@ function createMockQaRuntime(params?: {
2626const sessionUpdatedAt = new Map<string, number>();
2727return {
2828channel: {
29+mentions: {
30+buildMentionRegexes() {
31+return [/^@openclaw\b/i];
32+},
33+matchesMentionPatterns(text: string, patterns: RegExp[]) {
34+return patterns.some((pattern) => pattern.test(text));
35+},
36+},
2937routing: {
3038resolveAgentRoute({
3139 accountId,
@@ -142,6 +150,35 @@ describe("qa-channel plugin", () => {
142150expect(route?.threadId).toBeUndefined();
143151});
144152153+it("derives group outbound session routes from explicit group targets", async () => {
154+const route = await qaChannelPlugin.messaging?.resolveOutboundSessionRoute?.({
155+cfg: {},
156+agentId: "main",
157+accountId: "default",
158+target: "group:qa-room",
159+});
160+161+expect(route).toMatchObject({
162+sessionKey: "agent:main:qa-channel:group:group:qa-room",
163+baseSessionKey: "agent:main:qa-channel:group:group:qa-room",
164+chatType: "group",
165+to: "group:qa-room",
166+});
167+});
168+169+it("normalizes explicit group targets for session group policy lookup", () => {
170+const resolved = qaChannelPlugin.messaging?.resolveSessionConversation?.({
171+kind: "group",
172+rawId: "group:qa-room",
173+});
174+175+expect(resolved).toMatchObject({
176+id: "qa-room",
177+baseConversationId: "qa-room",
178+parentConversationCandidates: ["qa-room"],
179+});
180+});
181+145182it("recovers thread-aware outbound session routes from currentSessionKey", async () => {
146183const route = await qaChannelPlugin.messaging?.resolveOutboundSessionRoute?.({
147184cfg: {},
@@ -197,6 +234,53 @@ describe("qa-channel plugin", () => {
197234}
198235});
199236237+it(
238+"surfaces shared group traffic with the room target as From",
239+{ timeout: 20_000 },
240+async () => {
241+let dispatchedCtx: Record<string, unknown> | null = null;
242+const harness = await startQaChannelTestHarness({
243+allowFrom: ["*"],
244+runtime: createMockQaRuntime({
245+onDispatch: (ctx) => {
246+dispatchedCtx = ctx;
247+},
248+}),
249+});
250+251+try {
252+harness.state.addInboundMessage({
253+conversation: { id: "qa-room", kind: "group", title: "QA Room" },
254+senderId: "alice",
255+senderName: "Alice",
256+text: "@openclaw hello",
257+});
258+259+const outbound = await harness.state.waitFor({
260+kind: "message-text",
261+textIncludes: "qa-echo: @openclaw hello",
262+direction: "outbound",
263+timeoutMs: 15_000,
264+});
265+266+expect(dispatchedCtx).toMatchObject({
267+ChatType: "group",
268+From: "group:qa-room",
269+To: "group:qa-room",
270+SessionKey: "qa-agent:group:group:qa-room",
271+SenderId: "alice",
272+GroupSubject: "QA Room",
273+});
274+expect("conversation" in outbound && outbound.conversation).toMatchObject({
275+id: "qa-room",
276+kind: "group",
277+});
278+} finally {
279+await harness.stop();
280+}
281+},
282+);
283+200284it("stages inbound image attachments into agent media payload", { timeout: 20_000 }, async () => {
201285let dispatchedCtx: Record<string, unknown> | null = null;
202286const harness = await startQaChannelTestHarness({
@@ -396,4 +480,41 @@ describe("qa-channel plugin", () => {
396480await bus.stop();
397481}
398482});
483+484+it("routes group send targets to group qa bus conversations", async () => {
485+installQaChannelTestRegistry();
486+const state = createQaBusState();
487+const bus = await startQaBusServer({ state });
488+489+try {
490+const cfg = createQaChannelConfig({ baseUrl: bus.baseUrl });
491+492+const result = await qaChannelPlugin.actions?.handleAction?.({
493+channel: "qa-channel",
494+action: "send",
495+ cfg,
496+accountId: "default",
497+params: {
498+target: "group:qa-room",
499+message: "hello group",
500+},
501+});
502+const payload = extractToolPayload(result);
503+expect(payload).toMatchObject({ message: { text: "hello group" } });
504+505+const outbound = await state.waitFor({
506+kind: "message-text",
507+direction: "outbound",
508+textIncludes: "hello group",
509+timeoutMs: 5_000,
510+});
511+expect("conversation" in outbound).toBe(true);
512+if (!("conversation" in outbound)) {
513+throw new Error("expected outbound message match");
514+}
515+expect(outbound.conversation).toMatchObject({ id: "qa-room", kind: "group" });
516+} finally {
517+await bus.stop();
518+}
519+});
399520});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。