diff --git a/apps/sim/lib/knowledge/connectors/sync-engine.test.ts b/apps/sim/lib/knowledge/connectors/sync-engine.test.ts index 23e5d5fa564..dbb58359347 100644 --- a/apps/sim/lib/knowledge/connectors/sync-engine.test.ts +++ b/apps/sim/lib/knowledge/connectors/sync-engine.test.ts @@ -515,6 +515,23 @@ describe('classifyExternalDoc', () => { ).toEqual({ type: 'update', existingId: 'doc-1' }) }) + it('uses the same skip replacement rule after deferred hydration', async () => { + const { shouldReplaceExistingWithSkippedDocument } = await import( + '@/lib/knowledge/connectors/sync-engine' + ) + + expect(shouldReplaceExistingWithSkippedDocument({ storageKey: null }, {})).toBe(true) + expect(shouldReplaceExistingWithSkippedDocument({ storageKey: 'kb/indexed.txt' }, {})).toBe( + false + ) + expect( + shouldReplaceExistingWithSkippedDocument( + { storageKey: 'kb/indexed.txt' }, + { skippedExistingDisposition: 'replace' } + ) + ).toBe(true) + }) + it('replaces stale indexed content for an authoritative skip', async () => { const { classifyExternalDoc } = await import('@/lib/knowledge/connectors/sync-engine') diff --git a/apps/sim/lib/knowledge/connectors/sync-engine.ts b/apps/sim/lib/knowledge/connectors/sync-engine.ts index 84d890db819..bdca8b716f0 100644 --- a/apps/sim/lib/knowledge/connectors/sync-engine.ts +++ b/apps/sim/lib/knowledge/connectors/sync-engine.ts @@ -454,6 +454,13 @@ type DocClassification = | { type: 'unchanged' } | { type: 'drop' } +export function shouldReplaceExistingWithSkippedDocument( + existing: { storageKey?: string | null }, + skipped: Pick +): boolean { + return existing.storageKey === null || skipped.skippedExistingDisposition === 'replace' +} + /** * Decides what a listed external document becomes during reconciliation. * @@ -487,7 +494,7 @@ export function classifyExternalDoc( ): DocClassification { if (extDoc.skippedReason) { if (!existing) return { type: 'skip' } - return existing.storageKey === null || extDoc.skippedExistingDisposition === 'replace' + return shouldReplaceExistingWithSkippedDocument(existing, extDoc) ? { type: 'skip', existingId: existing.id } : { type: 'unchanged' } } @@ -2377,7 +2384,8 @@ export async function executeSync( extDoc: mergeHydratedSkippedDocument(op.extDoc, fullDoc), }) } else if (op.type === 'update') { - if (fullDoc.skippedExistingDisposition === 'replace') { + const existing = priorByExternalId.get(op.extDoc.externalId) + if (existing && shouldReplaceExistingWithSkippedDocument(existing, fullDoc)) { skipOps.push({ type: 'skip', existingId: op.existingId,