fix(chat): stabilize message identities
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const UiMessageSchema = z.object({
|
||||
id: z.string().optional(),
|
||||
displayId: z.string().min(1),
|
||||
remoteId: z.string().min(1).optional(),
|
||||
clientId: z.string().min(1).optional(),
|
||||
content: z.string(),
|
||||
isFromAI: z.boolean(),
|
||||
date: z.string(),
|
||||
@@ -18,6 +20,41 @@ export const UiMessageSchema = z.object({
|
||||
|
||||
export type UiMessage = z.infer<typeof UiMessageSchema>;
|
||||
|
||||
let fallbackClientId = 0;
|
||||
|
||||
export function createRemoteUiMessageIdentity(
|
||||
remoteId: string,
|
||||
isFromAI: boolean,
|
||||
occurrence = 0,
|
||||
): Pick<UiMessage, "displayId" | "remoteId"> {
|
||||
const role = isFromAI ? "assistant" : "user";
|
||||
const base = `server:${encodeURIComponent(remoteId)}:${role}`;
|
||||
return {
|
||||
displayId: occurrence > 0 ? `${base}:${occurrence}` : base,
|
||||
remoteId,
|
||||
};
|
||||
}
|
||||
|
||||
export function createLegacyUiMessageIdentity(
|
||||
fingerprint: string,
|
||||
occurrence = 0,
|
||||
): Pick<UiMessage, "displayId"> {
|
||||
const base = `legacy:${hashIdentity(fingerprint)}`;
|
||||
return {
|
||||
displayId: occurrence > 0 ? `${base}:${occurrence}` : base,
|
||||
};
|
||||
}
|
||||
|
||||
export function createClientUiMessageIdentity(
|
||||
kind: "message" | "image" | "reply" | "error",
|
||||
): Pick<UiMessage, "displayId" | "clientId"> {
|
||||
const clientId = createClientId();
|
||||
return {
|
||||
clientId,
|
||||
displayId: `client:${kind}:${clientId}`,
|
||||
};
|
||||
}
|
||||
|
||||
export const UiMessage = {
|
||||
create(input: Omit<UiMessage, "date"> & { date?: string }): UiMessage {
|
||||
return UiMessageSchema.parse({
|
||||
@@ -31,3 +68,20 @@ export const UiMessage = {
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
function createClientId(): string {
|
||||
if (typeof globalThis.crypto?.randomUUID === "function") {
|
||||
return globalThis.crypto.randomUUID();
|
||||
}
|
||||
fallbackClientId += 1;
|
||||
return `${Date.now().toString(36)}-${fallbackClientId.toString(36)}`;
|
||||
}
|
||||
|
||||
function hashIdentity(value: string): string {
|
||||
let hash = 0x811c9dc5;
|
||||
for (let index = 0; index < value.length; index += 1) {
|
||||
hash ^= value.charCodeAt(index);
|
||||
hash = Math.imul(hash, 0x01000193);
|
||||
}
|
||||
return (hash >>> 0).toString(36);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user