Skip to content

refactor(media): image-egress review follow-up — value objects, probe result, dedup#1348

Merged
Aaronontheweb merged 1 commit into
netclaw-dev:devfrom
Aaronontheweb:followup-1296-review
Jun 7, 2026
Merged

refactor(media): image-egress review follow-up — value objects, probe result, dedup#1348
Aaronontheweb merged 1 commit into
netclaw-dev:devfrom
Aaronontheweb:followup-1296-review

Conversation

@Aaronontheweb

Copy link
Copy Markdown
Collaborator

Follow-up to #1345, addressing the review comments.

What's in here

Value objects (your ImageNormalization.cs:54 note). The options/result records used bare int for both pixels and bytes, which is exactly the kind of thing a future reader — human or LLM — will mix up. Wrapped them in tidy little structs: Pixels, ByteSize, JpegQuality. No implicit conversions (you go through .Value), so you can't pass a byte count where a pixel cap is expected. ByteSize.ToString() also absorbed the human B/KB/MB formatting, so the old FormatBudget helper is gone and the drop messages just interpolate the value object.

Real result type for the probe (ImageNormalizerProbe.cs:23). TryProbe() returned string? with null meaning success, which is the null-as-sentinel smell you flagged. It now returns ImagingProbeResult { IsWorking, Error }, and the doctor check reads .IsWorking / .Error.

Dedup (ChatMessageConverter.cs:163 — "why is this duplicated?"). Good catch. The "write the DataContent, add a reference or append an [image omitted] note" block was copy-pasted in ChannelPipeline and ChatMessageConverter. Pulled it into a single SessionMediaStore.WriteMediaInto(...) so there's one owner of that fold; AppendOmittedImageNote is now private since nothing outside calls it directly.

Comments.

  • SkiaImageNormalizer.cs:46 ("what image types are not decodeable?") — spelled it out: corrupt/truncated files, non-image bytes wearing an image MIME, or formats Skia doesn't decode (HEIC/AVIF without a platform codec, SVG). JPEG/PNG/WebP/GIF/BMP all decode fine.
  • SkiaImageNormalizer.cs:90 — left the breadcrumb you asked for: we drop an over-budget-after-resize image rather than shrink it further, and if those drops get common the place to reintroduce a bounded size-reduction loop is right there.
  • Tests.Utilities.csproj:14 ("what about Windows and OS X?") — they come transitively from the base SkiaSharp package (it depends on NativeAssets.Win32/NativeAssets.macOS); desktop Linux is the only one not pulled in by default, hence the explicit add. Noted it in the csproj. CI already proved it — Test-windows-latest and Test-macos-26 both passed on fix(media): resize images once at ingest instead of re-inlining them every turn (#1296) #1345.

Tests

  • Netclaw.Media.Tests (65) — added a ByteSize.ToString formatting test (guards the sub-MiB "0MB" case), updated the options/probe call sites.
  • Netclaw.Actors.Tests (2211) — the seam and converter tests cover the deduped path.
  • Clean build (0 warnings), slopwatch clean, headers verified.

No behavior change — this is the tidy-up pass.

…probe result, dedup

Follow-up to the image-egress PR:

- Wrap the normalizer's bare ints in tidy value objects so px and bytes can't be
  confused at a call site: Pixels, ByteSize, JpegQuality. ByteSize.ToString folds
  in the human B/KB/MB formatting (replacing the FormatBudget helper).
- ImageNormalizerProbe returns a real ImagingProbeResult { IsWorking, Error }
  instead of null-as-success.
- Dedup the "write DataContent -> add reference or append [image omitted] note"
  logic that was copy-pasted in ChannelPipeline and ChatMessageConverter into one
  SessionMediaStore.WriteMediaInto helper; AppendOmittedImageNote is now private.
- Comments: spell out what hits the "not a decodable image" drop; leave a
  breadcrumb where an iterative size-reduction loop would go if over-budget drops
  get common; note in Tests.Utilities.csproj that Win/macOS native assets come
  transitively from base SkiaSharp (only Linux needs the explicit add).

Media tests 65, Actors 2211; solution builds clean; slopwatch + headers pass.

@Aaronontheweb Aaronontheweb left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Aaronontheweb Aaronontheweb enabled auto-merge (squash) June 7, 2026 13:19
@Aaronontheweb Aaronontheweb merged commit 258d594 into netclaw-dev:dev Jun 7, 2026
15 checks passed
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.

1 participant