Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { IntegrationCtaButton } from '@/app/(landing)/integrations/(shell)/[slug
import { IntegrationFAQ } from '@/app/(landing)/integrations/(shell)/[slug]/components/integration-faq'
import { TemplateCardButton } from '@/app/(landing)/integrations/(shell)/[slug]/components/template-card-button'
import { IntegrationIcon } from '@/app/(landing)/integrations/components/integration-icon'
import { getTemplatesForBlock } from '@/blocks/registry'
import { getTemplatesForBlock } from '@/blocks/manifest'

const allIntegrations = INTEGRATIONS
const INTEGRATION_COUNT = allIntegrations.length
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { AgentSkillsIcon } from '@/components/icons'
import { getDocumentIcon } from '@/components/icons/document-icons'
import type { ChatContextKind, ChatMessageContext } from '@/app/workspace/[workspaceId]/home/types'
import { getBareIconStyle } from '@/blocks/icon-color'
import { registry as blockRegistry } from '@/blocks/registry'
import { getBlockDisplay } from '@/blocks/manifest'

interface RenderIconArgs {
context: ChatMessageContext
Expand All @@ -39,7 +39,7 @@ function renderWorkflowIcon({ className }: RenderIconArgs): ReactNode | null {
function renderIntegrationTile({ context, className }: RenderIconArgs): ReactNode | null {
if (context.kind !== 'integration') return null
if (!context.blockType) return null
const block = blockRegistry[context.blockType]
const block = getBlockDisplay(context.blockType)
if (!block) return null
const Icon = block.icon
return <Icon className={className} style={getBareIconStyle(Icon)} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
getSuggestedSkillsForBlock,
getTemplatesForBlock,
type ScopedBlockTemplate,
} from '@/blocks/registry'
} from '@/blocks/manifest'
import { useWorkspaceCredentials } from '@/hooks/queries/credentials'
import { useOAuthReturnRouter } from '@/hooks/use-oauth-return'

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ComponentType } from 'react'
import { getBlock } from '@/blocks'
import { getBlockDisplay } from '@/blocks/manifest'

/**
* URL-encoded SVG used as a mask to carve the bottom-right notch out of the
Expand Down Expand Up @@ -48,7 +48,7 @@ const SHOWCASE_TILES = [
* Returns `null` when the block is unknown or has no brand color configured.
*/
function resolveBrandTileBg(blockType: string): string | null {
return getBlock(blockType)?.bgColor || null
return getBlockDisplay(blockType)?.bgColor || null
}

interface IntegrationTileProps {
Expand Down Expand Up @@ -119,7 +119,7 @@ export function IntegrationsShowcase() {
>
<div className='absolute inset-0 grid translate-x-[0.5px] translate-y-[0.5px] grid-cols-[repeat(auto-fill,48px)] grid-rows-[repeat(auto-fill,48px)]'>
{SHOWCASE_TILES.map((tile) => {
const block = getBlock(tile.id)
const block = getBlockDisplay(tile.id)
if (!block) return null
return (
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { SYNC_INTERVALS } from '@/app/workspace/[workspaceId]/knowledge/[id]/com
import { MaxBadge } from '@/app/workspace/[workspaceId]/knowledge/[id]/components/max-badge'
import { useConnectorConfigFields } from '@/app/workspace/[workspaceId]/knowledge/[id]/hooks/use-connector-config-fields'
import { isBillingEnabled } from '@/app/workspace/[workspaceId]/settings/navigation'
import { getBlock } from '@/blocks'
import { getBlockDisplay } from '@/blocks/manifest'
import { CONNECTOR_META_REGISTRY } from '@/connectors/registry'
import type { ConnectorMeta } from '@/connectors/types'
import { useCreateConnector } from '@/hooks/queries/kb/connectors'
Expand Down Expand Up @@ -459,7 +459,7 @@ interface ConnectorTypeCardProps {

function ConnectorTypeCard({ type, config, onClick }: ConnectorTypeCardProps) {
const Icon = config.icon
const brandBg = getBlock(type)?.bgColor ?? null
const brandBg = getBlockDisplay(type)?.bgColor ?? null

return (
<button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { getCanonicalScopesForProvider, getProviderIdFromServiceId } from '@/lib
import { getMissingRequiredScopes } from '@/lib/oauth/utils'
import { ConnectOAuthModal } from '@/app/workspace/[workspaceId]/components/connect-oauth-modal'
import { EditConnectorModal } from '@/app/workspace/[workspaceId]/knowledge/[id]/components/edit-connector-modal/edit-connector-modal'
import { getBlock } from '@/blocks'
import { getBlockDisplay } from '@/blocks/manifest'
import { CONNECTOR_META_REGISTRY } from '@/connectors/registry'
import type { ConnectorData, SyncLogData } from '@/hooks/queries/kb/connectors'
import {
Expand Down Expand Up @@ -296,7 +296,7 @@ function ConnectorCard({

const connectorDef = CONNECTOR_META_REGISTRY[connector.connectorType]
const Icon = connectorDef?.icon
const brandBg = getBlock(connector.connectorType)?.bgColor ?? null
const brandBg = getBlockDisplay(connector.connectorType)?.bgColor ?? null
const statusConfig =
STATUS_CONFIG[connector.status as keyof typeof STATUS_CONFIG] || STATUS_CONFIG.active

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { formatCreditCost } from '@/lib/billing/credits/conversion'
import type { TraceSpan } from '@/lib/logs/types'
import { LoopTool } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/subflows/loop/loop-config'
import { ParallelTool } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/subflows/parallel/parallel-config'
import { getBlock, getBlockByToolName } from '@/blocks'
import { getBlockDisplay, getBlockDisplayByToolName } from '@/blocks/manifest'
import { PROVIDER_DEFINITIONS } from '@/providers/models'
import { normalizeToolId } from '@/tools/normalize'

Expand Down Expand Up @@ -56,13 +56,13 @@ export function getBlockIconAndColor(
const lowerType = type.toLowerCase()
if (lowerType === 'tool' && toolName) {
if (tryParseMcpToolName(toolName)) {
const mcpBlock = getBlock('mcp')
const mcpBlock = getBlockDisplay('mcp')
if (mcpBlock) return { icon: mcpBlock.icon, bgColor: mcpBlock.bgColor }
}
const normalized = normalizeToolId(toolName)
if (normalized === 'load_skill' || normalized === 'load_user_skill')
return { icon: AgentSkillsIcon, bgColor: '#8B5CF6' }
const toolBlock = getBlockByToolName(normalized)
const toolBlock = getBlockDisplayByToolName(normalized)
if (toolBlock) return { icon: toolBlock.icon, bgColor: toolBlock.bgColor }
}
if (lowerType === 'loop' || lowerType === 'loop-iteration')
Expand All @@ -76,7 +76,7 @@ export function getBlockIconAndColor(
return { icon: providerDef.icon, bgColor: providerDef.color ?? DEFAULT_BLOCK_COLOR }
}
const blockType = lowerType === 'model' ? 'agent' : lowerType
const blockConfig = getBlock(blockType)
const blockConfig = getBlockDisplay(blockType)
if (blockConfig) return { icon: blockConfig.icon, bgColor: blockConfig.bgColor }
return { icon: null, bgColor: DEFAULT_BLOCK_COLOR }
}
Expand Down
4 changes: 2 additions & 2 deletions apps/sim/app/workspace/[workspaceId]/logs/logs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ import {
} from '@/app/workspace/[workspaceId]/logs/search-params'
import type { Suggestion } from '@/app/workspace/[workspaceId]/logs/types'
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
import { getBlock } from '@/blocks/registry'
import { getBlockDisplay } from '@/blocks/manifest'
import { useFolderMap, useFolders } from '@/hooks/queries/folders'
import type { LogSortBy, LogSortOrder } from '@/hooks/queries/logs'
import {
Expand Down Expand Up @@ -186,7 +186,7 @@ function getTriggerIcon(
triggerType: string
): React.ComponentType<{ className?: string }> | undefined {
if ((CORE_TRIGGER_TYPES as readonly string[]).includes(triggerType)) return undefined
const block = getBlock(triggerType)
const block = getBlockDisplay(triggerType)
if (!block?.icon) return undefined
const BlockIcon = block.icon
const TriggerIcon = ({ className }: { className?: string }) => (
Expand Down
4 changes: 2 additions & 2 deletions apps/sim/app/workspace/[workspaceId]/logs/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { format } from 'date-fns'
import { Badge } from '@/components/emcn'
import type { WorkflowLogDetail } from '@/lib/api/contracts/logs'
import { getIntegrationMetadata } from '@/lib/logs/get-trigger-options'
import { getBlock } from '@/blocks/registry'
import { getBlockDisplay } from '@/blocks/manifest'
import { CORE_TRIGGER_TYPES } from '@/stores/logs/filters/types'

export const LOG_COLUMNS = {
Expand Down Expand Up @@ -109,7 +109,7 @@ interface TriggerBadgeProps {
export function TriggerBadge({ trigger }: TriggerBadgeProps) {
const metadata = getIntegrationMetadata(trigger)
const isIntegration = !(CORE_TRIGGER_TYPES as readonly string[]).includes(trigger)
const block = isIntegration ? getBlock(trigger) : null
const block = isIntegration ? getBlockDisplay(trigger) : null
const IconComponent = block?.icon

const coreVariant = TRIGGER_VARIANT_MAP[trigger]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ import {
RequiredLabel,
} from '@/app/workspace/[workspaceId]/tables/[tableId]/components/sidebar-fields'
import { PreviewWorkflow } from '@/app/workspace/[workspaceId]/w/components/preview'
import { getBlock } from '@/blocks'
import { getBlockDisplay } from '@/blocks/manifest'
import {
useAddWorkflowGroup,
useUpdateColumn,
Expand Down Expand Up @@ -470,7 +470,7 @@ export function WorkflowSidebarBody({
for (const f of flat) {
let group = groupsByBlockId.get(f.blockId)
if (!group) {
const blockConfig = getBlock(f.blockType)
const blockConfig = getBlockDisplay(f.blockType)
const blockColor = blockConfig?.bgColor || '#2F55FF'
let blockIcon: string | React.ComponentType<{ className?: string }> = f.blockName
.charAt(0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useQueryClient } from '@tanstack/react-query'
import type { ColumnDefinition, TableDefinition, TableRow, WorkflowGroup } from '@/lib/table'
import { TABLE_LIMITS } from '@/lib/table/constants'
import type { FlattenOutputsBlockInput } from '@/lib/workflows/blocks/flatten-outputs'
import { getBlock } from '@/blocks'
import { getBlockDisplay } from '@/blocks/manifest'
import {
tableRowsInfiniteOptions,
useInfiniteTableRows,
Expand Down Expand Up @@ -211,7 +211,7 @@ export function useTable({ workspaceId, tableId, queryOptions }: UseTableParams)
const isLiveMode = group.deploymentMode !== 'deployed'
for (const out of group.outputs) {
const block = blocks?.[out.blockId]
const blockConfig = block?.type ? getBlock(block.type) : undefined
const blockConfig = block?.type ? getBlockDisplay(block.type) : undefined
const blockIconInfo: BlockIconInfo | undefined = blockConfig?.icon
? { icon: blockConfig.icon, color: blockConfig.bgColor || '#2F55FF' }
: undefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
type FlattenOutputsBlockInput,
flattenWorkflowOutputs,
} from '@/lib/workflows/blocks/flatten-outputs'
import { getBlock } from '@/blocks'
import { getBlockDisplay } from '@/blocks/manifest'
import { normalizeName } from '@/executor/constants'
import { useWorkflowDiffStore } from '@/stores/workflow-diff/store'
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
Expand Down Expand Up @@ -199,7 +199,7 @@ export function OutputSelect({
* @returns The hex color code for the block
*/
const getOutputColor = (blockType: string) => {
const blockConfig = getBlock(blockType)
const blockConfig = getBlockDisplay(blockType)
return blockConfig?.bgColor || '#2F55FF'
}

Expand Down Expand Up @@ -254,7 +254,7 @@ export function OutputSelect({

return sortedGroups.map(({ blockName, outputs }) => {
const firstOutput = outputs[0]
const blockConfig = getBlock(firstOutput.blockType)
const blockConfig = getBlockDisplay(firstOutput.blockType)
const blockColor = getOutputColor(firstOutput.blockType)

let blockIcon: string | React.ComponentType<{ className?: string }> = blockName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { listCopilotChatsContract } from '@/lib/api/contracts/copilot'
import { listKnowledgeBasesContract } from '@/lib/api/contracts/knowledge/base'
import { listLogsContract } from '@/lib/api/contracts/logs'
import { type IntegrationDescriptor, listIntegrations } from '@/blocks/integration-matcher'
import { getBlockDisplay } from '@/blocks/manifest'
import { useWorkflows } from '@/hooks/queries/workflows'
import { usePermissionConfig } from '@/hooks/use-permission-config'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
Expand Down Expand Up @@ -188,9 +189,8 @@ export function useMentionData(props: UseMentionDataProps): MentionDataReturn {
// Fetch current blocks from store
const workflowStoreBlocks = useWorkflowStore.getState().blocks

const { registry: blockRegistry } = await import('@/blocks/registry')
const mapped = Object.values(workflowStoreBlocks).map((b: any) => {
const reg = (blockRegistry as any)[b.type]
const reg = getBlockDisplay(b.type)
return {
id: b.id,
name: b.name || b.id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
} from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/connection-blocks/components/field-item/field-item'
import type { ConnectedBlock } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/hooks/use-block-connections'
import { useBlockOutputFields } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-block-output-fields'
import { getBlock } from '@/blocks/registry'
import { getBlockDisplay } from '@/blocks/manifest'
import { normalizeName } from '@/executor/constants'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
import { EMPTY_SUBBLOCK_VALUES, useSubBlockStore } from '@/stores/workflows/subblock/store'
Expand Down Expand Up @@ -103,7 +103,7 @@ function ConnectionItem({
mergedSubBlocks,
sourceBlock,
}: ConnectionItemProps) {
const blockConfig = getBlock(connection.type)
const blockConfig = getBlockDisplay(connection.type)

const fields = useBlockOutputFields({
blockId: connection.id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
SplitIcon,
XCircleIcon,
} from 'lucide-react'
import { getBlock } from '@/blocks'
import { getBlockDisplay } from '@/blocks/manifest'
import { isWorkflowBlockType } from '@/executor/constants'
import { TERMINAL_BLOCK_COLUMN_WIDTH } from '@/stores/constants'
import type { ConsoleEntry } from '@/stores/terminal'
Expand Down Expand Up @@ -36,7 +36,7 @@ const SPECIAL_BLOCK_COLORS = {
export function getBlockIcon(
blockType: string
): React.ComponentType<{ className?: string }> | null {
const blockConfig = getBlock(blockType)
const blockConfig = getBlockDisplay(blockType)

if (blockConfig?.icon) {
return blockConfig.icon
Expand Down Expand Up @@ -73,7 +73,7 @@ export function getBlockIcon(
* Gets the background color for a block type
*/
export function getBlockColor(blockType: string): string {
const blockConfig = getBlock(blockType)
const blockConfig = getBlockDisplay(blockType)
if (blockConfig?.bgColor) {
return blockConfig.bgColor
}
Expand Down
18 changes: 18 additions & 0 deletions apps/sim/blocks/blocks/a2a.display.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { A2AIcon } from '@/components/icons'
import type { BlockDisplay } from '@/blocks/manifest'
import { IntegrationType } from '@/blocks/types'

export const A2ABlockDisplay = {
type: 'a2a',
name: 'A2A',
description: 'Interact with external A2A-compatible agents',
category: 'blocks',
bgColor: '#4151B5',
icon: A2AIcon,
longDescription:
'Use the A2A (Agent-to-Agent) protocol to interact with external AI agents. ' +
'Send messages, query task status, cancel tasks, or discover agent capabilities. ' +
'Compatible with any A2A-compliant agent including LangGraph, Google ADK, and other Sim workflows.',
docsLink: 'https://docs.sim.ai/workflows/blocks/a2a',
integrationType: IntegrationType.DevOps,
} satisfies BlockDisplay
16 changes: 2 additions & 14 deletions apps/sim/blocks/blocks/a2a.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { A2AIcon } from '@/components/icons'
import { A2ABlockDisplay } from '@/blocks/blocks/a2a.display'
import type { BlockConfig } from '@/blocks/types'
import { IntegrationType } from '@/blocks/types'
import { normalizeFileInput } from '@/blocks/utils'
import type { ToolResponse } from '@/tools/types'

Expand Down Expand Up @@ -55,18 +54,7 @@ export interface A2AResponse extends ToolResponse {
}

export const A2ABlock: BlockConfig<A2AResponse> = {
type: 'a2a',
name: 'A2A',
description: 'Interact with external A2A-compatible agents',
longDescription:
'Use the A2A (Agent-to-Agent) protocol to interact with external AI agents. ' +
'Send messages, query task status, cancel tasks, or discover agent capabilities. ' +
'Compatible with any A2A-compliant agent including LangGraph, Google ADK, and other Sim workflows.',
docsLink: 'https://docs.sim.ai/workflows/blocks/a2a',
category: 'blocks',
integrationType: IntegrationType.DevOps,
bgColor: '#4151B5',
icon: A2AIcon,
...A2ABlockDisplay,
subBlocks: [
{
id: 'operation',
Expand Down
16 changes: 16 additions & 0 deletions apps/sim/blocks/blocks/agent.display.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { AgentIcon } from '@/components/icons'
import type { BlockDisplay } from '@/blocks/manifest'
import { IntegrationType } from '@/blocks/types'

export const AgentBlockDisplay = {
type: 'agent',
name: 'Agent',
description: 'Build an agent',
category: 'blocks',
bgColor: 'var(--brand)',
icon: AgentIcon,
longDescription:
'The Agent block is a core workflow block that is a wrapper around an LLM. It takes in system/user prompts and calls an LLM provider. It can also make tool calls by directly containing tools inside of its tool input. It can additionally return structured output.',
docsLink: 'https://docs.sim.ai/workflows/blocks/agent',
integrationType: IntegrationType.AI,
} satisfies BlockDisplay
15 changes: 3 additions & 12 deletions apps/sim/blocks/blocks/agent.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger'
import { AgentIcon } from '@/components/icons'
import { AgentBlockDisplay } from '@/blocks/blocks/agent.display'
import type { BlockConfig } from '@/blocks/types'
import { AuthMode, IntegrationType } from '@/blocks/types'
import { AuthMode } from '@/blocks/types'
import {
getModelOptions,
getProviderCredentialSubBlocks,
Expand Down Expand Up @@ -67,21 +67,12 @@ const getToolIdFromBlock = (blockType: string): string | undefined => {
}

export const AgentBlock: BlockConfig<AgentResponse> = {
type: 'agent',
name: 'Agent',
description: 'Build an agent',
...AgentBlockDisplay,
authMode: AuthMode.ApiKey,
longDescription:
'The Agent block is a core workflow block that is a wrapper around an LLM. It takes in system/user prompts and calls an LLM provider. It can also make tool calls by directly containing tools inside of its tool input. It can additionally return structured output.',
bestPractices: `
- Prefer using integrations as tools within the agent block over separate integration blocks unless complete determinism needed.
- Response Format should be a valid JSON Schema. This determines the output of the agent only if present. Fields can be accessed at root level by the following blocks: e.g. <agent1.field>. If response format is not present, the agent will return the standard outputs: content, model, tokens, toolCalls.
`,
docsLink: 'https://docs.sim.ai/workflows/blocks/agent',
category: 'blocks',
integrationType: IntegrationType.AI,
bgColor: 'var(--brand)',
icon: AgentIcon,
subBlocks: [
{
id: 'messages',
Expand Down
Loading