← Back to PRs

#20186: fix(discord): thread mediaLocalRoots through reply delivery path

by pvoo open 2026-02-18 16:32 View on GitHub →
channel: discord size: XS
## Summary `deliverDiscordReply` sends media attachments via `sendMessageDiscord` but does not forward `mediaLocalRoots`. This causes local media files in agent workspace directories to be rejected by `assertLocalMediaAllowed`, since only the default state-dir roots are checked. The outbound delivery path (`infra/outbound/deliver.ts`) already handles this correctly by calling `getAgentScopedMediaLocalRoots(cfg, agentId)`. This PR applies the same pattern to the Discord reply delivery path. ## Changes - **`reply-delivery.ts`** — Add optional `mediaLocalRoots` param and forward it to all three `sendMessageDiscord` calls that carry a `mediaUrl` - **`message-handler.process.ts`** — Supply `getAgentScopedMediaLocalRoots(cfg, route.agentId)` when calling `deliverDiscordReply` - **`agent-components.ts`** — Same for the component interaction delivery path - **`reply-delivery.test.ts`** — Add test asserting `mediaLocalRoots` is forwarded to `sendMessageDiscord` 4 files changed, +39 lines ## Reproduction 1. Configure an agent with a workspace directory outside the state dir 2. Have the agent generate or download a file to its workspace (e.g. an edited image) 3. Agent replies with the file as a media attachment via Discord 4. **Before fix:** `Local media path is not under an allowed directory` error 5. **After fix:** Media is sent successfully ## Testing - [x] `pnpm build` — passes - [x] `pnpm check` (format + types + lint) — passes - [x] `pnpm test` — 1106 passed, 1 skipped, 0 failures - [x] Tested end-to-end on a live Discord gateway with agent workspace media ## Note `sendVoiceMessageDiscord` has a similar gap (its `VoiceMessageOpts` type does not accept `mediaLocalRoots`), but that's a separate concern requiring changes to the voice message API surface — left out of scope to keep this PR focused. 🤖 AI-assisted (Claude) — fully tested, all changes understood and reviewed <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR fixes a bug where Discord reply delivery (both from message handling and component interactions) failed to forward `mediaLocalRoots` to `sendMessageDiscord`, causing agent workspace media to be rejected by `assertLocalMediaAllowed`. The fix threads the `mediaLocalRoots` parameter through the reply delivery path, matching the pattern already used by the outbound delivery path in `src/infra/outbound/deliver.ts`. - `deliverDiscordReply` gains an optional `mediaLocalRoots` parameter, forwarded to all three `sendMessageDiscord` call sites that include a `mediaUrl` - Both callers (`processDiscordMessage` and `dispatchDiscordComponentEvent`) now supply `getAgentScopedMediaLocalRoots(cfg, agentId)`, consistent with the outbound adapter - New test validates that `mediaLocalRoots` is correctly propagated for media payloads - As noted in the PR, `sendVoiceMessageDiscord` has the same gap but is left out of scope <h3>Confidence Score: 5/5</h3> - This PR is safe to merge — it adds a well-scoped parameter plumbing fix consistent with existing patterns, with no behavioral regressions. - The changes are minimal and mechanical: adding one optional parameter to a function signature and forwarding it at all appropriate call sites. The pattern directly mirrors the already-working outbound delivery path. All three `sendMessageDiscord` calls with `mediaUrl` now receive `mediaLocalRoots`. The parameter type (`readonly string[]`) matches the downstream `DiscordSendOpts` type exactly. A new test covers the change. Build, types, lint, and tests all pass per the PR. - No files require special attention. <sub>Last reviewed commit: 9469201</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs