Skip to content

Commit 28ccfb3

Browse files
committed
fix(v2): drop an inert field from the document tag-filter scope
resolveKnowledgeTagFilters builds every structured filter with the stored definition's fieldType and never reads the caller's — not for resolution, not for validation, not in its output. Fingerprinting it made a field the query ignores decide whether a cursor resumes, so adding or removing a matching fieldType refused a page that had not moved. Swept the other twelve cursor-scope routes for the same shape. No scope part is absent from its mapInput, this was the only scope carrying a structure resolved against stored state, and knowledge/search has no cursor at all. Reported by Greptile.
1 parent b78a640 commit 28ccfb3

2 files changed

Lines changed: 13 additions & 1 deletion

File tree

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,10 @@ describe('GET /api/v2/knowledge/[id]/documents', () => {
409409
'the default operator stated explicitly',
410410
'[{"tagName":"a","value":"1","operator":"eq"},{"tagName":"b","value":"2","operator":"eq"}]',
411411
],
412+
[
413+
'a fieldType the resolver overrides with the stored definition',
414+
'[{"tagName":"a","value":"1","fieldType":"text"},{"tagName":"b","value":"2","fieldType":"text"}]',
415+
],
412416
['the clauses reordered', '[{"tagName":"b","value":"2"},{"tagName":"a","value":"1"}]'],
413417
])('resumes a tag-filter cursor with %s', async (_label, replayFilters) => {
414418
const mintFilters = '[{"tagName":"a","value":"1"},{"tagName":"b","value":"2"}]'

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { omit } from '@sim/utils/object'
12
import {
23
parseV2KnowledgeTagFiltersParam,
34
v2BulkUpdateKnowledgeDocumentsContract,
@@ -47,6 +48,11 @@ const MAX_FILE_SIZE = MAX_KNOWLEDGE_DOCUMENT_FILE_SIZE
4748
* schema defaults `operator` to `eq`, so `{tagName}` and `{tagName, operator}`
4849
* are one filter to the query and must be one scope to the cursor. An
4950
* unparseable value binds raw — that request is about to 400 anyway.
51+
*
52+
* `fieldType` is dropped: `resolveKnowledgeTagFilters` builds every structured
53+
* filter with the stored definition's type and never reads the caller's, so
54+
* stating it or omitting it selects the same documents. A scope part the query
55+
* ignores refuses a cursor for a page that did not move.
5056
*/
5157
function documentCursorFilters(
5258
knowledgeBaseId: string,
@@ -58,7 +64,9 @@ function documentCursorFilters(
5864
workspaceId: query.workspaceId,
5965
enabledFilter: query.enabledFilter,
6066
search: query.search,
61-
tagFilters: parsed.success ? unorderedScopeOf(parsed.filters) : query.tagFilters,
67+
tagFilters: parsed.success
68+
? unorderedScopeOf(parsed.filters?.map((filter) => omit(filter, ['fieldType'])))
69+
: query.tagFilters,
6270
})
6371
}
6472

0 commit comments

Comments
 (0)