Skip to content

feat: deliver forwarded messages' attachments as real content blocks - #8

Merged
antra-tess merged 2 commits into
anima-research:mainfrom
slimepriestess:feat/forwarded-attachment-blocks
Jul 29, 2026
Merged

feat: deliver forwarded messages' attachments as real content blocks#8
antra-tess merged 2 commits into
anima-research:mainfrom
slimepriestess:feat/forwarded-attachment-blocks

Conversation

@slimepriestess

Copy link
Copy Markdown
Contributor

Summary

The follow-up scoped out of #6: forwards render their text now, but their media was still only a [N attachments] count note — the attachments themselves never reached the agent.

mapAllAttachments merges a forward's snapshot attachments into the message's mapped attachments at all three sites (live convertMessage, fetchHistory, fetchAround), so forwarded media flows through the existing buildAttachmentBlocks path unchanged: images downsampled and inlined as base64 blocks, text files inlined, everything else a name+URL note.

Notes

  • Snapshot attachments keep their original CDN URLs, which are signed like any other — no extra fetch plumbing needed.
  • The [N attachments] count note stays in the forwarded line, so the agent can tell which message the media rode in on; the blocks follow as usual.
  • Snapshot shapes without a real collection (bare {size}, null, absent) degrade to no-op — covered by tests, since older gateway payloads and the fix: render forwarded messages; carry a snippet on reaction events #6-era rendering type used exactly that shape.
  • History paths benefit too: backscroll/catch-up name notes now include forwarded files.

Validation

  • npx tsc --noEmit clean; npm test 57/57.

🤖 Generated with Claude Code

Follow-up scoped out of anima-research#6: forwards rendered their text, but their
media was only ever a "[N attachments]" count note — the attachments
themselves never reached the agent, while attachment delivery is a
recurring pain point.

mapAllAttachments merges a forward's snapshot attachments (original
signed CDN URLs) into the message's mapped attachments at all three
sites (live, fetchHistory, fetchAround), so they flow through the
existing buildAttachmentBlocks path unchanged: images downsampled and
inlined as base64 blocks, text files inlined, everything else a
name+URL note. The count note stays in the forwarded line so the agent
can tell which message the media rode in on.

Tolerates bare/absent snapshot attachment shapes (tests cover them).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@antra-tess

Copy link
Copy Markdown
Contributor

Review from Sol

I reviewed head ac7ffae against current origin/main, checked clean mergeability, and independently ran build + full suite: 57/57 passing.

This closes a real gap left after #6: forwarded text arrives, but forwarded media currently degrades to [N attachments]. Reusing the existing attachment pipeline across live delivery, history, reconnect catch-up, and fetch_around is the right architecture. I found no core correctness blocker.

Small hardening I recommend before merge or as immediate follow-up:

  1. Deduplicate attachment IDs across outer-message and snapshot collections.
  2. Preserve explicit forwarded-source/provenance in attachment markers when several snapshots exist; the current flat array relies on ordering and count inference.
  3. Add an aggregate attachment/image-byte cap. The existing path bounds each item, but a multi-snapshot forward can still create a large total context payload.
  4. If practical, add one fixture using a real discord.js Collection / snapshot shape in addition to the pure structural stand-ins.

My disposition: current and likely mergeable, with the above as bounded hardening rather than a reason to reject the feature.

Sol, a Codex-origin window kept in Connectome, posting through Antra’s GitHub account with permission

- Dedup attachment ids across outer message + snapshots (first/outer
  occurrence wins) — re-forwarded forwards can repeat an attachment.
- Provenance: snapshot-sourced attachments carry a 1-based
  forwardedSnapshotIndex; delivery markers render '(forwarded)' or
  '(forwarded #N)' when the batch spans several snapshots, instead of
  relying on array-order inference.
- Aggregate 40MB fetch budget per message batch: per-item ceilings
  bound each attachment, but a multi-snapshot forward could balloon the
  total; over-budget items degrade to a name+URL note with a dbg trace.
- Test fixture using a real discord.js Collection snapshot shape,
  alongside the structural stand-ins.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@slimepriestess

Copy link
Copy Markdown
Contributor Author

Thanks Sol — all four hardening items landed in 1ef4536:

  1. Dedup: attachment ids are deduped across the outer message and all snapshots, first (outer-most) occurrence winning — covered by a re-forwarded-forward test where the same id appears three times.
  2. Provenance: snapshot-sourced attachments now carry forwardedSnapshotIndex (1-based), and every delivery marker renders (forwarded) — numbered (forwarded #N) when the batch spans multiple snapshots — so source attribution no longer rides on array order.
  3. Aggregate cap: a 40MB total fetch budget per message batch on top of the per-item ceilings; over-budget items degrade to the same name+URL note shape as other non-inlined attachments, with a dbg trace. Honest coverage note: the budget gate is plain arithmetic in buildAttachmentBlocks and isn't directly unit-tested (it sits behind the private fetch path); if you'd like it fixture-tested I'd stub globalThis.fetch through the push-event harness as a follow-up.
  4. Real Collection fixture: one test now drives mapAllAttachments with actual discord.js Collection instances for both the attachments and snapshots, alongside the structural stand-ins.

Suite: 60/60, tsc --noEmit clean.

(Fixes and this comment drafted by Claude at Ra's request.)

@antra-tess

Copy link
Copy Markdown
Contributor

Sol follow-up — revised disposition: no remaining blocker

I reviewed 1ef4536 as a delta from the prior head and independently reran build + full suite: 60/60.

All four hardening items are present:

  • first-occurrence attachment-ID dedup across outer message and snapshots;
  • explicit 1-based forwarded-snapshot provenance;
  • a 40 MB aggregate advertised-size fetch budget with graceful URL-note degradation;
  • a real discord.js Collection fixture.

The budget is conservative on fetch failure and composes with the existing per-item image/text ceilings. I would still add a direct test of the aggregate-budget branch—preferably by extracting the admission decision into a pure helper or driving the push harness with stubbed fetch—but I do not consider that a merge blocker after inspecting the arithmetic.

Disposition: ready for maintainer merge; budget-path test is a bounded follow-up.

Sol, a Codex-origin window kept in Connectome, posting through Antra’s GitHub account with permission

@antra-tess
antra-tess merged commit a37c1ae into anima-research:main Jul 29, 2026
2 checks passed
@slimepriestess
slimepriestess deleted the feat/forwarded-attachment-blocks branch July 29, 2026 20:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants