Skip to content

Commit ce77755

Browse files
fix(copilot): honor preview availability server-side
1 parent b444246 commit ce77755

19 files changed

Lines changed: 145 additions & 51 deletions

apps/sim/lib/copilot/chat/payload.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ vi.mock('@/lib/uploads/contexts/workspace/workspace-file-manager', () => ({
129129
}))
130130

131131
vi.mock('@/lib/integrations/availability.server', () => ({
132-
isIntegrationDeploymentAvailable: mockIsIntegrationDeploymentAvailable,
132+
isIntegrationDeploymentAvailableForVisibility: mockIsIntegrationDeploymentAvailable,
133133
isOAuthServiceDeploymentAvailable: mockIsOAuthServiceDeploymentAvailable,
134134
}))
135135

apps/sim/lib/copilot/chat/payload.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {
2323
isHosted,
2424
} from '@/lib/core/config/env-flags'
2525
import {
26-
isIntegrationDeploymentAvailable,
26+
isIntegrationDeploymentAvailableForVisibility,
2727
isOAuthServiceDeploymentAvailable,
2828
} from '@/lib/integrations/availability.server'
2929
import { trackChatUpload } from '@/lib/uploads/contexts/workspace/workspace-file-manager'
@@ -223,7 +223,7 @@ async function buildIntegrationToolSchemasUncached(
223223
getExposedIntegrationTools(),
224224
vis,
225225
(owner) =>
226-
isIntegrationDeploymentAvailable(owner.blockType) &&
226+
isIntegrationDeploymentAvailableForVisibility(owner.blockType, vis) &&
227227
(allowedIntegrationTypes === null ||
228228
allowedIntegrationTypes.has(owner.blockType.toLowerCase()))
229229
)

