summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDax Raad <[email protected]>2025-05-18 02:50:38 -0400
committerDax Raad <[email protected]>2025-05-26 12:40:17 -0400
commitbcd2fd68b7fa00af055f558049994c2975d9515d (patch)
tree350e419b64919ea87859a65f7eb9bff5c29efca2
parentd0d67029f4baad7389b5ba072379c2ff44a22dc4 (diff)
downloadopencode-bcd2fd68b7fa00af055f558049994c2975d9515d.tar.gz
opencode-bcd2fd68b7fa00af055f558049994c2975d9515d.zip
sync
-rw-r--r--js/src/id/id.ts38
-rw-r--r--js/src/index.ts2
-rw-r--r--js/src/session/session.ts6
3 files changed, 36 insertions, 10 deletions
diff --git a/js/src/id/id.ts b/js/src/id/id.ts
index 5ad2fb91d..e4744f172 100644
--- a/js/src/id/id.ts
+++ b/js/src/id/id.ts
@@ -1,5 +1,5 @@
-import { ulid } from "ulid";
import { z } from "zod";
+import { randomBytes } from "crypto";
export namespace Identifier {
const prefixes = {
@@ -7,18 +7,44 @@ export namespace Identifier {
message: "msg",
} as const;
- export function create(
+ export function schema(prefix: keyof typeof prefixes) {
+ return z.string().startsWith(prefixes[prefix]);
+ }
+
+ const LENGTH = 24;
+
+ export function ascending(prefix: keyof typeof prefixes, given?: string) {
+ return generateID(prefix, false, given);
+ }
+
+ export function descending(prefix: keyof typeof prefixes, given?: string) {
+ return generateID(prefix, true, given);
+ }
+
+ function generateID(
prefix: keyof typeof prefixes,
+ descending: boolean,
given?: string,
): string {
if (given) {
if (given.startsWith(prefixes[prefix])) return given;
throw new Error(`ID ${given} does not start with ${prefixes[prefix]}`);
}
- return [prefixes[prefix], ulid()].join("_");
- }
- export function schema(prefix: keyof typeof prefixes) {
- return z.string().startsWith(prefixes[prefix]);
+ let now = BigInt(Date.now());
+
+ if (descending) {
+ now = ~now;
+ }
+
+ const timeBytes = Buffer.alloc(6);
+ for (let i = 0; i < 6; i++) {
+ timeBytes[i] = Number((now >> BigInt(40 - 8 * i)) & BigInt(0xff));
+ }
+
+ const randLength = (LENGTH - 12) / 2;
+ const random = randomBytes(randLength);
+
+ return prefix + "_" + timeBytes.toString("hex") + random.toString("hex");
}
}
diff --git a/js/src/index.ts b/js/src/index.ts
index 959d1182a..72c32c8e9 100644
--- a/js/src/index.ts
+++ b/js/src/index.ts
@@ -16,7 +16,7 @@ App.provide(app, async () => {
await Session.chat(sessionID, {
role: "user",
- id: Identifier.create("message"),
+ id: Identifier.ascending("message"),
parts: [
{
type: "text",
diff --git a/js/src/session/session.ts b/js/src/session/session.ts
index 4ad40f32a..d07c799b9 100644
--- a/js/src/session/session.ts
+++ b/js/src/session/session.ts
@@ -34,7 +34,7 @@ export namespace Session {
export async function create() {
const result: Info = {
- id: Identifier.create("session"),
+ id: Identifier.descending("session"),
title: "New Session - " + new Date().toISOString(),
};
log.info("created", result);
@@ -86,7 +86,7 @@ export namespace Session {
l.info("chatting");
const msgs = (await messages(sessionID)) ?? [
{
- id: Identifier.create("message"),
+ id: Identifier.ascending("message"),
role: "system",
parts: [
{
@@ -125,7 +125,7 @@ export namespace Session {
model,
});
const next: UIMessage = {
- id: Identifier.create("message"),
+ id: Identifier.ascending("message"),
role: "assistant",
parts: [],
};