@assistant-ui/react
Version:
TypeScript/React library for AI Chat
127 lines • 5.42 kB
JavaScript
import { parsePartialJsonObject } from "assistant-stream/utils";
import { generateId } from "../../../utils/idUtils.js";
export const fromThreadMessageLike = (like, fallbackId, fallbackStatus) => {
const { role, id, createdAt, attachments, status, metadata } = like;
const common = {
id: id ?? fallbackId,
createdAt: createdAt ?? new Date(),
};
const content = typeof like.content === "string"
? [{ type: "text", text: like.content }]
: like.content;
const sanitizeImageContent = ({ image, ...rest }) => {
const match = image.match(/^data:image\/(png|jpeg|jpg|gif|webp);base64,(.*)$/);
if (match) {
return { ...rest, image };
}
console.warn(`Invalid image data format detected`);
return null;
};
if (role !== "user" && attachments?.length)
throw new Error("attachments are only supported for user messages");
if (role !== "assistant" && status)
throw new Error("status is only supported for assistant messages");
if (role !== "assistant" && metadata?.steps)
throw new Error("metadata.steps is only supported for assistant messages");
switch (role) {
case "assistant":
return {
...common,
role,
content: content
.map((part) => {
const type = part.type;
switch (type) {
case "text":
case "reasoning":
if (part.text.trim().length === 0)
return null;
return part;
case "file":
case "source":
return part;
case "image":
return sanitizeImageContent(part);
case "data":
return part;
case "tool-call": {
const { parentId, messages, ...basePart } = part;
const commonProps = {
...basePart,
toolCallId: part.toolCallId ?? `tool-${generateId()}`,
...(parentId !== undefined && { parentId }),
...(messages !== undefined && { messages }),
};
if (part.args) {
return {
...commonProps,
args: part.args,
argsText: part.argsText ?? JSON.stringify(part.args),
};
}
return {
...commonProps,
args: parsePartialJsonObject(part.argsText ?? "") ?? {},
argsText: part.argsText ?? "",
};
}
default: {
const unhandledType = type;
throw new Error(`Unsupported assistant message part type: ${unhandledType}`);
}
}
})
.filter((c) => !!c),
status: status ?? fallbackStatus,
metadata: {
unstable_state: metadata?.unstable_state ?? null,
unstable_annotations: metadata?.unstable_annotations ?? [],
unstable_data: metadata?.unstable_data ?? [],
custom: metadata?.custom ?? {},
steps: metadata?.steps ?? [],
...(metadata?.submittedFeedback && {
submittedFeedback: metadata.submittedFeedback,
}),
},
};
case "user":
return {
...common,
role,
content: content.map((part) => {
const type = part.type;
switch (type) {
case "text":
case "image":
case "audio":
case "file":
return part;
default: {
const unhandledType = type;
throw new Error(`Unsupported user message part type: ${unhandledType}`);
}
}
}),
attachments: attachments ?? [],
metadata: {
custom: metadata?.custom ?? {},
},
};
case "system":
if (content.length !== 1 || content[0].type !== "text")
throw new Error("System messages must have exactly one text message part.");
return {
...common,
role,
content: content,
metadata: {
custom: metadata?.custom ?? {},
},
};
default: {
const unsupportedRole = role;
throw new Error(`Unknown message role: ${unsupportedRole}`);
}
}
};
//# sourceMappingURL=ThreadMessageLike.js.map