Skip to content

Commit f1e56fa

Browse files
committed
Merge remote-tracking branch 'origin/staging' into feat/docs-reorg
2 parents dedd5bb + efa4f27 commit f1e56fa

9 files changed

Lines changed: 401 additions & 133 deletions

File tree

apps/docs/components/icons.tsx

Lines changed: 103 additions & 56 deletions
Large diffs are not rendered by default.

apps/docs/content/docs/en/integrations/onepassword.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
77

88
<BlockInfoCard
99
type="onepassword"
10-
color="#145FE4"
10+
color="#FFFFFF"
1111
/>
1212

1313
{/* MANUAL-CONTENT-START:intro */}

apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-filter/table-filter.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import {
1111
DropdownMenuTrigger,
1212
} from '@/components/emcn'
1313
import { ChevronDown, Plus } from '@/components/emcn/icons'
14-
import type { Filter, FilterRule } from '@/lib/table'
14+
import type { ColumnDefinition, Filter, FilterRule } from '@/lib/table'
15+
import { getColumnId } from '@/lib/table/column-keys'
1516
import { COMPARISON_OPERATORS, VALUELESS_OPERATORS } from '@/lib/table/query-builder/constants'
1617
import { filterRulesToFilter, filterToRules } from '@/lib/table/query-builder/converters'
1718

@@ -20,7 +21,7 @@ const OPERATOR_LABELS = Object.fromEntries(
2021
) as Record<string, string>
2122

