Multimodal Content
ContentPart, MessageContent, builders, text projection helpers, and unsupported-content behavior.
import {
UnsupportedContentError,
contentText,
filePart,
hasMediaParts,
imagePart,
messageText,
textPart,
} from "@use-crux/core";
import type { ContentPart, MessageContent } from "@use-crux/core";Types
MessageContent is the content type used by canonical generation messages:
type MessageContent = string | readonly ContentPart[];ContentPart is a closed JSON-serializable union:
| Part | Required fields | Notes |
|---|---|---|
text | text | Plain visible text. |
image-data | data, mediaType | Base64 bytes. |
image-url | url | Optional mediaType. |
image-file-id | fileId | Provider file reference, string or provider record. |
file-data | data, mediaType | Base64 bytes, optional filename. |
file-url | url | Optional mediaType and filename. |
file-id | fileId | Provider file reference, string or provider record. |
custom | none | Provider-specific escape through providerOptions. |
Every part may carry providerOptions. Protocol/control state such as tool calls and approvals belongs in Message.metadata, not in ContentPart.
Builders
textPart(text)
Create a text part.
const part = textPart("Summarize this image.");imagePart(input)
Create image-data from bytes/base64 or image-url from a URL.
imagePart({ data: pngBytes, mediaType: "image/png" });
imagePart({ url: new URL("https://example.com/chart.png") });filePart(input)
Create file-data from bytes/base64 or file-url from a URL.
filePart({
data: pdfBytes,
mediaType: "application/pdf",
filename: "report.pdf",
});
filePart({
url: "https://example.com/report.pdf",
mediaType: "application/pdf",
filename: "report.pdf",
});The builders accept string, Uint8Array, or ArrayBuffer for data, and string or URL for URLs. The returned parts contain only JSON-safe strings.
Text Projection
contentText(content)
Project a MessageContent value into bounded text.
const projected = contentText([
textPart("Inspect this."),
imagePart({ data: pngBytes, mediaType: "image/png" }),
]);Text parts are emitted verbatim. Data-backed parts include byte size and a short SHA-256 hash. URL-backed parts include the URL, optional MIME type, and optional filename. Labels are escaped and data URLs are truncated to their scheme and MIME type.
messageText(message)
Project a canonical message by reading message.content.
const projected = messageText(message);Use this anywhere a widened Message.content must become a string: guardrails, compaction, memory capture, cache query text, logs, or custom provider fallbacks.
hasMediaParts(content)
Return true when a content array contains any non-text part.
Unsupported Content
Adapters degrade unsupported parts by default: they send a deterministic placeholder, emit a diagnostics warning, and record a content.degraded span event. Use strict mode when degradation is not acceptable:
await adapter.generate(prompt, {
model,
input,
unsupportedContent: "error",
});Strict mode throws UnsupportedContentError before the provider call. The error exposes partType, optional mediaType, role, and provider.
Convex Mirror
@use-crux/convex re-exports ContentPart, MessageContent, textPart, imagePart, filePart, contentText, messageText, hasMediaParts, and UnsupportedContentError from its root. They are identical core re-exports for Convex code that imports through the runtime profile.