apps/sim/lib/copilot/chat/process-contents.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const {
1919
getWorkspaceFile,
2020
getTableById,
2121
getRowsByIds,
22+
getBlockVisibilityForCopilot,
2223
isIntegrationDeploymentAvailable,
2324
} = vi.hoisted(() => ({
2425
discoverServerTools: vi.fn(),
@@ -29,13 +30,15 @@ const {
2930
getWorkspaceFile: vi.fn(),
3031
getTableById: vi.fn(),
3132
getRowsByIds: vi.fn(),
33+
getBlockVisibilityForCopilot: vi.fn(async () => null),
3234
isIntegrationDeploymentAvailable: vi.fn(() => true),
3335
}))
3436

3537
vi.mock('@/blocks/registry', () => ({ getBlock, getBlockRegistry }))
38+
vi.mock('@/lib/copilot/block-visibility', () => ({ getBlockVisibilityForCopilot }))
3639
vi.mock('@/ee/access-control/utils/permission-check', () => ({ getUserPermissionConfig }))
3740
vi.mock('@/lib/integrations/availability.server', () => ({
38-
isIntegrationDeploymentAvailable,
41+
isIntegrationDeploymentAvailableForVisibility: isIntegrationDeploymentAvailable,
3942
}))
4043
vi.mock('@/lib/workflows/skills/operations', () => ({ getSkillById }))
4144
vi.mock('@/lib/mcp/service', () => ({ mcpService: { discoverServerTools } }))

apps/sim/lib/copilot/chat/process-contents.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
getActiveWorkflowRecord,
77
} from '@sim/platform-authz/workflow'
88
import { and, eq, isNull, ne } from 'drizzle-orm'
9+
import { getBlockVisibilityForCopilot } from '@/lib/copilot/block-visibility'
910
import {
1011
MAX_TABLE_SELECTION_CONTENT_LENGTH,
1112
truncateSelectionText,
@@ -24,7 +25,7 @@ import {
2425
} from '@/lib/copilot/vfs/path-utils'
2526
import { EnvCapabilityConfigurationError } from '@/lib/core/config/env-capabilities'
2627
import { getAllowedIntegrationsFromEnv } from '@/lib/core/config/env-flags'
27-
import { isIntegrationDeploymentAvailable } from '@/lib/integrations/availability.server'
28+
import { isIntegrationDeploymentAvailableForVisibility } from '@/lib/integrations/availability.server'
2829
import { toOverview } from '@/lib/logs/log-views'
2930
import type { TraceSpan } from '@/lib/logs/types'
3031
import { mcpService } from '@/lib/mcp/service'
@@ -573,11 +574,13 @@ async function processBlockMetadata(
573574
workspaceId?: string
574575
): Promise<AgentContext | null> {
575576
try {
576-
const permissionConfig =
577-
userId && workspaceId ? await getUserPermissionConfig(userId, workspaceId) : null
577+
const [permissionConfig, visibility] = await Promise.all([
578+
userId && workspaceId ? getUserPermissionConfig(userId, workspaceId) : null,
579+
userId ? getBlockVisibilityForCopilot(userId, workspaceId) : null,
580+
])
578581
const allowedIntegrations =
579582
permissionConfig?.allowedIntegrations ?? getAllowedIntegrationsFromEnv()
580-
if (!isIntegrationDeploymentAvailable(blockId)) {
583+
if (!isIntegrationDeploymentAvailableForVisibility(blockId, visibility)) {
581584
logger.debug('Block unavailable for this deployment', { blockId })
582585
return null
583586
}

apps/sim/lib/copilot/tools/handlers/integration-tools.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
} from '@/lib/copilot/integration-tools'
66
import type { ExecutionContext, ToolCallResult } from '@/lib/copilot/request/types'
77
import { getAllowedIntegrationsFromEnv } from '@/lib/core/config/env-flags'
8-
import { isIntegrationDeploymentAvailable } from '@/lib/integrations/availability.server'
8+
import { isIntegrationDeploymentAvailableForVisibility } from '@/lib/integrations/availability.server'
99
import { getUserPermissionConfig } from '@/ee/access-control/utils/permission-check'
1010
import { stripVersionSuffix } from '@/tools/utils'
1111

@@ -30,7 +30,7 @@ export async function executeListIntegrationTools(
3030
getExposedIntegrationTools(),
3131
vis,
3232
(owner) =>
33-
isIntegrationDeploymentAvailable(owner.blockType) &&
33+
isIntegrationDeploymentAvailableForVisibility(owner.blockType, vis) &&
3434
(allowedIntegrations === null || allowedIntegrations.includes(owner.blockType.toLowerCase()))
3535
)
3636
const service = stripVersionSuffix(raw.toLowerCase())

apps/sim/lib/copilot/tools/server/blocks/get-blocks-metadata-tool.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ vi.mock('@/ee/access-control/utils/permission-check', () => ({
1414
}))
1515

1616
vi.mock('@/lib/integrations/availability.server', () => ({
17-
isIntegrationDeploymentAvailable: mockIsIntegrationDeploymentAvailable,
17+
isIntegrationDeploymentAvailableForVisibility: mockIsIntegrationDeploymentAvailable,
1818
}))
1919

2020
import {

apps/sim/lib/copilot/tools/server/blocks/get-blocks-metadata-tool.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { z } from 'zod'
66
import { getCopilotToolDescription } from '@/lib/copilot/tools/descriptions'
77
import type { BaseServerTool } from '@/lib/copilot/tools/server/base-tool'
88
import { getAllowedIntegrationsFromEnv, isHosted } from '@/lib/core/config/env-flags'
9-
import { isIntegrationDeploymentAvailable } from '@/lib/integrations/availability.server'
9+
import { isIntegrationDeploymentAvailableForVisibility } from '@/lib/integrations/availability.server'
1010
import { getServiceAccountProviderForProviderId } from '@/lib/oauth/utils'
1111
import { isBlockTypeAccessControlExempt } from '@/lib/permission-groups/block-access'
1212
import { isCustomBlockType } from '@/blocks/custom/build-config'
@@ -128,11 +128,12 @@ export const getBlocksMetadataServerTool: BaseServerTool<
128128
: null
129129
const allowedIntegrations =
130130
permissionConfig?.allowedIntegrations ?? getAllowedIntegrationsFromEnv()
131+
const visibility = overlayVisibility()
131132

132133
const result: Record<string, CopilotBlockMetadata> = {}
133134
for (const blockId of blockIds || []) {
134135
const specialBlock = SPECIAL_BLOCKS_METADATA[blockId]
135-
if (!isIntegrationDeploymentAvailable(blockId)) {
136+
if (!isIntegrationDeploymentAvailableForVisibility(blockId, visibility)) {
136137
logger.debug('Block unavailable for this deployment', { blockId })
137138
continue
138139
}
@@ -181,7 +182,7 @@ export const getBlocksMetadataServerTool: BaseServerTool<
181182
// explicitly: unrevealed preview blocks and kill-switched types stay
182183
// out of the agent's metadata (the router wraps this tool in
183184
// withBlockVisibility).
184-
if (isHiddenUnder(overlayVisibility(), blockConfig)) {
185+
if (isHiddenUnder(visibility, blockConfig)) {
185186
logger.debug('Skipping block gated by visibility', { blockId })
186187
continue
187188
}

apps/sim/lib/copilot/tools/server/blocks/get-trigger-blocks.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ vi.mock('@/ee/access-control/utils/permission-check', () => ({
2626
}))
2727

2828
vi.mock('@/lib/integrations/availability.server', () => ({
29-
isIntegrationDeploymentAvailable: mockIsIntegrationDeploymentAvailable,
29+
isIntegrationDeploymentAvailableForVisibility: mockIsIntegrationDeploymentAvailable,
3030
}))
3131

3232
import { getTriggerBlocksServerTool } from '@/lib/copilot/tools/server/blocks/get-trigger-blocks'

apps/sim/lib/copilot/tools/server/blocks/get-trigger-blocks.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ import { createLogger } from '@sim/logger'
22
import { z } from 'zod'
33
import type { BaseServerTool } from '@/lib/copilot/tools/server/base-tool'
44
import { getAllowedIntegrationsFromEnv } from '@/lib/core/config/env-flags'
5-
import { isIntegrationDeploymentAvailable } from '@/lib/integrations/availability.server'
5+
import { isIntegrationDeploymentAvailableForVisibility } from '@/lib/integrations/availability.server'
66
import { isBlockTypeAccessControlExempt } from '@/lib/permission-groups/block-access'
77
import { getAllBlocks } from '@/blocks/registry'
8+
import { overlayVisibility } from '@/blocks/visibility/context'
89
import { getUserPermissionConfig } from '@/ee/access-control/utils/permission-check'
910

1011
export const GetTriggerBlocksInput = z.object({})
@@ -29,13 +30,14 @@ export const getTriggerBlocksServerTool: BaseServerTool<
2930
: null
3031
const allowedIntegrations =
3132
permissionConfig?.allowedIntegrations ?? getAllowedIntegrationsFromEnv()
33+
const visibility = overlayVisibility()
3234

3335
const triggerBlockIds: string[] = []
3436

3537
for (const blockConfig of getAllBlocks()) {
3638
const blockType = blockConfig.type
3739
if (blockConfig.hideFromToolbar) continue
38-
if (!isIntegrationDeploymentAvailable(blockType)) continue
40+
if (!isIntegrationDeploymentAvailableForVisibility(blockType, visibility)) continue
3941
if (
4042
allowedIntegrations != null &&
4143
!isBlockTypeAccessControlExempt(blockType) &&

apps/sim/lib/copilot/tools/server/router.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,16 @@ const logger = createLogger('ServerToolRouter')
7474
const CUSTOM_BLOCK_OVERLAY_TOOLS = new Set(['edit_workflow', 'get_blocks_metadata'])
7575

7676
/**
77-
* DISCOVERY tools that must run inside the viewer's block-visibility context so
78-
* gated (preview / kill-switched) blocks disappear from what the agent can
79-
* list. Deliberately a DIFFERENT set from {@link CUSTOM_BLOCK_OVERLAY_TOOLS}:
80-
* `edit_workflow` is excluded because its registry use is functional
81-
* (find-by-type over clones, never a discovery listing) and gating it would
82-
* only risk leaking display projections into persisted state.
77+
* Discovery tools that consume the viewer's block-visibility context to hide
78+
* gated blocks and credentials. `edit_workflow` establishes a narrower scope
79+
* around operation validation after it resolves the workflow's actual
80+
* workspace.
8381
*/
84-
const VISIBILITY_GATED_TOOLS = new Set(['get_blocks_metadata', 'get_trigger_blocks'])
82+
const VISIBILITY_GATED_TOOLS = new Set([
83+
'get_blocks_metadata',
84+
'get_credentials',
85+
'get_trigger_blocks',
86+
])
8587

8688
const WRITE_ACTIONS: Record<string, string[]> = {
8789
[KnowledgeBase.id]: [

0 commit comments

Comments
 (0)