diff --git a/apps/sim/providers/utils.test.ts b/apps/sim/providers/utils.test.ts index c550b19dbcf..af00af7cc34 100644 --- a/apps/sim/providers/utils.test.ts +++ b/apps/sim/providers/utils.test.ts @@ -1622,7 +1622,7 @@ describe('transformBlockTool multi-instance unique IDs', () => { expect(result?.id).toBe('table_query_rows_tbl_abc') }) - it('resolves the canonical table id before enriching the LLM tool schema', async () => { + it('resolves the active table selector before enriching the LLM tool schema', async () => { const enrichTool = vi.fn( async ( tableId: string, @@ -1646,7 +1646,7 @@ describe('transformBlockTool multi-instance unique IDs', () => { { type: 'table', operation: 'query_rows', - params: { tableSelector: 'tbl_abc' }, + params: { tableId: 'tbl_stale', tableSelector: 'tbl_active' }, }, { selectedOperation: 'query_rows', @@ -1672,7 +1672,7 @@ describe('transformBlockTool multi-instance unique IDs', () => { ) expect(enrichTool).toHaveBeenCalledWith( - 'tbl_abc', + 'tbl_active', expect.objectContaining({ properties: expect.objectContaining({ filter: expect.any(Object) }), }), @@ -1683,15 +1683,16 @@ describe('transformBlockTool multi-instance unique IDs', () => { } ) expect(result).toMatchObject({ - id: 'table_query_rows_tbl_abc', - description: 'Query rows from tbl_abc', - params: { tableSelector: 'tbl_abc' }, + id: 'table_query_rows_tbl_active', + description: 'Query rows from tbl_active', + params: { tableId: 'tbl_stale', tableSelector: 'tbl_active' }, parameters: { properties: { customer_name: { type: 'string' }, }, }, }) + expect(result?.paramsTransform?.(result.params)).toEqual({ tableId: 'tbl_active' }) }) it('appends the table id resolved from the advanced manual input', async () => { @@ -1715,6 +1716,16 @@ describe('transformBlockTool multi-instance unique IDs', () => { expect(result?.id).toBe('table_query_rows_tbl_direct') }) + it('preserves the canonical table id when advanced mode is active', async () => { + const result = await transformTable( + { tableId: 'tbl_advanced', tableSelector: 'tbl_basic' }, + { '0:tableId': 'advanced' }, + 0 + ) + expect(result?.id).toBe('table_query_rows_tbl_advanced') + expect(result?.paramsTransform?.(result.params)).toEqual({ tableId: 'tbl_advanced' }) + }) + it('falls back to the base tool id when no table is selected', async () => { const result = await transformTable({}) expect(result?.id).toBe('table_query_rows') diff --git a/apps/sim/providers/utils.ts b/apps/sim/providers/utils.ts index 7d805394ea8..3563ced59ed 100644 --- a/apps/sim/providers/utils.ts +++ b/apps/sim/providers/utils.ts @@ -487,15 +487,16 @@ export function extractAndParseJSON(content: string): any { /** * Resolves canonical pair ids (e.g. `tableId`, `knowledgeBaseId`) from a tool's - * raw params, filling them in from their basic/advanced selector subblock source - * values when the canonical key isn't already present. + * raw params, preferring the active basic/advanced selector subblock source over + * a previously resolved canonical value. * * Selector subblocks persist their value under the subblock id (e.g. * `tableSelector`), not the canonical id, so any lookup that keys off the * canonical id — like the unique-tool-id suffix below — must resolve it first. * Mode selection mirrors {@link transformBlockTool}'s execution-time * `paramsTransform` so the resolved id matches the params the tool actually runs - * with. + * with. When the active selector has no value, the original canonical value is + * preserved for direct-id callers and nested tools in advanced mode. * * @returns The params with canonical resource ids resolved (non-destructive) */ @@ -507,8 +508,6 @@ function resolveCanonicalResourceParams( if (canonicalGroups.length === 0) return params const resolved = { ...params } for (const group of canonicalGroups) { - const existing = resolved[group.canonicalId] - if (existing !== undefined && existing !== null && existing !== '') continue // Route through the canonical SOT: an explicit scoped override wins, else the value heuristic - // no `?? 'basic'` (which ignored an advanced-only value when basic was empty). const explicitMode = scopedCanonicalModes?.[group.canonicalId]