Skip to content

Commit 3e4a6e4

Browse files
waleedlatif1claude
andcommitted
fix(knowledge): address review comments on upsert document
- Reorder create-then-delete to prevent data loss if creation fails - Move Zod validation before workflow authorization for validated input - Fix btoa stack overflow for large content using loop-based encoding Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8bf63fe commit 3e4a6e4

File tree

2 files changed

+21
-12
lines changed

2 files changed

+21
-12
lines changed

apps/sim/app/api/knowledge/[id]/documents/upsert/route.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,11 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
5555
}
5656
const userId = auth.userId
5757

58-
if (body.workflowId) {
58+
const validatedData = UpsertDocumentSchema.parse(body)
59+
60+
if (validatedData.workflowId) {
5961
const authorization = await authorizeWorkflowByWorkspacePermission({
60-
workflowId: body.workflowId,
62+
workflowId: validatedData.workflowId,
6163
userId,
6264
action: 'write',
6365
})
@@ -82,8 +84,6 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
8284
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
8385
}
8486

85-
const validatedData = UpsertDocumentSchema.parse(body)
86-
8787
let existingDocumentId: string | null = null
8888
let isUpdate = false
8989

@@ -126,9 +126,8 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
126126
if (existingDocumentId) {
127127
isUpdate = true
128128
logger.info(
129-
`[${requestId}] Found existing document ${existingDocumentId}, deleting before re-creation`
129+
`[${requestId}] Found existing document ${existingDocumentId}, creating replacement before deleting old`
130130
)
131-
await deleteDocument(existingDocumentId, requestId)
132131
}
133132

134133
const createdDocuments = await createDocumentRecords(
@@ -147,6 +146,10 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
147146
requestId
148147
)
149148

149+
if (existingDocumentId) {
150+
await deleteDocument(existingDocumentId, requestId)
151+
}
152+
150153
const firstDocument = createdDocuments[0]
151154

152155
processDocumentsWithQueue(

apps/sim/tools/knowledge/upsert_document.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,18 @@ export const knowledgeUpsertDocumentTool: ToolConfig<
8181
throw new Error('Document content exceeds maximum size of 1MB')
8282
}
8383

84-
const contentBytes = new TextEncoder().encode(textContent).length
85-
86-
const base64Content =
87-
typeof Buffer !== 'undefined'
88-
? Buffer.from(textContent, 'utf8').toString('base64')
89-
: btoa(String.fromCharCode(...new TextEncoder().encode(textContent)))
84+
const utf8Bytes = new TextEncoder().encode(textContent)
85+
const contentBytes = utf8Bytes.length
86+
let base64Content: string
87+
if (typeof Buffer !== 'undefined') {
88+
base64Content = Buffer.from(textContent, 'utf8').toString('base64')
89+
} else {
90+
let binary = ''
91+
for (let i = 0; i < utf8Bytes.length; i++) {
92+
binary += String.fromCharCode(utf8Bytes[i])
93+
}
94+
base64Content = btoa(binary)
95+
}
9096

9197
const dataUri = `data:text/plain;base64,${base64Content}`
9298

0 commit comments

Comments
 (0)