2223
interface TableFilterProps {
23-
columns: Array<{ name: string; type: string }>
24+
columns: ColumnDefinition[]
2425
filter: Filter | null
2526
onApply: (filter: Filter | null) => void
2627
onClose: () => void
@@ -35,8 +36,9 @@ export function TableFilter({ columns, filter, onApply, onClose }: TableFilterPr
3536
const rulesRef = useRef(rules)
3637
rulesRef.current = rules
3738

39+
// `value` is the filter field key (column id); `label` is what the user sees.
3840
const columnOptions = useMemo(
39-
() => columns.map((col) => ({ value: col.name, label: col.name })),
41+
() => columns.map((col) => ({ value: getColumnId(col), label: col.name })),
4042
[columns]
4143
)
4244

@@ -164,7 +166,9 @@ const FilterRuleRow = memo(function FilterRuleRow({
164166
<DropdownMenu>
165167
<DropdownMenuTrigger asChild>
166168
<button className='flex h-[28px] min-w-[100px] items-center justify-between rounded-[5px] border border-[var(--border)] bg-transparent px-2 text-[var(--text-secondary)] text-xs outline-none hover-hover:border-[var(--border-1)]'>
167-
<span className='truncate'>{rule.column || 'Column'}</span>
169+
<span className='truncate'>
170+
{columns.find((col) => col.value === rule.column)?.label || rule.column || 'Column'}
171+
</span>
168172
<ChevronDown className='ml-1 size-[10px] shrink-0 text-[var(--text-icon)]' />
169173
</button>
170174
</DropdownMenuTrigger>
@@ -224,11 +228,11 @@ const FilterRuleRow = memo(function FilterRuleRow({
224228
)
225229
})
226230

227-
function createRule(columns: Array<{ name: string }>): FilterRule {
231+
function createRule(columns: ColumnDefinition[]): FilterRule {
228232
return {
229233
id: generateShortId(),
230234
logicalOperator: 'and',
231-
column: columns[0]?.name ?? '',
235+
column: columns[0] ? getColumnId(columns[0]) : '',
232236
operator: 'eq',
233237
value: '',
234238
}

apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -740,7 +740,9 @@ export function Table({
740740
<>
741741
Are you sure you want to delete{' '}
742742
<span className='font-medium text-[var(--text-primary)]'>
743-
{deletingColumns?.[0]}
743+
{(deletingColumns &&
744+
columns.find((c) => getColumnId(c) === deletingColumns[0])?.name) ??
745+
deletingColumns?.[0]}
744746
</span>
745747
?{' '}
746748
</>

apps/sim/blocks/blocks/onepassword.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export const OnePasswordBlock: BlockConfig = {
1010
docsLink: 'https://docs.sim.ai/tools/onepassword',
1111
category: 'tools',
1212
integrationType: IntegrationType.Security,
13-
bgColor: '#145FE4',
13+
bgColor: '#FFFFFF',
1414
icon: OnePasswordIcon,
1515
authMode: AuthMode.ApiKey,
1616

apps/sim/components/icons.tsx

Lines changed: 103 additions & 56 deletions
Large diffs are not rendered by default.

apps/sim/lib/integrations/integrations.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"name": "1Password",
66
"description": "Manage secrets and items in 1Password vaults",
77
"longDescription": "Access and manage secrets stored in 1Password vaults using the Connect API or Service Account SDK. List vaults, retrieve items with their fields and secrets, create new items, update existing ones, delete items, and resolve secret references.",
8-
"bgColor": "#145FE4",
8+
"bgColor": "#FFFFFF",
99
"iconName": "OnePasswordIcon",
1010
"docsUrl": "https://docs.sim.ai/tools/onepassword",
1111
"operations": [

apps/sim/providers/utils.test.ts

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {
3838
supportsThinking,
3939
supportsToolUsageControl,
4040
supportsVerbosity,
41+
transformBlockTool,
4142
updateOllamaProviderModels,
4243
} from '@/providers/utils'
4344

@@ -1514,3 +1515,130 @@ describe('Provider/Model Blacklist', () => {
15141515
})
15151516
})
15161517
})
1518+
1519+
describe('transformBlockTool multi-instance unique IDs', () => {
1520+
const tableBlockDef = {
1521+
type: 'table',
1522+
inputs: {},
1523+
subBlocks: [
1524+
{ id: 'operation', type: 'dropdown' },
1525+
{ id: 'tableSelector', type: 'table-selector', canonicalParamId: 'tableId', mode: 'basic' },
1526+
{
1527+
id: 'manualTableId',
1528+
type: 'short-input',
1529+
canonicalParamId: 'tableId',
1530+
mode: 'advanced',
1531+
},
1532+
],
1533+
tools: {
1534+
access: ['table_query_rows', 'table_insert_row'],
1535+
config: { tool: () => 'table_query_rows' },
1536+
},
1537+
}
1538+
1539+
const getAllBlocks = () => [tableBlockDef]
1540+
const getTool = (id: string) => ({
1541+
id,
1542+
name: 'Query Rows',
1543+
description: 'Query table rows',
1544+
params: {},
1545+
})
1546+
1547+
const transformTable = (
1548+
params: Record<string, unknown>,
1549+
canonicalModes?: Record<string, 'basic' | 'advanced'>
1550+
) =>
1551+
transformBlockTool(
1552+
{ type: 'table', operation: 'query_rows', params },
1553+
{ selectedOperation: 'query_rows', getAllBlocks, getTool, canonicalModes }
1554+
)
1555+
1556+
it('appends the table id when stored under the basic selector subblock key', async () => {
1557+
const result = await transformTable({ tableSelector: 'tbl_abc' })
1558+
expect(result?.id).toBe('table_query_rows_tbl_abc')
1559+
})
1560+
1561+
it('appends the table id resolved from the advanced manual input', async () => {
1562+
const result = await transformTable(
1563+
{ manualTableId: 'tbl_xyz' },
1564+
{ 'table:tableId': 'advanced' }
1565+
)
1566+
expect(result?.id).toBe('table_query_rows_tbl_xyz')
1567+
})
1568+
1569+
it('appends the canonical table id when already present in params', async () => {
1570+
const result = await transformTable({ tableId: 'tbl_direct' })
1571+
expect(result?.id).toBe('table_query_rows_tbl_direct')
1572+
})
1573+
1574+
it('falls back to the base tool id when no table is selected', async () => {
1575+
const result = await transformTable({})
1576+
expect(result?.id).toBe('table_query_rows')
1577+
})
1578+
})
1579+
1580+
describe('transformBlockTool knowledge-base multi-instance unique IDs', () => {
1581+
const knowledgeBlockDef = {
1582+
type: 'knowledge',
1583+
inputs: {},
1584+
subBlocks: [
1585+
{ id: 'operation', type: 'dropdown' },
1586+
{
1587+
id: 'knowledgeBaseSelector',
1588+
type: 'knowledge-base-selector',
1589+
canonicalParamId: 'knowledgeBaseId',
1590+
mode: 'basic',
1591+
},
1592+
{
1593+
id: 'manualKnowledgeBaseId',
1594+
type: 'short-input',
1595+
canonicalParamId: 'knowledgeBaseId',
1596+
mode: 'advanced',
1597+
},
1598+
],
1599+
tools: {
1600+
access: ['knowledge_search', 'knowledge_upload_chunk'],
1601+
config: { tool: () => 'knowledge_search' },
1602+
},
1603+
}
1604+
1605+
const getAllBlocks = () => [knowledgeBlockDef]
1606+
const getTool = (id: string) => ({
1607+
id,
1608+
name: 'Search',
1609+
description: 'Search the knowledge base',
1610+
params: {},
1611+
})
1612+
1613+
const transformKb = (
1614+
params: Record<string, unknown>,
1615+
canonicalModes?: Record<string, 'basic' | 'advanced'>
1616+
) =>
1617+
transformBlockTool(
1618+
{ type: 'knowledge', operation: 'search', params },
1619+
{ selectedOperation: 'search', getAllBlocks, getTool, canonicalModes }
1620+
)
1621+
1622+
it('appends the knowledge base id when stored under the basic selector subblock key', async () => {
1623+
const result = await transformKb({ knowledgeBaseSelector: 'kb_abc' })
1624+
expect(result?.id).toBe('knowledge_search_kb_abc')
1625+
})
1626+
1627+
it('appends the knowledge base id resolved from the advanced manual input', async () => {
1628+
const result = await transformKb(
1629+
{ manualKnowledgeBaseId: 'kb_xyz' },
1630+
{ 'knowledge:knowledgeBaseId': 'advanced' }
1631+
)
1632+
expect(result?.id).toBe('knowledge_search_kb_xyz')
1633+
})
1634+
1635+
it('appends the canonical knowledge base id when already present in params', async () => {
1636+
const result = await transformKb({ knowledgeBaseId: 'kb_direct' })
1637+
expect(result?.id).toBe('knowledge_search_kb_direct')
1638+
})
1639+
1640+
it('falls back to the base tool id when no knowledge base is selected', async () => {
1641+
const result = await transformKb({})
1642+
expect(result?.id).toBe('knowledge_search')
1643+
})
1644+
})

apps/sim/providers/utils.ts

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,39 @@ export function extractAndParseJSON(content: string): any {
473473
}
474474
}
475475

476+
/**
477+
* Resolves canonical pair ids (e.g. `tableId`, `knowledgeBaseId`) from a tool's
478+
* raw params, filling them in from their basic/advanced selector subblock source
479+
* values when the canonical key isn't already present.
480+
*
481+
* Selector subblocks persist their value under the subblock id (e.g.
482+
* `tableSelector`), not the canonical id, so any lookup that keys off the
483+
* canonical id — like the unique-tool-id suffix below — must resolve it first.
484+
* Mode selection mirrors {@link transformBlockTool}'s execution-time
485+
* `paramsTransform` so the resolved id matches the params the tool actually runs
486+
* with.
487+
*
488+
* @returns The params with canonical resource ids resolved (non-destructive)
489+
*/
490+
function resolveCanonicalResourceParams(
491+
params: Record<string, any>,
492+
canonicalGroups: CanonicalGroup[],
493+
blockType: string,
494+
canonicalModes?: Record<string, 'basic' | 'advanced'>
495+
): Record<string, any> {
496+
if (canonicalGroups.length === 0) return params
497+
const resolved = { ...params }
498+
for (const group of canonicalGroups) {
499+
const existing = resolved[group.canonicalId]
500+
if (existing !== undefined && existing !== null && existing !== '') continue
501+
const { basicValue, advancedValue } = getCanonicalValues(group, params)
502+
const pairMode = canonicalModes?.[`${blockType}:${group.canonicalId}`] ?? 'basic'
503+
const chosen = pairMode === 'advanced' ? advancedValue : basicValue
504+
if (chosen !== undefined) resolved[group.canonicalId] = chosen
505+
}
506+
return resolved
507+
}
508+
476509
/**
477510
* Transforms a block tool into a provider tool config with operation selection
478511
*
@@ -549,14 +582,25 @@ export async function transformBlockTool(
549582
userProvidedParams
550583
)
551584

585+
const canonicalGroups: CanonicalGroup[] = blockDef?.subBlocks
586+
? Object.values(buildCanonicalIndex(blockDef.subBlocks).groupsById).filter(isCanonicalPair)
587+
: []
588+
589+
const resolvedResourceParams = resolveCanonicalResourceParams(
590+
userProvidedParams,
591+
canonicalGroups,
592+
block.type,
593+
canonicalModes
594+
)
595+
552596
let uniqueToolId = toolConfig.id
553597
let toolName = toolConfig.name
554598
let toolDescription = enrichedDescription || toolConfig.description
555599

556-
if (toolId === 'workflow_executor' && userProvidedParams.workflowId) {
557-
uniqueToolId = `${toolConfig.id}_${userProvidedParams.workflowId}`
600+
if (toolId === 'workflow_executor' && resolvedResourceParams.workflowId) {
601+
uniqueToolId = `${toolConfig.id}_${resolvedResourceParams.workflowId}`
558602

559-
const workflowMetadata = await fetchWorkflowMetadata(userProvidedParams.workflowId)
603+
const workflowMetadata = await fetchWorkflowMetadata(resolvedResourceParams.workflowId)
560604
if (workflowMetadata) {
561605
toolName = workflowMetadata.name || toolConfig.name
562606
if (
@@ -566,21 +610,17 @@ export async function transformBlockTool(
566610
toolDescription = workflowMetadata.description
567611
}
568612
}
569-
} else if (toolId.startsWith('knowledge_') && userProvidedParams.knowledgeBaseId) {
570-
uniqueToolId = `${toolConfig.id}_${userProvidedParams.knowledgeBaseId}`
571-
} else if (toolId.startsWith('table_') && userProvidedParams.tableId) {
572-
uniqueToolId = `${toolConfig.id}_${userProvidedParams.tableId}`
613+
} else if (toolId.startsWith('knowledge_') && resolvedResourceParams.knowledgeBaseId) {
614+
uniqueToolId = `${toolConfig.id}_${resolvedResourceParams.knowledgeBaseId}`
615+
} else if (toolId.startsWith('table_') && resolvedResourceParams.tableId) {
616+
uniqueToolId = `${toolConfig.id}_${resolvedResourceParams.tableId}`
573617
}
574618

575619
const blockParamsFn = blockDef?.tools?.config?.params as
576620
| ((p: Record<string, any>) => Record<string, any>)
577621
| undefined
578622
const blockInputDefs = blockDef?.inputs as Record<string, any> | undefined
579623

580-
const canonicalGroups: CanonicalGroup[] = blockDef?.subBlocks
581-
? Object.values(buildCanonicalIndex(blockDef.subBlocks).groupsById).filter(isCanonicalPair)
582-
: []
583-
584624
const needsTransform = blockParamsFn || blockInputDefs || canonicalGroups.length > 0
585625
const paramsTransform = needsTransform
586626
? (params: Record<string, any>): Record<string, any> => {

0 commit comments

Comments
 (0)