Skip to content

feat: inline image groups via spec blocks#825

Merged
miurla merged 2 commits intomainfrom
feat/inline-images-spec
Apr 15, 2026
Merged

feat: inline image groups via spec blocks#825
miurla merged 2 commits intomainfrom
feat/inline-images-spec

Conversation

@miurla
Copy link
Copy Markdown
Owner

@miurla miurla commented Apr 15, 2026

Summary

Extends the spec-block rendering system (#803) with inline image groups. LLM emits a Grid containing Image children via ```spec fences; the Grid reserves CSS grid columns upfront so streaming images don't reflow. Clicking any image opens a dynamic lightbox that fits the image's natural aspect ratio.

Changes

  • Catalog: Add Grid { columns, gap? } and Image { src, sourceUrl?, title?, description?, aspectRatio? } components, split into per-file modules under lib/render/components/.
  • Prompt: LLM copies url/sourceUrl/title/description verbatim from search tool output. Multiple image spec blocks allowed inline; related-questions block stays at the end.
  • Tavily: Preserves image title and best-effort matches it to results[].url to produce sourceUrl pointing at the original article.
  • Lightbox: Transparent, size-to-content Dialog with shared ImageCreditOverlay (used by both the new Image dialog and the existing carousel). URL scheme allowlisted to http(s) to prevent XSS via model-generated links.
  • Dialog: Close button focus ring switched to `focus-visible:` so it only shows for keyboard navigation.
  • Tests: Grid/Image parse test, multi-fence strip test, gated E2E test (`RUN_LLM_E2E=1`) verifying LLM emits valid image specs with non-hallucinated URLs.

Test plan

  • `bun typecheck` / `lint` / `format:check` / `test` (171 passing)
  • Manual: search for a visual subject → inline image Grid streams without reflow
  • Manual: click image → fitted lightbox with credit linking to source article
  • Manual: copy message → all spec blocks stripped from clipboard

- Add Grid and Image components to the json-render catalog so the LLM can
  embed inline image groups with a fixed-column layout that reserves cell
  widths upfront (no reflow as images stream in).
- Extend the image embedding prompt: LLM must copy src/sourceUrl/title/
  description verbatim from search tool output and wrap groups in a Grid.
- Enrich Tavily provider results: preserve image titles and best-effort
  match them to results[].url so image credits can link to the source
  article instead of the image host.
- Add SearchResultImage.title and SearchResultImage.sourceUrl to types.
- Extract ImageCreditOverlay into a shared component used by both the
  search-results-image carousel and the new inline Image lightbox.
- Replace the gray letterboxed image dialog with a dynamic one that
  fits to the image's natural size (max 90vw/85vh) with a transparent
  background.
- Soften Dialog close button focus ring and switch to focus-visible so
  the ring only shows for keyboard navigation.
- Add unit tests for parsing Grid/Image specs and for stripping multiple
  spec fences, plus a gated E2E test that verifies an LLM actually emits
  well-formed image spec blocks (RUN_LLM_E2E=1).
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 15, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
morphic Ready Ready Preview, Comment Apr 15, 2026 8:29am

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2ac63b47f3

ℹ️ 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".

Comment thread components/image-credit-overlay.tsx Outdated
- Split lib/render/registry.tsx into one file per catalog component
  (components/{section-header,stack,question-button,grid,image}.tsx)
  with a shared CatalogType/stackGap module. registry.tsx is now
  just import + defineRegistry.
- Restrict ImageCreditOverlay links to http/https via URL.protocol
  allowlist. Falls back to a non-clickable label when the sourceUrl
  (model-generated) has an unsafe scheme — prevents javascript:/data:
  XSS via inline image spec blocks (Codex P2).
- Re-run prettier on registry.tsx and tavily.ts (CI Format Check
  was failing on the initial commit).
@miurla miurla merged commit d2886aa into main Apr 15, 2026
8 checks passed
@miurla miurla deleted the feat/inline-images-spec branch April 15, 2026 08: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.

1 participant