Skip to content

Commit 639faf0

Browse files
committed
fix(copilot): replace crypto.randomUUID() with generateId() per project rule
AGENTS.md / CLAUDE.md forbid crypto.randomUUID() (non-secure contexts throw TypeError in browsers). Four copilot server-side files still violated this rule, left over after PR #3397 polyfilled the client. Routes through request lifecycle, OAuth draft insertion, persisted message normalization, and table-row generation now use generateId from @sim/utils/id, which is a drop-in UUID v4 producer that falls back to crypto.getRandomValues when randomUUID is unavailable. Refs #3393.
1 parent bed5e95 commit 639faf0

4 files changed

Lines changed: 12 additions & 8 deletions

File tree

apps/sim/lib/copilot/chat/persisted-message.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { generateId } from '@sim/utils/id'
12
import {
23
MothershipStreamV1CompletionStatus,
34
MothershipStreamV1EventType,
@@ -191,7 +192,7 @@ export function buildPersistedAssistantMessage(
191192
requestId?: string
192193
): PersistedMessage {
193194
const message: PersistedMessage = {
194-
id: crypto.randomUUID(),
195+
id: generateId(),
195196
role: 'assistant',
196197
content: result.content,
197198
timestamp: new Date().toISOString(),
@@ -488,7 +489,7 @@ function normalizeBlocks(rawBlocks: RawBlock[], messageContent: string): Persist
488489

489490
export function normalizeMessage(raw: Record<string, unknown>): PersistedMessage {
490491
const msg: PersistedMessage = {
491-
id: (raw.id as string) ?? crypto.randomUUID(),
492+
id: (raw.id as string) ?? generateId(),
492493
role: (raw.role as 'user' | 'assistant') ?? 'assistant',
493494
content: (raw.content as string) ?? '',
494495
timestamp: (raw.timestamp as string) ?? new Date().toISOString(),

apps/sim/lib/copilot/chat/post.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { type Context as OtelContext, context as otelContextApi } from '@opentel
22
import { db } from '@sim/db'
33
import { copilotChats } from '@sim/db/schema'
44
import { createLogger } from '@sim/logger'
5+
import { generateId } from '@sim/utils/id'
56
import { eq, sql } from 'drizzle-orm'
67
import { type NextRequest, NextResponse } from 'next/server'
78
import { z } from 'zod'
@@ -615,8 +616,8 @@ export async function handleUnifiedChatPost(req: NextRequest) {
615616
// trace ID) as soon as startCopilotOtelRoot runs. Empty only in the
616617
// narrow pre-otelRoot window where errors don't correlate anyway.
617618
let requestId = ''
618-
const executionId = crypto.randomUUID()
619-
const runId = crypto.randomUUID()
619+
const executionId = generateId()
620+
const runId = generateId()
620621

621622
try {
622623
const session = await getSession()
@@ -628,7 +629,7 @@ export async function handleUnifiedChatPost(req: NextRequest) {
628629

629630
const body = ChatMessageSchema.parse(await req.json())
630631
const normalizedContexts = normalizeContexts(body.contexts) ?? []
631-
userMessageId = body.userMessageId || crypto.randomUUID()
632+
userMessageId = body.userMessageId || generateId()
632633

633634
otelRoot = startCopilotOtelRoot({
634635
streamId: userMessageId,

apps/sim/lib/copilot/request/tools/tables.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { db } from '@sim/db'
22
import { userTableRows } from '@sim/db/schema'
33
import { createLogger } from '@sim/logger'
44
import { toError } from '@sim/utils/errors'
5+
import { generateId } from '@sim/utils/id'
56
import { parse as csvParse } from 'csv-parse/sync'
67
import { eq } from 'drizzle-orm'
78
import { FunctionExecute, Read as ReadTool } from '@/lib/copilot/generated/tool-catalog-v1'
@@ -107,7 +108,7 @@ export async function maybeWriteOutputToTable(
107108
}
108109
const chunk = rows.slice(i, i + BATCH_CHUNK_SIZE)
109110
const values = chunk.map((rowData, j) => ({
110-
id: `row_${crypto.randomUUID().replace(/-/g, '')}`,
111+
id: `row_${generateId().replace(/-/g, '')}`,
111112
tableId: outputTable,
112113
workspaceId: context.workspaceId!,
113114
data: rowData,
@@ -251,7 +252,7 @@ export async function maybeWriteReadCsvToTable(
251252
}
252253
const chunk = rows.slice(i, i + BATCH_CHUNK_SIZE)
253254
const values = chunk.map((rowData, j) => ({
254-
id: `row_${crypto.randomUUID().replace(/-/g, '')}`,
255+
id: `row_${generateId().replace(/-/g, '')}`,
255256
tableId: outputTable,
256257
workspaceId: context.workspaceId!,
257258
data: rowData,

apps/sim/lib/copilot/tools/handlers/oauth.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { db } from '@sim/db'
22
import { pendingCredentialDraft, user } from '@sim/db/schema'
33
import { toError } from '@sim/utils/errors'
4+
import { generateId } from '@sim/utils/id'
45
import { and, eq, lt } from 'drizzle-orm'
56
import type { ExecutionContext, ToolCallResult } from '@/lib/copilot/request/types'
67
import { getBaseUrl } from '@/lib/core/utils/urls'
@@ -140,7 +141,7 @@ export async function generateOAuthLink(
140141
await db
141142
.insert(pendingCredentialDraft)
142143
.values({
143-
id: crypto.randomUUID(),
144+
id: generateId(),
144145
userId,
145146
workspaceId,
146147
providerId,

0 commit comments

Comments
 (0)