Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/openstatusHQ/openstatus. ๐ซ Status page with uptime monitoring & API monitoring as code ๐ซ openstatus.dev
bun drizzle-orm monitoring monitoring-as-code nextjs observability on-call open-source shadcn-ui status-page statuspage synthetic-monitoring tinybird turso uptime uptime-checker uptime-monitor
Something went wrong. Try again.
2.0 kB ยท 69 lines
TypeScript
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970import { CHAT_TITLE_MAX_LENGTH, type ChatSessionRow, MAX_CHAT_SESSIONS_PER_USER, chatSession,} from "@openstatus/db/src/schema";
import { type ServiceContext, tryGetActorUserId, withTransaction,} from "../context";import { UnauthorizedError } from "../errors";import { enforceSessionCap } from "./internal";import { CreateChatSessionInput } from "./schemas";
// Per-user UI state, not workspace configuration: only user actors get past// `tryGetActorUserId`, so `requireScope` could never fire, and the audit action// union has no `chat_session` verb.// oxlint-disable-next-line openstatus/services-mutation-guardsexport async function createChatSession(args: { ctx: ServiceContext; input: CreateChatSessionInput;}): Promise<ChatSessionRow> { const { ctx } = args; const input = CreateChatSessionInput.parse(args.input);
const userId = tryGetActorUserId(ctx.actor); if (userId == null) { throw new UnauthorizedError( "Chat sessions must be created by a known user actor.", ); }
return withTransaction(ctx, async (tx) => { await enforceSessionCap({ tx, workspaceId: ctx.workspace.id, userId, capAfterInsert: MAX_CHAT_SESSIONS_PER_USER - 1, });
const title = deriveTitle(input.firstMessage.parts);
const row = await tx .insert(chatSession) .values({ workspaceId: ctx.workspace.id, userId, title, messages: [input.firstMessage], }) .returning() .get();
return row; });}
function deriveTitle(parts: CreateChatSessionInput["firstMessage"]["parts"]) { const textPart = parts.find( (p): p is { type: "text"; text: string } & Record<string, unknown> => p.type === "text" && typeof (p as { text?: unknown }).text === "string", ); const raw = textPart?.text ?? "New chat"; const trimmed = raw.trim().replace(/\s+/g, " "); if (trimmed.length === 0) return "New chat"; return trimmed.slice(0, CHAT_TITLE_MAX_LENGTH);}