Skip to content

feat(core): Content union type — structured multimodal content model#828

Merged
christso merged 1 commit intomainfrom
feat/817-content-union
Mar 29, 2026
Merged

feat(core): Content union type — structured multimodal content model#828
christso merged 1 commit intomainfrom
feat/817-content-union

Conversation

@christso
Copy link
Copy Markdown
Collaborator

Summary

Introduces a Content discriminated union type (ContentText | ContentImage | ContentFile) and updates Message.content to string | Content[], enabling multimodal content to flow through the pipeline without lossy flattening.

Changes

  • New module packages/core/src/evaluation/content.ts:
    • ContentText, ContentImage, ContentFile type definitions
    • Content discriminated union
    • Type guards: isContent(), isContentArray()
    • Text accessor: getTextContent(content) — extracts text without destroying the array
  • Updated Message.content from unknown to string | Content[] (backward compatible)
  • Updated extractLastAssistantContent() to handle Content[] via getTextContent()
  • Claude CLI provider now preserves image content blocks instead of dropping them
  • CLI provider handles Content[] from external processes
  • Exported all content types from @agentv/core public API

Design Decisions

  • Binary content (images, files) uses URL/base64 strings or filesystem paths, not raw bytes
  • toContentArray() in claude-cli only promotes to Content[] when non-text blocks exist (avoids unnecessary complexity for text-only responses)
  • Bare string content continues to work everywhere (backward compat)

Testing

  • 25 new unit tests covering type guards, accessors, backward compat, and extractLastAssistantContent with Content[]
  • All 1227 existing core tests pass
  • Build, typecheck, lint all pass

Closes #817

Introduce a discriminated union Content type (ContentText | ContentImage |
ContentFile) that enables multimodal content to flow through the pipeline
without lossy flattening.

Changes:
- Add packages/core/src/evaluation/content.ts with Content union type,
  type guards (isContent, isContentArray), and getTextContent() accessor
- Update Message.content from 'unknown' to 'string | Content[]'
- Update extractLastAssistantContent() to handle Content[] via getTextContent()
- Update claude-cli provider to preserve non-text content blocks (images)
  instead of dropping them during extraction
- Update cli provider to handle Content[] from external processes
- Export all content types from @agentv/core public API
- Add 25 unit tests covering type guards, accessors, backward compat,
  and extractLastAssistantContent with Content[]

Closes #817

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@cloudflare-workers-and-pages
Copy link
Copy Markdown

Deploying agentv with  Cloudflare Pages  Cloudflare Pages

Latest commit: 9ab0641
Status: ✅  Deploy successful!
Preview URL: https://9f78ee98.agentv.pages.dev
Branch Preview URL: https://feat-817-content-union.agentv.pages.dev

View logs

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.

feat(core): Content union type — structured multimodal content model

1 participant