Skip to content

Commit 2d91e2a

Browse files
committed
fix(files): scope the picker from either half of the folder pair
1 parent 68ddc46 commit 2d91e2a

5 files changed

Lines changed: 41 additions & 3 deletions

File tree

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/file-upload/file-upload.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ interface FileUploadProps {
5252
* A sibling folder field that narrows what this picker offers, and the switch
5353
* saying whether that scope descends. See `SubBlockConfig.folderScope`.
5454
*/
55-
folderScope?: { fieldId: string; recursiveFieldId?: string }
55+
folderScope?: { fieldId: string; manualFieldId?: string; recursiveFieldId?: string }
5656
/**
5757
* Controlled value. When `onValueChange` is provided the component reads from
5858
* this prop and writes through `onValueChange` instead of the subblock store,
@@ -338,6 +338,16 @@ export function FileUpload({
338338
* scope reads as absent.
339339
*/
340340
const [folderScopeValue] = useSubBlockValue<unknown>(blockId, folderScope?.fieldId ?? subBlockId)
341+
/*
342+
* The advanced half of the same canonical pair. Values are stored per
343+
* sub-block id, so a scope typed into the advanced field lives under a
344+
* different key and reading only the basic one left the picker unscoped
345+
* while looking configured.
346+
*/
347+
const [manualFolderScopeValue] = useSubBlockValue<unknown>(
348+
blockId,
349+
folderScope?.manualFieldId ?? folderScope?.fieldId ?? subBlockId
350+
)
341351
const [folderScopeRecursive] = useSubBlockValue<unknown>(
342352
blockId,
343353
folderScope?.recursiveFieldId ?? subBlockId
@@ -348,7 +358,9 @@ export function FileUpload({
348358
* its literal text passes a string check and then matches no folder, so every
349359
* file is filtered out of a picker that looks correctly configured.
350360
*/
351-
const folderScopePath = folderScope ? readFolderPath(folderScopeValue) : ''
361+
const folderScopePath = folderScope
362+
? readFolderPath(folderScopeValue) || readFolderPath(manualFolderScopeValue)
363+
: ''
352364
const folderScopeIncludesSubfolders =
353365
!folderScope?.recursiveFieldId ||
354366
folderScopeRecursive === undefined ||

apps/sim/blocks/blocks.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ describe.concurrent('Blocks Module', () => {
197197
*/
198198
expect(block?.subBlocks.find((subBlock) => subBlock.id === 'readFile')?.folderScope).toEqual({
199199
fieldId: 'folderSelection',
200+
manualFieldId: 'manualFolderSelection',
200201
recursiveFieldId: 'folderIncludeSubfolders',
201202
})
202203
expect(

apps/sim/blocks/blocks/file-folders.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ describe('file_v5 folder operations produce contract-valid tool input', () => {
374374

375375
expect(picker?.folderScope).toEqual({
376376
fieldId: 'folderSelection',
377+
manualFieldId: 'manualFolderSelection',
377378
recursiveFieldId: 'folderIncludeSubfolders',
378379
})
379380
}
@@ -392,6 +393,21 @@ describe('file_v5 folder operations produce contract-valid tool input', () => {
392393
}
393394
)
394395

396+
/*
397+
* Sub-block values are stored per sub-block id, so a picker that reads only
398+
* the basic half is unscoped whenever the scope was typed into the advanced
399+
* one - configured-looking and silently wrong.
400+
*/
401+
it('names both halves of the folder pair so either can scope a picker', () => {
402+
const picker = FileV5Block.subBlocks.find((subBlock) => subBlock.id === 'readFile')
403+
404+
expect(picker?.folderScope).toEqual({
405+
fieldId: 'folderSelection',
406+
manualFieldId: 'manualFolderSelection',
407+
recursiveFieldId: 'folderIncludeSubfolders',
408+
})
409+
})
410+
395411
it('offers the folder on every operation whose picker it narrows', () => {
396412
const folder = FileV5Block.subBlocks.find((subBlock) => subBlock.id === 'folderSelection')
397413

apps/sim/blocks/blocks/file.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ const MOVE_TARGET_FIELD = ['moveTargetFolderPath', 'manualMoveTargetFolderPath']
108108
*/
109109
const FOLDER_SCOPE = {
110110
fieldId: 'folderSelection',
111+
manualFieldId: 'manualFolderSelection',
111112
recursiveFieldId: 'folderIncludeSubfolders',
112113
} as const
113114

apps/sim/blocks/types.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,15 @@ export interface SubBlockConfig {
299299
* whether the scope descends, so the picker and the run agree on how deep the
300300
* folder reaches.
301301
*/
302-
folderScope?: { fieldId: string; recursiveFieldId?: string }
302+
/**
303+
* Narrows this control's options to a folder chosen elsewhere on the block.
304+
*
305+
* `manualFieldId` is the advanced half of the same canonical pair. Sub-block
306+
* values are stored per sub-block id, not per canonical id, so reading only
307+
* `fieldId` leaves a scope typed into the advanced field invisible here and
308+
* the picker silently unscoped.
309+
*/
310+
folderScope?: { fieldId: string; manualFieldId?: string; recursiveFieldId?: string }
303311
/** Controls parameter visibility in agent/tool-input context */
304312
paramVisibility?: 'user-or-llm' | 'user-only' | 'llm-only' | 'hidden'
305313
/**

0 commit comments

Comments
 (0)