mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-28 05:16:23 -06:00
fix(matrix): suppress previews for modifying hooks
This commit is contained in:
@@ -53,6 +53,15 @@ const resolveMatrixMentionsForBodyMock = vi.hoisted(() =>
|
||||
};
|
||||
}),
|
||||
);
|
||||
const getGlobalHookRunnerMock = vi.hoisted(() => vi.fn());
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/plugin-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/plugin-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
getGlobalHookRunner: getGlobalHookRunnerMock,
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../send.js", () => ({
|
||||
editMessageMatrix: editMessageMatrixMock,
|
||||
@@ -116,6 +125,7 @@ async function writeMatrixSessionMeta(
|
||||
beforeEach(() => {
|
||||
sessionBindingTesting.resetSessionBindingAdaptersForTests();
|
||||
installMatrixMonitorTestRuntime();
|
||||
getGlobalHookRunnerMock.mockReset().mockReturnValue(null);
|
||||
prepareMatrixSingleTextMock.mockReset().mockImplementation((text: string) => {
|
||||
const trimmedText = text.trim();
|
||||
return {
|
||||
@@ -2988,6 +2998,53 @@ describe("matrix monitor handler draft streaming", () => {
|
||||
await finish();
|
||||
});
|
||||
|
||||
it("preserves provider previews for observer-only hooks", async () => {
|
||||
getGlobalHookRunnerMock.mockReturnValue({
|
||||
hasHooks: vi.fn((hookName: string) => hookName === "message_sent"),
|
||||
});
|
||||
const { dispatch } = createStreamingHarness({ streaming: "partial" });
|
||||
const { deliver, opts, finish } = await dispatch();
|
||||
|
||||
opts.onPartialReply?.({ text: "Visible preview" });
|
||||
await waitForMatrixState(() => {
|
||||
expect(sendSingleTextMessageMatrixMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
await deliver({ text: "Visible preview" }, { kind: "final" });
|
||||
|
||||
expectEditLiveFlag("$draft1", "Visible preview", false);
|
||||
expect(deliverMatrixRepliesMock).not.toHaveBeenCalled();
|
||||
await finish();
|
||||
});
|
||||
|
||||
it.each([
|
||||
{ label: "reply_payload_sending", hooks: ["reply_payload_sending"] },
|
||||
{ label: "message_sending", hooks: ["message_sending"] },
|
||||
{
|
||||
label: "both modifying hooks",
|
||||
hooks: ["reply_payload_sending", "message_sending"],
|
||||
},
|
||||
])("suppresses provider previews when $label is registered", async ({ hooks }) => {
|
||||
const registered = new Set(hooks);
|
||||
getGlobalHookRunnerMock.mockReturnValue({
|
||||
hasHooks: vi.fn((hookName: string) => registered.has(hookName)),
|
||||
});
|
||||
const { dispatch } = createStreamingHarness({
|
||||
previewToolProgressEnabled: true,
|
||||
streaming: "progress",
|
||||
});
|
||||
const { deliver, opts, finish } = await dispatch();
|
||||
|
||||
expect(opts.onPartialReply).toBeUndefined();
|
||||
expect(opts.onToolStart).toBeUndefined();
|
||||
expect(opts.suppressDefaultToolProgressMessages).toBeUndefined();
|
||||
await deliver({ text: "Durable final" }, { kind: "final" });
|
||||
|
||||
expect(sendSingleTextMessageMatrixMock).not.toHaveBeenCalled();
|
||||
expect(editMessageMatrixMock).not.toHaveBeenCalled();
|
||||
expect(deliverMatrixRepliesMock).toHaveBeenCalledTimes(1);
|
||||
await finish();
|
||||
});
|
||||
|
||||
it("streams tool progress into the Matrix draft preview when enabled", async () => {
|
||||
const { dispatch, redactEventMock } = createStreamingHarness({
|
||||
previewToolProgressEnabled: true,
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
} from "openclaw/plugin-sdk/channel-inbound";
|
||||
import { resolveChannelContextVisibilityMode } from "openclaw/plugin-sdk/context-visibility-runtime";
|
||||
import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
|
||||
import { getGlobalHookRunner } from "openclaw/plugin-sdk/plugin-runtime";
|
||||
import { resolveInboundLastRouteSessionKey } from "openclaw/plugin-sdk/routing";
|
||||
import { resolvePinnedMainDmOwnerFromAllowlist } from "openclaw/plugin-sdk/security-runtime";
|
||||
import { resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
|
||||
@@ -388,9 +389,16 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
|
||||
});
|
||||
},
|
||||
});
|
||||
// Matrix drafts are provider-visible before outbound modifiers run. Keep them off when a
|
||||
// hook can rewrite or cancel so the original payload cannot escape the delivery gate.
|
||||
const hookRunner = getGlobalHookRunner();
|
||||
const allowProviderPreview = !(
|
||||
(hookRunner?.hasHooks("reply_payload_sending") ?? false) ||
|
||||
(hookRunner?.hasHooks("message_sending") ?? false)
|
||||
);
|
||||
const draftController = await createMatrixDraftController({
|
||||
streaming,
|
||||
previewToolProgressEnabled,
|
||||
streaming: allowProviderPreview ? streaming : "off",
|
||||
previewToolProgressEnabled: allowProviderPreview && previewToolProgressEnabled,
|
||||
replyToMode,
|
||||
messageId,
|
||||
threadTarget,
|
||||
|
||||
Reference in New Issue
Block a user