From 82afcfd4e00052c8dfdee448f2ad0aa65cd02041 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Fri, 7 Aug 2026 14:04:15 -0500 Subject: [PATCH] fix(ai): generate uuidv7 item ids --- packages/ai/src/schema/ids.ts | 15 ++++++++++++++- packages/ai/test/schema.test.ts | 7 +++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/packages/ai/src/schema/ids.ts b/packages/ai/src/schema/ids.ts index 0104052684c..b25a734217a 100644 --- a/packages/ai/src/schema/ids.ts +++ b/packages/ai/src/schema/ids.ts @@ -21,8 +21,21 @@ export type ProviderID = typeof ProviderID.Type export const ResponseID = Schema.String export type ResponseID = Schema.Schema.Type +const uuidv7 = () => { + const bytes = crypto.getRandomValues(new Uint8Array(16)) + const timestamp = BigInt(Date.now()) + bytes.set( + Array.from({ length: 6 }, (_, index) => Number((timestamp >> BigInt((5 - index) * 8)) & 0xffn)), + 0, + ) + bytes[6] = 0x70 | ((bytes[6] ?? 0) & 0x0f) + bytes[8] = 0x80 | ((bytes[8] ?? 0) & 0x3f) + const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("") + return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}` +} + export const ResponseItemID = Object.assign(Schema.String, { - create: (prefix: string): ResponseItemID => `${prefix}_${crypto.randomUUID()}`, + create: (prefix: string): ResponseItemID => `${prefix}_${uuidv7()}`, isPrefixed: (value: string) => { const separator = value.indexOf("_") return separator > 0 && separator < value.length - 1 diff --git a/packages/ai/test/schema.test.ts b/packages/ai/test/schema.test.ts index bf5c94dfd96..130904d2b6f 100644 --- a/packages/ai/test/schema.test.ts +++ b/packages/ai/test/schema.test.ts @@ -11,6 +11,7 @@ import { LanguageModel, ModelID, ProviderID, + ResponseItemID, Usage, } from "../src/schema" import { ProviderShared } from "../src/protocols/shared" @@ -68,6 +69,12 @@ describe("llm schema", () => { expect(ContentPart.guards.text({ type: "text", text: "hi" })).toBe(true) expect(ContentPart.guards.media({ type: "text", text: "hi" })).toBe(false) }) + + test("creates prefixed UUIDv7 response item ids", () => { + const id = ResponseItemID.create("msg") + expect(id).toMatch(/^msg_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/) + expect(ResponseItemID.isPrefixed(id)).toBe(true) + }) }) describe("AI.Usage", () => {