diff --git a/packages/client/ui-conversation/src/client/chat/ContextBody.tsx b/packages/client/ui-conversation/src/client/chat/ContextBody.tsx
index d590d104b5..2978fd9400 100644
--- a/packages/client/ui-conversation/src/client/chat/ContextBody.tsx
+++ b/packages/client/ui-conversation/src/client/chat/ContextBody.tsx
@@ -83,15 +83,14 @@ function SourceFields({ source, t }: { source: unknown; t: Translate }): ReactNo
}
/**
- * Default presentation: the model-facing text as text, with its real line
- * breaks, and the remaining provenance beneath it. This is what every form
- * this UI version does not recognize renders as.
- * @param props - Durable content, its source, and the locale seat.
- * @returns The opaque context body.
+ * The model-facing content of one context, shared by every form that shows it:
+ * the text with its real line breaks, then any block this UI version does not
+ * know, which keeps its own fallback rather than vanishing.
+ * @param props - Durable content and the locale seat.
+ * @returns The content blocks as the model received them.
*/
-export function OpaqueBody({ content, source, t }: {
+function ModelFacingContent({ content, t }: {
content: ContextMessageNode['content']
- source: unknown
t: Translate
}): ReactNode {
const { text, rest } = partitionContent(content)
@@ -106,6 +105,25 @@ export function OpaqueBody({ content, source, t }: {
truncatedLabel={total => t('json.truncated', { total })}
/>
))}
+ >
+ )
+}
+
+/**
+ * Default presentation: the model-facing text as text, with its real line
+ * breaks, and the remaining provenance beneath it. This is what every form
+ * this UI version does not recognize renders as.
+ * @param props - Durable content, its source, and the locale seat.
+ * @returns The opaque context body.
+ */
+export function OpaqueBody({ content, source, t }: {
+ content: ContextMessageNode['content']
+ source: unknown
+ t: Translate
+}): ReactNode {
+ return (
+ <>
+
{boundedText(text, t)}}
- {rest.map((block, index) => (
-