Skip to content

Commit bc09b56

Browse files
committed
fix(workflows): resolve tool references by active canonical mode and keep the reference cache live
- workflow_input tools inside tool-input now resolve basic/advanced via the index-scoped canonicalModes override, mirroring execution (Cursor finding) - staleTime back to 0: no mutation invalidates this key, so a reopen must background-refetch; on-demand mounting keeps the cached tree painting instantly (Greptile P1) - modal header uses the em-dash label-entity convention; tree items carry aria-level instead of a static aria-selected
1 parent 35bda23 commit bc09b56

5 files changed

Lines changed: 54 additions & 13 deletions

File tree

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/components/references-modal/components/reference-tree/reference-tree.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ interface ReferenceTreeItemProps {
2424

2525
function ReferenceTreeItem({ node, depth, onNavigate }: ReferenceTreeItemProps) {
2626
return (
27-
<div role='treeitem' aria-selected={false}>
27+
<div role='treeitem' aria-level={depth + 1}>
2828
<button
2929
type='button'
3030
onClick={() => onNavigate(node.id)}

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/components/references-modal/references-modal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export function ReferencesModal({
5151

5252
return (
5353
<ChipModal open onOpenChange={(next) => !next && onClose()} srTitle='References'>
54-
<ChipModalHeader onClose={onClose}>References · {workflowName}</ChipModalHeader>
54+
<ChipModalHeader onClose={onClose}>References {workflowName}</ChipModalHeader>
5555
<ChipModalBody>
5656
<ChipModalTabs
5757
tabs={TABS}

apps/sim/hooks/queries/workflow-references.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ import {
66
} from '@/lib/api/contracts/workflow-references'
77

88
/**
9-
* Short — the graph reflects live editor state (workflow blocks/names can change
10-
* between opens). The modal mounts on demand, so each open refetches once the
11-
* window lapses while still absorbing rapid open/close flapping.
9+
* Zero — the graph reflects live editor state, and no workflow-edit mutation
10+
* invalidates this key (edits arrive over the socket, not through React Query).
11+
* The modal mounts on demand, so every open refetches; a reopen paints the
12+
* cached tree instantly while the background refetch reconciles it.
1213
*/
13-
export const WORKFLOW_REFERENCES_STALE_TIME = 30 * 1000
14+
export const WORKFLOW_REFERENCES_STALE_TIME = 0
1415

1516
export const workflowReferenceKeys = {
1617
all: ['workflow-references'] as const,

apps/sim/lib/workflows/references/operations.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,25 @@ describe('resolveWorkflowReferences', () => {
198198
expect(bResult.callers.map((n) => n.id)).toEqual(['a'])
199199
})
200200

201+
it('resolves a workflow tool to its active advanced-mode value', () => {
202+
// Tool 0 is toggled to advanced via the index-scoped canonicalModes key; the
203+
// stale basic selector (`b`) must not mask the live manual value (`c`).
204+
const blocks: ReferenceBlockRow[] = [
205+
{
206+
parentId: 'a',
207+
type: 'agent',
208+
childFromSelector: null,
209+
childFromManual: null,
210+
canonicalModes: { '0:workflowId': 'advanced' },
211+
toolInputValues: [
212+
[{ type: 'workflow_input', params: { workflowId: 'b', manualWorkflowId: 'c' } }],
213+
],
214+
},
215+
]
216+
const { callees } = resolveWorkflowReferences('a', workflows, blocks, [])
217+
expect(callees.map((n) => n.id)).toEqual(['c'])
218+
})
219+
201220
it('resolves workflow tools from a JSON-stringified tool-input value', () => {
202221
const blocks: ReferenceBlockRow[] = [
203222
{

apps/sim/lib/workflows/references/operations.ts

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
type CanonicalGroup,
1010
type CanonicalModeOverrides,
1111
resolveActiveCanonicalValue,
12+
scopeCanonicalModesForTool,
1213
} from '@/lib/workflows/subblocks/visibility'
1314
import { CUSTOM_BLOCK_TYPE_PREFIX } from '@/blocks/custom/build-config'
1415
import { BlockType, isWorkflowBlockType } from '@/executor/constants'
@@ -85,20 +86,40 @@ interface ReferenceGraph {
8586

8687
/**
8788
* Callee workflow ids referenced by a block's tool-input values: `workflow_input`
88-
* tools whose `params.workflowId` was picked from the workflow selector.
89+
* tools resolved to their ACTIVE canonical member — the basic `params.workflowId`
90+
* selector or the advanced `params.manualWorkflowId` input, per the tool's
91+
* index-scoped `canonicalModes` override ({@link scopeCanonicalModesForTool}) —
92+
* mirroring how execution picks the live value.
8993
*/
90-
function toolInputCallees(toolInputValues: unknown[] | null): string[] {
94+
function toolInputCallees(
95+
toolInputValues: unknown[] | null,
96+
canonicalModes: CanonicalModeOverrides | null
97+
): string[] {
9198
if (!toolInputValues) return []
9299
const callees: string[] = []
93100
for (const value of toolInputValues) {
94101
const { array } = coerceObjectArray(value)
95102
if (!array) continue
96-
for (const tool of array) {
103+
array.forEach((tool, toolIndex) => {
97104
if (!isRecord(tool) || tool.type !== BlockType.WORKFLOW_INPUT || !isRecord(tool.params)) {
98-
continue
105+
return
99106
}
100-
if (typeof tool.params.workflowId === 'string') callees.push(tool.params.workflowId)
101-
}
107+
const scoped = scopeCanonicalModesForTool(
108+
canonicalModes ?? undefined,
109+
toolIndex,
110+
BlockType.WORKFLOW_INPUT
111+
)
112+
const active = resolveActiveCanonicalValue(
113+
WORKFLOW_ID_CANONICAL_GROUP,
114+
{
115+
workflowId: typeof tool.params.workflowId === 'string' ? tool.params.workflowId : null,
116+
manualWorkflowId:
117+
typeof tool.params.manualWorkflowId === 'string' ? tool.params.manualWorkflowId : null,
118+
},
119+
scoped
120+
)
121+
if (typeof active === 'string' && active) callees.push(active)
122+
})
102123
}
103124
return callees
104125
}
@@ -161,7 +182,7 @@ function buildReferenceGraph(
161182
const sourceId = sourceByCustomType.get(block.type)
162183
if (sourceId) addEdge(block.parentId, sourceId)
163184
}
164-
for (const calleeId of toolInputCallees(block.toolInputValues)) {
185+
for (const calleeId of toolInputCallees(block.toolInputValues, block.canonicalModes)) {
165186
addEdge(block.parentId, calleeId)
166187
}
167188
}

0 commit comments

Comments
 (0)