feat(knowledge): add upsert document operation#3644
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Greptile SummaryThis PR adds a All critical issues raised in the previous review thread have been resolved:
One minor UX suggestion: the "Document ID (Optional)" sub-block currently appears after "Document Tags" in the form — reordering it before Confidence Score: 4/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant Client as Tool Client
participant Route as POST /api/knowledge/[id]/documents/upsert
participant DB as Database
participant DocSvc as Document Service
Client->>Route: POST { filename, fileUrl, documentId?, ... }
Route->>Route: checkSessionOrInternalAuth()
Route->>Route: UpsertDocumentSchema.parse(body)
Route->>Route: authorizeWorkflowByWorkspacePermission() (if workflowId)
Route->>Route: checkKnowledgeBaseWriteAccess()
alt documentId provided
Route->>DB: SELECT id WHERE id=documentId AND knowledgeBaseId AND deletedAt IS NULL
DB-->>Route: existingDoc (may be empty)
else no documentId
Route->>DB: SELECT id WHERE filename=filename AND knowledgeBaseId AND deletedAt IS NULL
DB-->>Route: docsByFilename (may be empty)
end
Route->>DocSvc: createDocumentRecords([{filename, fileUrl, ...}])
DocSvc-->>Route: createdDocuments[]
Route->>Route: Guard: firstDocument = createdDocuments[0]
alt existingDocumentId found
Route->>DocSvc: deleteDocument(existingDocumentId)
alt delete fails
DocSvc-->>Route: throws
Route->>DocSvc: deleteDocument(firstDocument.documentId) [rollback]
Route-->>Client: 500 Failed to replace existing document
end
end
Route->>DocSvc: processDocumentsWithQueue() [fire & forget]
Route->>Route: recordAudit(DOCUMENT_UPDATED | DOCUMENT_UPLOADED)
Route-->>Client: 200 { success, data: { documentsCreated, isUpdate, previousDocumentId } }
Last reviewed commit: "lint" |
Add a "Create or Update" (upsert) document capability that finds an existing document by ID or filename, deletes it if found, then creates a new document and queues re-processing. Includes new tool, API route, block wiring, and typed interfaces. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
a616e05 to
8bf63fe
Compare
- 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>
|
@greptile |
Add safety check before accessing firstDocument to prevent TypeError and data loss if createDocumentRecords unexpectedly returns empty. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@greptile |
- Use if/else so filename lookup only runs when no documentId is provided, preventing stale IDs from silently replacing unrelated documents - Check utf8 byte length instead of character count for 1MB size limit, correctly handling multi-byte characters (CJK, emoji) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@greptile |
- Add compensating rollback: if deleteDocument throws after create succeeds, clean up the new record to prevent orphaned pending docs - Merge duplicate name/content sub-blocks into single entries with array conditions, matching the documentTags pattern Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(knowledge): add upsert document operation to Knowledge block Add a "Create or Update" (upsert) document capability that finds an existing document by ID or filename, deletes it if found, then creates a new document and queues re-processing. Includes new tool, API route, block wiring, and typed interfaces. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * 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> * fix(knowledge): guard against empty createDocumentRecords result Add safety check before accessing firstDocument to prevent TypeError and data loss if createDocumentRecords unexpectedly returns empty. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(knowledge): prevent documentId fallthrough and use byte-count limit - Use if/else so filename lookup only runs when no documentId is provided, preventing stale IDs from silently replacing unrelated documents - Check utf8 byte length instead of character count for 1MB size limit, correctly handling multi-byte characters (CJK, emoji) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(knowledge): rollback on delete failure, deduplicate sub-block IDs - Add compensating rollback: if deleteDocument throws after create succeeds, clean up the new record to prevent orphaned pending docs - Merge duplicate name/content sub-blocks into single entries with array conditions, matching the documentTags pattern Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * lint * lint Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

Summary
knowledge_upsert_documenttool that creates or updates a document in a knowledge base/api/knowledge/[id]/documents/upsertwith auth, write access checks, Zod validation, audit logging, and background processingKnowledgeUpsertDocumentParams) and response interfaces following the add-tools skill conventionsContext
The Knowledge Block previously had no way to update an entire document — only individual chunks could be modified. Users wanting to maintain a knowledge base with source document changes had to manually delete and re-create documents. This adds a proper upsert flow.
Test plan
documentId— verify lookup by ID works