Skip to main content
Glama

mcp-google-sheets

step-utils.tsx6.89 kB
import { t } from 'i18next'; import { agentsApi } from '@/features/agents/lib/agents-api'; import { ErrorHandlingOptionsParam, PieceMetadataModel, PieceMetadataModelSummary, } from '@activepieces/pieces-framework'; import { FlowAction, FlowActionType, flowStructureUtil, LocalesEnum, spreadIfDefined, Step, FlowTriggerType, FlowTrigger, StepOutput, StepRunResponse, } from '@activepieces/shared'; import { PieceStepMetadata, PrimitiveStepMetadata, StepMetadata, StepMetadataWithActionOrTriggerOrAgentDisplayName, } from '../../../lib/types'; import { piecesApi } from './pieces-api'; export const CORE_STEP_METADATA: Record< Exclude<FlowActionType, FlowActionType.PIECE> | FlowTriggerType.EMPTY, PrimitiveStepMetadata > = { [FlowActionType.CODE]: { displayName: t('Code'), logoUrl: 'https://cdn.activepieces.com/pieces/code.svg', description: t('Powerful Node.js & TypeScript code with npm'), type: FlowActionType.CODE as const, }, [FlowActionType.LOOP_ON_ITEMS]: { displayName: t('Loop on Items'), logoUrl: 'https://cdn.activepieces.com/pieces/loop.svg', description: 'Iterate over a list of items', type: FlowActionType.LOOP_ON_ITEMS as const, }, [FlowActionType.ROUTER]: { displayName: t('Router'), logoUrl: 'https://cdn.activepieces.com/pieces/branch.svg', description: t('Split your flow into branches depending on condition(s)'), type: FlowActionType.ROUTER as const, }, [FlowTriggerType.EMPTY]: { displayName: t('Empty Trigger'), logoUrl: 'https://cdn.activepieces.com/pieces/empty-trigger.svg', description: t('Empty Trigger'), type: FlowTriggerType.EMPTY as const, }, } as const; export const CORE_ACTIONS_METADATA = [ CORE_STEP_METADATA[FlowActionType.CODE], CORE_STEP_METADATA[FlowActionType.LOOP_ON_ITEMS], CORE_STEP_METADATA[FlowActionType.ROUTER], ] as const; export const TODO_ACTIONS = { createTodo: 'createTodo', createTodoAndWait: 'createTodoAndWait', waitForApproval: 'wait_for_approval', }; export const HIDDEN_ACTIONS = [ { pieceName: '@activepieces/piece-todos', actions: [TODO_ACTIONS.createTodoAndWait, TODO_ACTIONS.waitForApproval], }, ]; export const stepUtils = { getKeys( step: FlowAction | FlowTrigger, locale: LocalesEnum, ): (string | undefined)[] { const isPieceStep = step.type === FlowActionType.PIECE || step.type === FlowTriggerType.PIECE; const pieceName = isPieceStep ? step.settings.pieceName : undefined; const pieceVersion = isPieceStep ? step.settings.pieceVersion : undefined; const customLogoUrl = isPieceStep ? 'customLogoUrl' in step ? step.customLogoUrl : undefined : undefined; const agentId = flowStructureUtil.getExternalAgentId(step); return [pieceName, pieceVersion, customLogoUrl, agentId, locale, step.type]; }, async getMetadata( step: FlowAction | FlowTrigger, locale: LocalesEnum, ): Promise<StepMetadataWithActionOrTriggerOrAgentDisplayName> { const customLogoUrl = 'customLogoUrl' in step ? step.customLogoUrl : undefined; switch (step.type) { case FlowActionType.ROUTER: case FlowActionType.LOOP_ON_ITEMS: case FlowActionType.CODE: case FlowTriggerType.EMPTY: return { ...CORE_STEP_METADATA[step.type], ...spreadIfDefined('logoUrl', customLogoUrl), actionOrTriggerOrAgentDisplayName: '', }; case FlowActionType.PIECE: case FlowTriggerType.PIECE: { const piece = await piecesApi.get({ name: step.settings.pieceName, version: step.settings.pieceVersion, locale, }); const metadata = stepUtils.mapPieceToMetadata({ piece, type: step.type === FlowActionType.PIECE ? 'action' : 'trigger', }); const agentMetadata = await getAgentMetadata(step); const agentDisplayName = agentMetadata.displayName; const actionOrTriggerDisplayName = step.type === FlowActionType.PIECE ? piece.actions[step.settings.actionName!].displayName : piece.triggers[step.settings.triggerName!].displayName; return { ...metadata, ...spreadIfDefined('logoUrl', agentMetadata.logoUrl ?? customLogoUrl), ...spreadIfDefined( 'description', agentMetadata.description ?? piece.description, ), errorHandlingOptions: mapErrorHandlingOptions(piece, step), actionOrTriggerOrAgentDisplayName: agentDisplayName ?? actionOrTriggerDisplayName, }; } } }, mapPieceToMetadata({ piece, type, }: { piece: PieceMetadataModelSummary | PieceMetadataModel; type: 'action' | 'trigger'; }): Omit<PieceStepMetadata, 'stepDisplayName'> { return { displayName: piece.displayName, logoUrl: piece.logoUrl, description: piece.description, type: type === 'action' ? FlowActionType.PIECE : FlowTriggerType.PIECE, pieceType: piece.pieceType, pieceName: piece.name, pieceVersion: piece.version, categories: piece.categories ?? [], packageType: piece.packageType, auth: piece.auth, }; }, getAgentRunId(output: StepOutput | StepRunResponse | undefined | null) { if (!output) { return undefined; } return 'output' in output && 'agentRunId' in (output.output as { agentRunId: string }) ? (output.output as { agentRunId: string }).agentRunId : undefined; }, }; async function getAgentMetadata( step: FlowAction | FlowTrigger, ): Promise< Partial<Pick<StepMetadata, 'displayName' | 'logoUrl' | 'description'>> > { if (flowStructureUtil.isAgentPiece(step)) { const externalAgentId = flowStructureUtil.getExternalAgentId(step); if (!externalAgentId) { return {}; } const agent = await agentsApi.findByExteranlId(externalAgentId); if (!agent) { return {}; } return { logoUrl: agent.profilePictureUrl, description: agent.description, displayName: agent.displayName, }; } return {}; } function mapErrorHandlingOptions( piece: PieceMetadataModel, step: Step, ): ErrorHandlingOptionsParam { if (flowStructureUtil.isTrigger(step.type)) { return { continueOnFailure: { hide: true, }, retryOnFailure: { hide: true, }, }; } const selectedAction = step.type === FlowActionType.PIECE ? piece.actions[step.settings.actionName!] : null; const errorHandlingOptions = selectedAction?.errorHandlingOptions; if (errorHandlingOptions) { return errorHandlingOptions; } return { continueOnFailure: { hide: false, defaultValue: false, }, retryOnFailure: { hide: false, defaultValue: false, }, }; }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/activepieces/activepieces'

If you have feedback or need assistance with the MCP directory API, please join our Discord server