fix(whatsapp): harden Baileys media upload hotfix#65966
Conversation
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c6e065b660
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let result; | ||
| try { | ||
| - const stream = createReadStream(filePath); | ||
| + const body = await fs.readFile(filePath); |
There was a problem hiding this comment.
Keep media upload streaming instead of full-buffer reads
Replacing createReadStream(filePath) with await fs.readFile(filePath) forces every media upload to hold the entire encrypted payload in memory before the request is sent. For large WhatsApp documents/videos (or multiple concurrent sends), this can spike RSS by payload size per upload and trigger OOM/restarts in production, which is a regression from the previous streaming behavior.
Useful? React with 👍 / 👎.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c6e065b660
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| - const stream = createReadStream(filePath); | ||
| + const body = await fs.readFile(filePath); | ||
| const response = await fetch(url, { | ||
| - dispatcher: fetchAgent, | ||
| method: 'POST', | ||
| - body: stream, | ||
| + body, |
There was a problem hiding this comment.
Keep media uploads streaming instead of buffering whole file
Replacing createReadStream(filePath) with await fs.readFile(filePath) forces every encrypted media upload to be fully materialized in memory before POSTing. For large WhatsApp documents/videos (and especially concurrent sends), this can create major RSS spikes, trigger GC/OOM failures, and drop uploads that previously worked with bounded memory via streaming; this is a runtime regression in the hot upload path rather than a cosmetic refactor.
Useful? React with 👍 / 👎.
|
@codex review |
|
Codex Review: Didn't find any major issues. More of your lovely PRs please. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
39c45e9 to
e13bdc5
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e13bdc5759
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const transitiveClosure = collectInstalledRuntimeClosure(rootNodeModulesDir, dependencySpecs); | ||
| if (transitiveClosure !== null) { | ||
| for (const depName of transitiveClosure) { | ||
| dependencyNames.add(depName); | ||
| } |
There was a problem hiding this comment.
Fall back to install when transitive closure lookup fails
When collectInstalledRuntimeClosure() returns null, this code now keeps staging with only direct dependencies instead of aborting root staging. That can produce incomplete dist/extensions/*/node_modules trees whenever a transitive package is missing/incompatible at the root (for example platform-optional transitives), because hoisted layouts often keep required transitives outside the direct package folder; copying only the direct package then leads to runtime MODULE_NOT_FOUND failures. The previous behavior (return false) correctly fell back to npm install for a complete closure.
Useful? React with 👍 / 👎.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b35564b436
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| "bundle": { | ||
| "stageRuntimeDependencies": true | ||
| }, |
There was a problem hiding this comment.
Remove duplicated
openclaw.bundle key
This adds a second openclaw.bundle object even though the same key already exists later in the same openclaw object. Duplicate keys in JSON are ambiguous (many parsers keep only the last occurrence), so a future edit to one block can be silently ignored and cause confusing staging behavior drift. Keep a single canonical bundle entry.
Useful? React with 👍 / 👎.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0a5ef08334
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| "patchedDependencies": { | ||
| "@whiskeysockets/baileys@7.0.0-rc.9": "patches/@whiskeysockets__baileys@7.0.0-rc.9.patch" |
There was a problem hiding this comment.
Ship Baileys dispatcher fix beyond pnpm-only patching
This change delivers the WhatsApp upload fix only through pnpm.patchedDependencies, but the shipped install path still installs bundled plugin deps with npm install (scripts/postinstall-bundled-plugins.mjs:423-438), where the only runtime rewrite is the encrypted-stream flush hotfix (scripts/postinstall-bundled-plugins.mjs:41-57). That means npm/global installs can still run unpatched Baileys upload code and hit TypeError: agent.dispatch is not a function with non-Undici agents, so the dispatcher hardening in this commit is not actually applied in that environment.
Useful? React with 👍 / 👎.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 133cc52081
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (!patchedText.includes(BAILEYS_MEDIA_HOTFIX_REPLACEMENT)) { | ||
| if (!patchedText.includes(BAILEYS_MEDIA_HOTFIX_NEEDLE)) { | ||
| return { applied: false, reason: "unexpected_content" }; |
There was a problem hiding this comment.
Handle patched encrypted-stream variant before bailing out
The hotfix matcher now assumes only one “already patched” form (await Promise.all(...)), but this same commit adds a pnpm patch that uses the equivalent sequential awaits (await encFinishPromise; await originalFinishPromise;). In that valid patched state, this branch returns unexpected_content immediately, which causes source-checkout postinstall runs to warn on every install and prevents dispatcher-only patching for that file variant. Please accept the sequential-await form as patched (or continue to the dispatcher patch path) instead of returning early.
Useful? React with 👍 / 👎.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d5b9ff0150
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| patchedText.includes(BAILEYS_MEDIA_HOTFIX_REPLACEMENT) || | ||
| patchedText.includes(BAILEYS_MEDIA_HOTFIX_SEQUENTIAL_REPLACEMENT); | ||
|
|
||
| if (!encryptedStreamAlreadyPatched) { | ||
| if (!patchedText.includes(BAILEYS_MEDIA_HOTFIX_NEEDLE)) { |
There was a problem hiding this comment.
Treat commented sequential Baileys patch as already applied
This detection path relies on an exact multiline match for the sequential encrypted-stream replacement, then falls back to requiring the old unpatched needle. The new pnpm patch in this commit adds comment lines between those statements, so a file that is already patched via patches/@whiskeysockets__baileys@7.0.0-rc.9.patch does not match either form and returns unexpected_content. In source-checkout postinstall runs, that makes the hotfix non-idempotent (spurious warning every install) and can skip dispatcher backfill in mixed states where only the commented sequential variant is present.
Useful? React with 👍 / 👎.
|
@codex review |
|
@codex review |
04932d0 to
b5db59b
Compare
|
Merged via squash.
Thanks @frankekn! |
What changed
This PR adds a Baileys dependency patch for WhatsApp media sends.
encryptedStream()output streams to finish before returning the encrypted temp file pathfetchAgentobjects that do not implement Undici'sDispatcherinterfaceWhy
We hit two separate failures while sending XLSX documents over WhatsApp:
encryptedStream()could return before the encrypted temp file was fully flushed to disk, which led toENOENTraces on/tmp/document*-encAgentviadispatcher, which causedTypeError: agent.dispatch is not a functionTogether, these failures broke WhatsApp document sends and could take the gateway into repeated recovery / retry failure paths.
Impact
fetchAgentValidation
agent.dispatch is not a function200 OKmedia upload response and successful WhatsApp send@whiskeysockets/baileys@7.0.0-rc.9viapatch --dry-run