























@@ -4,6 +4,7 @@ import { tmpdir } from "node:os";
44import path from "node:path";
55import { describe, expect, it, vi } from "vitest";
66import {
7+applyBaileysEncryptedStreamFinishHotfix,
78collectLegacyPluginRuntimeDepsStateRoots,
89isSourceCheckoutRoot,
910isDirectPostinstallInvocation,
@@ -58,6 +59,21 @@ async function writePluginPackage(
5859}
5960}
606162+async function writeBaileysMediaFile(packageRoot: string, text: string) {
63+const mediaFile = path.join(
64+packageRoot,
65+"node_modules",
66+"@whiskeysockets",
67+"baileys",
68+"lib",
69+"Utils",
70+"messages-media.js",
71+);
72+await fs.mkdir(path.dirname(mediaFile), { recursive: true });
73+await fs.writeFile(mediaFile, text);
74+return mediaFile;
75+}
76+6177describe("bundled plugin postinstall", () => {
6278function existsSyncWithoutGlobalCompileCache(value: string) {
6379if (path.resolve(value) === path.join(tmpdir(), "node-compile-cache")) {
@@ -206,6 +222,83 @@ describe("bundled plugin postinstall", () => {
206222expect(warn).not.toHaveBeenCalled();
207223});
208224225+it("patches the Baileys rc10 upload helper dispatcher guard", async () => {
226+const packageRoot = await createTempDirAsync("openclaw-baileys-postinstall-");
227+const mediaFile = await writeBaileysMediaFile(
228+packageRoot,
229+[
230+"import { once } from 'events';",
231+"const encryptedStream = async () => {",
232+" encFileWriteStream.write(mac);",
233+" const encFinishPromise = once(encFileWriteStream, 'finish');",
234+" const originalFinishPromise = originalFileStream ? once(originalFileStream, 'finish') : Promise.resolve();",
235+" encFileWriteStream.end();",
236+" originalFileStream?.end?.();",
237+" stream.destroy();",
238+" await encFinishPromise;",
239+" await originalFinishPromise;",
240+" logger?.debug('encrypted data successfully');",
241+"};",
242+"const uploadWithFetch = async ({ url, filePath, headers, timeoutMs, agent }) => {",
243+" const nodeStream = createReadStream(filePath);",
244+" const webStream = Readable.toWeb(nodeStream);",
245+" const response = await fetch(url, {",
246+" dispatcher: agent,",
247+" method: 'POST',",
248+" body: webStream,",
249+" headers,",
250+" duplex: 'half',",
251+" signal: timeoutMs ? AbortSignal.timeout(timeoutMs) : undefined",
252+" });",
253+"};",
254+"",
255+].join("\n"),
256+);
257+258+expect(applyBaileysEncryptedStreamFinishHotfix({ packageRoot })).toMatchObject({
259+applied: true,
260+reason: "patched",
261+});
262+const patchedText = await fs.readFile(mediaFile, "utf8");
263+expect(patchedText).toContain(
264+"...(typeof agent?.dispatch === 'function' ? { dispatcher: agent } : {}),",
265+);
266+expect(patchedText).not.toContain(" dispatcher: agent,");
267+});
268+269+it("recognizes already patched Baileys rc10 upload helpers", async () => {
270+const packageRoot = await createTempDirAsync("openclaw-baileys-postinstall-");
271+await writeBaileysMediaFile(
272+packageRoot,
273+[
274+"import { once } from 'events';",
275+"const encryptedStream = async () => {",
276+" encFileWriteStream.write(mac);",
277+" const encFinishPromise = once(encFileWriteStream, 'finish');",
278+" const originalFinishPromise = originalFileStream ? once(originalFileStream, 'finish') : Promise.resolve();",
279+" encFileWriteStream.end();",
280+" originalFileStream?.end?.();",
281+" stream.destroy();",
282+" await encFinishPromise;",
283+" await originalFinishPromise;",
284+" logger?.debug('encrypted data successfully');",
285+"};",
286+"const uploadWithFetch = async ({ url, filePath, headers, timeoutMs, agent }) => {",
287+" const response = await fetch(url, {",
288+" ...(typeof agent?.dispatch === 'function' ? { dispatcher: agent } : {}),",
289+" method: 'POST',",
290+" });",
291+"};",
292+"",
293+].join("\n"),
294+);
295+296+expect(applyBaileysEncryptedStreamFinishHotfix({ packageRoot })).toMatchObject({
297+applied: false,
298+reason: "already_patched",
299+});
300+});
301+209302it("does not classify published packages with source files as source checkouts", () => {
210303const packageRoot = "/pkg";
211304const existingPaths = new Set([
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。