import type { LucideIcon } from 'lucide-react'
import {
  BookOpen,
  Bug,
  Check,
  CheckCircle,
  ClipboardList,
  Database,
  Eye,
  FileSearch,
  FileText,
  FolderPlus,
  GitBranch,
  Globe,
  Globe2,
  Grid2x2,
  Grid2x2Check,
  Grid2x2X,
  KeyRound,
  Link,
  Loader2,
  MessageSquare,
  MinusCircle,
  Moon,
  Navigation,
  PencilLine,
  Play,
  PlugZap,
  Plus,
  Rocket,
  Search,
  Server,
  Settings2,
  Sparkles,
  Table,
  Tag,
  TerminalSquare,
  Wrench,
  X,
  XCircle,
  Zap,
} from 'lucide-react'
import { getQueryClient } from '@/app/_shell/providers/get-query-client'
import type { CustomToolDefinition } from '@/hooks/queries/custom-tools'
import type { WorkflowDeploymentInfo } from '@/hooks/queries/deployments'
import { deploymentKeys } from '@/hooks/queries/deployments'
import { customToolsKeys } from '@/hooks/queries/utils/custom-tool-keys'
import { getWorkflowById } from '@/hooks/queries/utils/workflow-cache'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
import { useWorkflowStore } from '@/stores/workflows/workflow/store'

/** Resolve a block ID to its human-readable name from the workflow store. */
function resolveBlockName(blockId: string | undefined): string | undefined {
  if (!blockId) return undefined
  try {
    const blocks = useWorkflowStore.getState().blocks
    return blocks[blockId]?.name || undefined
  } catch {
    return undefined
  }
}

export enum ClientToolCallState {
  generating = 'generating',
  pending = 'pending',
  executing = 'executing',
  aborted = 'aborted',
  rejected = 'rejected',
  success = 'success',
  error = 'error',
  cancelled = 'cancelled',
  review = 'review',
  background = 'background',
}

export interface ClientToolDisplay {
  text: string
  icon: LucideIcon
}

export type DynamicTextFormatter = (
  params: Record<string, any>,
  state: ClientToolCallState
) => string | undefined

export interface ToolUIConfig {
  isSpecial?: boolean
  subagent?: boolean
  interrupt?: boolean
  customRenderer?: string
  paramsTable?: any
  dynamicText?: DynamicTextFormatter
  secondaryAction?: any
  alwaysExpanded?: boolean
  subagentLabels?: {
    streaming: string
    completed: string
  }
}

interface ToolMetadata {
  displayNames: Partial<Record<ClientToolCallState, ClientToolDisplay>>
  interrupt?: {
    accept: ClientToolDisplay
    reject: ClientToolDisplay
  }
  getDynamicText?: DynamicTextFormatter
  uiConfig?: {
    isSpecial?: boolean
    subagent?: {
      streamingLabel?: string
      completedLabel?: string
      shouldCollapse?: boolean
      outputArtifacts?: string[]
      hideThinkingText?: boolean
    }
    interrupt?: any
    customRenderer?: string
    paramsTable?: any
    secondaryAction?: any
    alwaysExpanded?: boolean
  }
}

interface ToolDisplayEntry {
  displayNames: Partial<Record<ClientToolCallState, ClientToolDisplay>>
  uiConfig?: ToolUIConfig
}

type WorkflowDataType = 'global_variables' | 'custom_tools' | 'mcp_tools' | 'files'

type NavigationDestination = 'workflow' | 'logs' | 'templates' | 'vector_db' | 'settings'

function formatDuration(seconds: number): string {
  if (seconds < 60) return `${Math.round(seconds)}s`
  const mins = Math.floor(seconds / 60)
  const secs = Math.round(seconds % 60)
  if (mins < 60) return secs > 0 ? `${mins}m ${secs}s` : `${mins}m`
  const hours = Math.floor(mins / 60)
  const remMins = mins % 60
  if (remMins > 0) return `${hours}h ${remMins}m`
  return `${hours}h`
}

function getScopedWorkspaceId(params: Record<string, any>): string | undefined {
  const paramWorkspaceId = params?.workspaceId
  if (typeof paramWorkspaceId === 'string' && paramWorkspaceId.length > 0) {
    return paramWorkspaceId
  }

  return useWorkflowRegistry.getState().hydration.workspaceId ?? undefined
}

function toUiConfig(metadata?: ToolMetadata): ToolUIConfig | undefined {
  const legacy = metadata?.uiConfig
  const subagent = legacy?.subagent
  const dynamicText = metadata?.getDynamicText
  // Check both nested uiConfig.interrupt AND top-level interrupt
  const hasInterrupt = !!legacy?.interrupt || !!metadata?.interrupt
  if (!legacy && !dynamicText && !hasInterrupt) return undefined

  const config: ToolUIConfig = {
    isSpecial: legacy?.isSpecial === true,
    subagent: !!legacy?.subagent,
    interrupt: hasInterrupt,
    customRenderer: legacy?.customRenderer,
    paramsTable: legacy?.paramsTable,
    dynamicText,
    secondaryAction: legacy?.secondaryAction,
    alwaysExpanded: legacy?.alwaysExpanded,
  }

  if (subagent?.streamingLabel || subagent?.completedLabel) {
    config.subagentLabels = {
      streaming: subagent.streamingLabel || '',
      completed: subagent.completedLabel || '',
    }
  }

  return config
}

function toToolDisplayEntry(metadata?: ToolMetadata): ToolDisplayEntry {
  return {
    displayNames: metadata?.displayNames || {},
    uiConfig: toUiConfig(metadata),
  }
}

const META_auth: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Authenticating', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Authenticating', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Authenticating', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Authenticated', icon: KeyRound },
    [ClientToolCallState.error]: { text: 'Failed to authenticate', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped auth', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted auth', icon: XCircle },
  },
  uiConfig: {
    subagent: {
      streamingLabel: 'Authenticating',
      completedLabel: 'Authenticated',
      shouldCollapse: true,
      outputArtifacts: [],
    },
  },
}

const META_check_deployment_status: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: {
      text: 'Checking deployment status',
      icon: Loader2,
    },
    [ClientToolCallState.pending]: { text: 'Checking deployment status', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Checking deployment status', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Checked deployment status', icon: Rocket },
    [ClientToolCallState.error]: { text: 'Failed to check deployment status', icon: X },
    [ClientToolCallState.aborted]: {
      text: 'Aborted checking deployment status',
      icon: XCircle,
    },
    [ClientToolCallState.rejected]: {
      text: 'Skipped checking deployment status',
      icon: XCircle,
    },
  },
  interrupt: undefined,
}

const META_checkoff_todo: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Marking todo', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Marking todo', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Marked todo complete', icon: Check },
    [ClientToolCallState.error]: { text: 'Failed to mark todo', icon: XCircle },
  },
}

const META_crawl_website: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Crawling website', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Crawling website', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Crawling website', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Crawled website', icon: Globe },
    [ClientToolCallState.error]: { text: 'Failed to crawl website', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted crawling website', icon: MinusCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped crawling website', icon: MinusCircle },
  },
  interrupt: undefined,
  getDynamicText: (params, state) => {
    if (params?.url && typeof params.url === 'string') {
      const url = params.url

      switch (state) {
        case ClientToolCallState.success:
          return `Crawled ${url}`
        case ClientToolCallState.executing:
        case ClientToolCallState.generating:
        case ClientToolCallState.pending:
          return `Crawling ${url}`
        case ClientToolCallState.error:
          return `Failed to crawl ${url}`
        case ClientToolCallState.aborted:
          return `Aborted crawling ${url}`
        case ClientToolCallState.rejected:
          return `Skipped crawling ${url}`
      }
    }
    return undefined
  },
}

const META_create_workspace_mcp_server: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: {
      text: 'Preparing to create MCP server',
      icon: Loader2,
    },
    [ClientToolCallState.pending]: { text: 'Create MCP server?', icon: Server },
    [ClientToolCallState.executing]: { text: 'Creating MCP server', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Created MCP server', icon: Server },
    [ClientToolCallState.error]: { text: 'Failed to create MCP server', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted creating MCP server', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped creating MCP server', icon: XCircle },
  },
  interrupt: {
    accept: { text: 'Create', icon: Plus },
    reject: { text: 'Skip', icon: XCircle },
  },
  getDynamicText: (params, state) => {
    const name = params?.name || 'MCP server'
    switch (state) {
      case ClientToolCallState.success:
        return `Created MCP server "${name}"`
      case ClientToolCallState.executing:
        return `Creating MCP server "${name}"`
      case ClientToolCallState.generating:
        return `Preparing to create "${name}"`
      case ClientToolCallState.pending:
        return `Create MCP server "${name}"?`
      case ClientToolCallState.error:
        return `Failed to create "${name}"`
    }
    return undefined
  },
}

const META_custom_tool: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Managing custom tool', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Managing custom tool', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Managing custom tool', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Managed custom tool', icon: Wrench },
    [ClientToolCallState.error]: { text: 'Failed custom tool', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped custom tool', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted custom tool', icon: XCircle },
  },
  uiConfig: {
    subagent: {
      streamingLabel: 'Managing custom tool',
      completedLabel: 'Custom tool managed',
      shouldCollapse: true,
      outputArtifacts: [],
    },
  },
}

const META_agent: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Managing tools & skills', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Managing tools & skills', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Managing tools & skills', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Managed tools & skills', icon: Wrench },
    [ClientToolCallState.error]: { text: 'Failed managing tools', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped managing tools', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted managing tools', icon: XCircle },
  },
  uiConfig: {
    subagent: {
      streamingLabel: 'Managing tools & skills',
      completedLabel: 'Tools & skills managed',
      shouldCollapse: true,
      outputArtifacts: [],
    },
  },
}

const META_manage_skill: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: {
      text: 'Managing skill',
      icon: Loader2,
    },
    [ClientToolCallState.pending]: { text: 'Manage skill?', icon: BookOpen },
    [ClientToolCallState.executing]: { text: 'Managing skill', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Managed skill', icon: Check },
    [ClientToolCallState.error]: { text: 'Failed to manage skill', icon: X },
    [ClientToolCallState.aborted]: {
      text: 'Aborted managing skill',
      icon: XCircle,
    },
    [ClientToolCallState.rejected]: {
      text: 'Skipped managing skill',
      icon: XCircle,
    },
  },
  interrupt: {
    accept: { text: 'Allow', icon: Check },
    reject: { text: 'Deny', icon: X },
  },
}

const META_build: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Building', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Building', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Building', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Built', icon: Wrench },
    [ClientToolCallState.error]: { text: 'Failed to build', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped build', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted build', icon: XCircle },
  },
  uiConfig: {
    subagent: {
      streamingLabel: 'Building',
      completedLabel: 'Built',
      shouldCollapse: true,
      outputArtifacts: [],
    },
  },
}

const META_deploy: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Deploying', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Deploying', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Deploying', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Deployed', icon: Rocket },
    [ClientToolCallState.error]: { text: 'Failed to deploy', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped deploy', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted deploy', icon: XCircle },
  },
  uiConfig: {
    subagent: {
      streamingLabel: 'Deploying',
      completedLabel: 'Deployed',
      shouldCollapse: true,
      outputArtifacts: [],
    },
  },
}

const META_deploy_api: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: {
      text: 'Preparing to deploy API',
      icon: Loader2,
    },
    [ClientToolCallState.pending]: { text: 'Deploy as API?', icon: Rocket },
    [ClientToolCallState.executing]: { text: 'Deploying API', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Deployed API', icon: Rocket },
    [ClientToolCallState.error]: { text: 'Failed to deploy API', icon: XCircle },
    [ClientToolCallState.aborted]: {
      text: 'Aborted deploying API',
      icon: XCircle,
    },
    [ClientToolCallState.rejected]: {
      text: 'Skipped deploying API',
      icon: XCircle,
    },
  },
  interrupt: {
    accept: { text: 'Deploy', icon: Rocket },
    reject: { text: 'Skip', icon: XCircle },
  },
  uiConfig: {
    isSpecial: true,
    interrupt: {
      accept: { text: 'Deploy', icon: Rocket },
      reject: { text: 'Skip', icon: XCircle },
      showAllowOnce: true,
      showAllowAlways: true,
    },
  },
  getDynamicText: (params, state) => {
    const action = params?.action === 'undeploy' ? 'undeploy' : 'deploy'

    const workflowId = params?.workflowId || useWorkflowRegistry.getState().activeWorkflowId
    const isAlreadyDeployed = workflowId
      ? (getQueryClient().getQueryData<WorkflowDeploymentInfo>(deploymentKeys.info(workflowId))
          ?.isDeployed ?? false)
      : false

    let actionText = action
    let actionTextIng = action === 'undeploy' ? 'undeploying' : 'deploying'
    const actionTextPast = action === 'undeploy' ? 'undeployed' : 'deployed'

    if (action === 'deploy' && isAlreadyDeployed) {
      actionText = 'redeploy'
      actionTextIng = 'redeploying'
    }

    const actionCapitalized = actionText.charAt(0).toUpperCase() + actionText.slice(1)

    switch (state) {
      case ClientToolCallState.success:
        return `API ${actionTextPast}`
      case ClientToolCallState.executing:
        return `${actionCapitalized}ing API`
      case ClientToolCallState.generating:
        return `Preparing to ${actionText} API`
      case ClientToolCallState.pending:
        return `${actionCapitalized} API?`
      case ClientToolCallState.error:
        return `Failed to ${actionText} API`
      case ClientToolCallState.aborted:
        return `Aborted ${actionTextIng} API`
      case ClientToolCallState.rejected:
        return `Skipped ${actionTextIng} API`
    }
    return undefined
  },
}

const META_deploy_chat: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: {
      text: 'Preparing to deploy chat',
      icon: Loader2,
    },
    [ClientToolCallState.pending]: { text: 'Deploy as chat?', icon: MessageSquare },
    [ClientToolCallState.executing]: { text: 'Deploying chat', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Deployed chat', icon: MessageSquare },
    [ClientToolCallState.error]: { text: 'Failed to deploy chat', icon: XCircle },
    [ClientToolCallState.aborted]: {
      text: 'Aborted deploying chat',
      icon: XCircle,
    },
    [ClientToolCallState.rejected]: {
      text: 'Skipped deploying chat',
      icon: XCircle,
    },
  },
  interrupt: {
    accept: { text: 'Deploy Chat', icon: MessageSquare },
    reject: { text: 'Skip', icon: XCircle },
  },
  uiConfig: {
    isSpecial: true,
    interrupt: {
      accept: { text: 'Deploy Chat', icon: MessageSquare },
      reject: { text: 'Skip', icon: XCircle },
      showAllowOnce: true,
      showAllowAlways: true,
    },
  },
  getDynamicText: (params, state) => {
    const action = params?.action === 'undeploy' ? 'undeploy' : 'deploy'

    switch (state) {
      case ClientToolCallState.success:
        return action === 'undeploy' ? 'Chat undeployed' : 'Chat deployed'
      case ClientToolCallState.executing:
        return action === 'undeploy' ? 'Undeploying chat' : 'Deploying chat'
      case ClientToolCallState.generating:
        return `Preparing to ${action} chat`
      case ClientToolCallState.pending:
        return action === 'undeploy' ? 'Undeploy chat?' : 'Deploy as chat?'
      case ClientToolCallState.error:
        return `Failed to ${action} chat`
      case ClientToolCallState.aborted:
        return action === 'undeploy' ? 'Aborted undeploying chat' : 'Aborted deploying chat'
      case ClientToolCallState.rejected:
        return action === 'undeploy' ? 'Skipped undeploying chat' : 'Skipped deploying chat'
    }
    return undefined
  },
}

const META_deploy_mcp: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: {
      text: 'Preparing to deploy to MCP',
      icon: Loader2,
    },
    [ClientToolCallState.pending]: { text: 'Deploy to MCP server?', icon: Server },
    [ClientToolCallState.executing]: { text: 'Deploying to MCP', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Deployed to MCP', icon: Server },
    [ClientToolCallState.error]: { text: 'Failed to deploy to MCP', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted MCP deployment', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped MCP deployment', icon: XCircle },
  },
  interrupt: {
    accept: { text: 'Deploy', icon: Server },
    reject: { text: 'Skip', icon: XCircle },
  },
  uiConfig: {
    isSpecial: true,
    interrupt: {
      accept: { text: 'Deploy', icon: Server },
      reject: { text: 'Skip', icon: XCircle },
      showAllowOnce: true,
      showAllowAlways: true,
    },
  },
  getDynamicText: (params, state) => {
    const toolName = params?.toolName || 'workflow'
    switch (state) {
      case ClientToolCallState.success:
        return `Deployed "${toolName}" to MCP`
      case ClientToolCallState.executing:
        return `Deploying "${toolName}" to MCP`
      case ClientToolCallState.generating:
        return `Preparing to deploy to MCP`
      case ClientToolCallState.pending:
        return `Deploy "${toolName}" to MCP?`
      case ClientToolCallState.error:
        return `Failed to deploy to MCP`
    }
    return undefined
  },
}

const META_edit_workflow: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Editing your workflow', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Editing your workflow', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Edited your workflow', icon: Grid2x2Check },
    [ClientToolCallState.error]: { text: 'Failed to edit your workflow', icon: XCircle },
    [ClientToolCallState.review]: { text: 'Review your workflow changes', icon: Grid2x2 },
    [ClientToolCallState.rejected]: { text: 'Rejected workflow changes', icon: Grid2x2X },
    [ClientToolCallState.aborted]: { text: 'Aborted editing your workflow', icon: MinusCircle },
    [ClientToolCallState.pending]: { text: 'Editing your workflow', icon: Loader2 },
  },
  uiConfig: {
    isSpecial: true,
    customRenderer: 'edit_summary',
  },
}

const META_get_block_outputs: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Getting block outputs', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Getting block outputs', icon: Tag },
    [ClientToolCallState.executing]: { text: 'Getting block outputs', icon: Loader2 },
    [ClientToolCallState.aborted]: { text: 'Aborted getting outputs', icon: XCircle },
    [ClientToolCallState.success]: { text: 'Retrieved block outputs', icon: Tag },
    [ClientToolCallState.error]: { text: 'Failed to get outputs', icon: X },
    [ClientToolCallState.rejected]: { text: 'Skipped getting outputs', icon: XCircle },
  },
  getDynamicText: (params, state) => {
    const blockIds = params?.blockIds
    if (blockIds && Array.isArray(blockIds) && blockIds.length > 0) {
      const count = blockIds.length
      switch (state) {
        case ClientToolCallState.success:
          return `Retrieved outputs for ${count} block${count > 1 ? 's' : ''}`
        case ClientToolCallState.executing:
        case ClientToolCallState.generating:
        case ClientToolCallState.pending:
          return `Getting outputs for ${count} block${count > 1 ? 's' : ''}`
        case ClientToolCallState.error:
          return `Failed to get outputs for ${count} block${count > 1 ? 's' : ''}`
      }
    }
    return undefined
  },
}

const META_get_block_upstream_references: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Getting upstream references', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Getting upstream references', icon: GitBranch },
    [ClientToolCallState.executing]: { text: 'Getting upstream references', icon: Loader2 },
    [ClientToolCallState.aborted]: { text: 'Aborted getting references', icon: XCircle },
    [ClientToolCallState.success]: { text: 'Retrieved upstream references', icon: GitBranch },
    [ClientToolCallState.error]: { text: 'Failed to get references', icon: X },
    [ClientToolCallState.rejected]: { text: 'Skipped getting references', icon: XCircle },
  },
  getDynamicText: (params, state) => {
    const blockIds = params?.blockIds
    if (blockIds && Array.isArray(blockIds) && blockIds.length > 0) {
      const count = blockIds.length
      switch (state) {
        case ClientToolCallState.success:
          return `Retrieved references for ${count} block${count > 1 ? 's' : ''}`
        case ClientToolCallState.executing:
        case ClientToolCallState.generating:
        case ClientToolCallState.pending:
          return `Getting references for ${count} block${count > 1 ? 's' : ''}`
        case ClientToolCallState.error:
          return `Failed to get references for ${count} block${count > 1 ? 's' : ''}`
      }
    }
    return undefined
  },
}

const META_get_examples_rag: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Fetching examples', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Fetching examples', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Fetching examples', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Fetched examples', icon: Search },
    [ClientToolCallState.error]: { text: 'Failed to fetch examples', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted getting examples', icon: MinusCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped getting examples', icon: MinusCircle },
  },
  interrupt: undefined,
  getDynamicText: (params, state) => {
    if (params?.query && typeof params.query === 'string') {
      const query = params.query

      switch (state) {
        case ClientToolCallState.success:
          return `Found examples for ${query}`
        case ClientToolCallState.executing:
        case ClientToolCallState.generating:
        case ClientToolCallState.pending:
          return `Searching examples for ${query}`
        case ClientToolCallState.error:
          return `Failed to find examples for ${query}`
        case ClientToolCallState.aborted:
          return `Aborted searching examples for ${query}`
        case ClientToolCallState.rejected:
          return `Skipped searching examples for ${query}`
      }
    }
    return undefined
  },
}

const META_get_operations_examples: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Designing workflow component', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Designing workflow component', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Designing workflow component', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Designed workflow component', icon: Zap },
    [ClientToolCallState.error]: { text: 'Failed to design workflow component', icon: XCircle },
    [ClientToolCallState.aborted]: {
      text: 'Aborted designing workflow component',
      icon: MinusCircle,
    },
    [ClientToolCallState.rejected]: {
      text: 'Skipped designing workflow component',
      icon: MinusCircle,
    },
  },
  interrupt: undefined,
  getDynamicText: (params, state) => {
    if (params?.query && typeof params.query === 'string') {
      const query = params.query

      switch (state) {
        case ClientToolCallState.success:
          return `Designed ${query}`
        case ClientToolCallState.executing:
        case ClientToolCallState.generating:
        case ClientToolCallState.pending:
          return `Designing ${query}`
        case ClientToolCallState.error:
          return `Failed to design ${query}`
        case ClientToolCallState.aborted:
          return `Aborted designing ${query}`
        case ClientToolCallState.rejected:
          return `Skipped designing ${query}`
      }
    }
    return undefined
  },
}

const META_get_platform_actions: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Viewing platform actions', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Viewing platform actions', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Viewing platform actions', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Viewed platform actions', icon: Navigation },
    [ClientToolCallState.error]: { text: 'Failed to view platform actions', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped platform actions', icon: MinusCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted platform actions', icon: MinusCircle },
  },
}

const META_get_page_contents: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Getting page contents', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Getting page contents', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Getting page contents', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Retrieved page contents', icon: FileText },
    [ClientToolCallState.error]: { text: 'Failed to get page contents', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted getting page contents', icon: MinusCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped getting page contents', icon: MinusCircle },
  },
  interrupt: undefined,
  getDynamicText: (params, state) => {
    if (params?.urls && Array.isArray(params.urls) && params.urls.length > 0) {
      const firstUrl = String(params.urls[0])
      const count = params.urls.length

      switch (state) {
        case ClientToolCallState.success:
          return count > 1 ? `Retrieved ${count} pages` : `Retrieved ${firstUrl}`
        case ClientToolCallState.executing:
        case ClientToolCallState.generating:
        case ClientToolCallState.pending:
          return count > 1 ? `Getting ${count} pages` : `Getting ${firstUrl}`
        case ClientToolCallState.error:
          return count > 1 ? `Failed to get ${count} pages` : `Failed to get ${firstUrl}`
        case ClientToolCallState.aborted:
          return count > 1 ? `Aborted getting ${count} pages` : `Aborted getting ${firstUrl}`
        case ClientToolCallState.rejected:
          return count > 1 ? `Skipped getting ${count} pages` : `Skipped getting ${firstUrl}`
      }
    }
    return undefined
  },
}

const META_get_trigger_examples: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Selecting a trigger', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Selecting a trigger', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Selecting a trigger', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Selected a trigger', icon: Zap },
    [ClientToolCallState.error]: { text: 'Failed to select a trigger', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted selecting a trigger', icon: MinusCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped selecting a trigger', icon: MinusCircle },
  },
  interrupt: undefined,
}

const META_get_workflow_logs: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Fetching execution logs', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Fetching execution logs', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Fetched execution logs', icon: TerminalSquare },
    [ClientToolCallState.error]: { text: 'Failed to fetch execution logs', icon: XCircle },
    [ClientToolCallState.rejected]: {
      text: 'Skipped fetching execution logs',
      icon: MinusCircle,
    },
    [ClientToolCallState.aborted]: {
      text: 'Aborted fetching execution logs',
      icon: MinusCircle,
    },
    [ClientToolCallState.pending]: { text: 'Fetching execution logs', icon: Loader2 },
  },
  getDynamicText: (params, state) => {
    const limit = params?.limit
    if (limit && typeof limit === 'number') {
      const logText = limit === 1 ? 'execution log' : 'execution logs'

      switch (state) {
        case ClientToolCallState.success:
          return `Fetched last ${limit} ${logText}`
        case ClientToolCallState.executing:
        case ClientToolCallState.generating:
        case ClientToolCallState.pending:
          return `Fetching last ${limit} ${logText}`
        case ClientToolCallState.error:
          return `Failed to fetch last ${limit} ${logText}`
        case ClientToolCallState.rejected:
          return `Skipped fetching last ${limit} ${logText}`
        case ClientToolCallState.aborted:
          return `Aborted fetching last ${limit} ${logText}`
      }
    }
    return undefined
  },
}

const META_get_workflow_data: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Fetching workflow data', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Fetching workflow data', icon: Database },
    [ClientToolCallState.executing]: { text: 'Fetching workflow data', icon: Loader2 },
    [ClientToolCallState.aborted]: { text: 'Aborted fetching data', icon: XCircle },
    [ClientToolCallState.success]: { text: 'Retrieved workflow data', icon: Database },
    [ClientToolCallState.error]: { text: 'Failed to fetch data', icon: X },
    [ClientToolCallState.rejected]: { text: 'Skipped fetching data', icon: XCircle },
  },
  getDynamicText: (params, state) => {
    const dataType = params?.data_type as WorkflowDataType | undefined
    if (!dataType) return undefined

    const typeLabels: Record<WorkflowDataType, string> = {
      global_variables: 'variables',
      custom_tools: 'custom tools',
      mcp_tools: 'MCP tools',
      files: 'files',
    }

    const label = typeLabels[dataType] || dataType

    switch (state) {
      case ClientToolCallState.success:
        return `Retrieved ${label}`
      case ClientToolCallState.executing:
      case ClientToolCallState.generating:
        return `Fetching ${label}`
      case ClientToolCallState.pending:
        return `Fetch ${label}?`
      case ClientToolCallState.error:
        return `Failed to fetch ${label}`
      case ClientToolCallState.aborted:
        return `Aborted fetching ${label}`
      case ClientToolCallState.rejected:
        return `Skipped fetching ${label}`
    }
    return undefined
  },
}

const META_knowledge: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Managing knowledge', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Managing knowledge', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Managing knowledge', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Managed knowledge', icon: BookOpen },
    [ClientToolCallState.error]: { text: 'Failed to manage knowledge', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped knowledge', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted knowledge', icon: XCircle },
  },
  uiConfig: {
    subagent: {
      streamingLabel: 'Managing knowledge',
      completedLabel: 'Knowledge managed',
      shouldCollapse: true,
      outputArtifacts: [],
    },
  },
}

const META_knowledge_base: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Accessing knowledge base', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Access knowledge base?', icon: Database },
    [ClientToolCallState.executing]: { text: 'Accessing knowledge base', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Accessed knowledge base', icon: Database },
    [ClientToolCallState.error]: { text: 'Failed to access knowledge base', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted knowledge base access', icon: MinusCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped knowledge base access', icon: MinusCircle },
  },
  interrupt: {
    accept: { text: 'Allow', icon: Database },
    reject: { text: 'Skip', icon: MinusCircle },
  },
  getDynamicText: (params: Record<string, any>, state: ClientToolCallState) => {
    const operation = params?.operation as string | undefined
    const name = params?.args?.name as string | undefined

    const opVerbs: Record<string, { active: string; past: string; pending?: string }> = {
      create: {
        active: 'Creating knowledge base',
        past: 'Created knowledge base',
        pending: name ? `Create knowledge base "${name}"?` : 'Create knowledge base?',
      },
      list: { active: 'Listing knowledge bases', past: 'Listed knowledge bases' },
      get: { active: 'Getting knowledge base', past: 'Retrieved knowledge base' },
      query: { active: 'Querying knowledge base', past: 'Queried knowledge base' },
    }
    const defaultVerb: { active: string; past: string; pending?: string } = {
      active: 'Accessing knowledge base',
      past: 'Accessed knowledge base',
    }
    const verb = operation ? opVerbs[operation] || defaultVerb : defaultVerb

    if (state === ClientToolCallState.success) {
      return verb.past
    }
    if (state === ClientToolCallState.pending && verb.pending) {
      return verb.pending
    }
    if (
      state === ClientToolCallState.generating ||
      state === ClientToolCallState.pending ||
      state === ClientToolCallState.executing
    ) {
      return verb.active
    }
    return undefined
  },
}

const META_list_workspace_mcp_servers: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: {
      text: 'Getting MCP servers',
      icon: Loader2,
    },
    [ClientToolCallState.pending]: { text: 'Getting MCP servers', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Getting MCP servers', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Retrieved MCP servers', icon: Server },
    [ClientToolCallState.error]: { text: 'Failed to get MCP servers', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted getting MCP servers', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped getting MCP servers', icon: XCircle },
  },
  interrupt: undefined,
}

const META_make_api_request: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Preparing API request', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Review API request', icon: Globe2 },
    [ClientToolCallState.executing]: { text: 'Executing API request', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Completed API request', icon: Globe2 },
    [ClientToolCallState.error]: { text: 'Failed to execute API request', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped API request', icon: MinusCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted API request', icon: XCircle },
  },
  interrupt: {
    accept: { text: 'Execute', icon: Globe2 },
    reject: { text: 'Skip', icon: MinusCircle },
  },
  uiConfig: {
    interrupt: {
      accept: { text: 'Execute', icon: Globe2 },
      reject: { text: 'Skip', icon: MinusCircle },
      showAllowOnce: true,
      showAllowAlways: true,
    },
    paramsTable: {
      columns: [
        { key: 'method', label: 'Method', width: '26%', editable: true, mono: true },
        { key: 'url', label: 'Endpoint', width: '74%', editable: true, mono: true },
      ],
      extractRows: (params: Record<string, any>): Array<[string, ...any[]]> => {
        return [['request', (params.method || 'GET').toUpperCase(), params.url || '']]
      },
    },
  },
  getDynamicText: (params, state) => {
    if (params?.url && typeof params.url === 'string') {
      const method = params.method || 'GET'
      let url = params.url

      // Extract domain from URL for cleaner display
      try {
        const urlObj = new URL(url)
        url = urlObj.hostname + urlObj.pathname
      } catch {
        // Use URL as-is if parsing fails
      }

      switch (state) {
        case ClientToolCallState.success:
          return `${method} ${url} complete`
        case ClientToolCallState.executing:
          return `${method} ${url}`
        case ClientToolCallState.generating:
          return `Preparing ${method} ${url}`
        case ClientToolCallState.pending:
          return `Review ${method} ${url}`
        case ClientToolCallState.error:
          return `Failed ${method} ${url}`
        case ClientToolCallState.rejected:
          return `Skipped ${method} ${url}`
        case ClientToolCallState.aborted:
          return `Aborted ${method} ${url}`
      }
    }
    return undefined
  },
}

const META_manage_custom_tool: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: {
      text: 'Managing custom tool',
      icon: Loader2,
    },
    [ClientToolCallState.pending]: { text: 'Manage custom tool?', icon: Plus },
    [ClientToolCallState.executing]: { text: 'Managing custom tool', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Managed custom tool', icon: Check },
    [ClientToolCallState.error]: { text: 'Failed to manage custom tool', icon: X },
    [ClientToolCallState.aborted]: {
      text: 'Aborted managing custom tool',
      icon: XCircle,
    },
    [ClientToolCallState.rejected]: {
      text: 'Skipped managing custom tool',
      icon: XCircle,
    },
  },
  interrupt: {
    accept: { text: 'Allow', icon: Check },
    reject: { text: 'Skip', icon: XCircle },
  },
  getDynamicText: (params, state) => {
    const operation = params?.operation as 'add' | 'edit' | 'delete' | 'list' | undefined
    const workspaceId = getScopedWorkspaceId(params)

    if (!operation) return undefined

    let toolName = params?.schema?.function?.name
    if (!toolName && params?.toolId && workspaceId) {
      try {
        const tools =
          getQueryClient().getQueryData<CustomToolDefinition[]>(
            customToolsKeys.list(workspaceId)
          ) ?? []
        const tool = tools.find((t) => t.id === params.toolId || t.title === params.toolId)
        toolName = tool?.schema?.function?.name
      } catch {
        // Ignore errors accessing cache
      }
    }

    const getActionText = (verb: 'present' | 'past' | 'gerund') => {
      switch (operation) {
        case 'add':
          return verb === 'present' ? 'Create' : verb === 'past' ? 'Created' : 'Creating'
        case 'edit':
          return verb === 'present' ? 'Edit' : verb === 'past' ? 'Edited' : 'Editing'
        case 'delete':
          return verb === 'present' ? 'Delete' : verb === 'past' ? 'Deleted' : 'Deleting'
        case 'list':
          return verb === 'present' ? 'List' : verb === 'past' ? 'Listed' : 'Listing'
        default:
          return verb === 'present' ? 'Manage' : verb === 'past' ? 'Managed' : 'Managing'
      }
    }

    // For add: only show tool name in past tense (success)
    // For edit/delete: always show tool name
    // For list: never show individual tool name, use plural
    const shouldShowToolName = (currentState: ClientToolCallState) => {
      if (operation === 'list') return false
      if (operation === 'add') {
        return currentState === ClientToolCallState.success
      }
      return true // edit and delete always show tool name
    }

    const nameText =
      operation === 'list'
        ? ' custom tools'
        : shouldShowToolName(state) && toolName
          ? ` ${toolName}`
          : ' custom tool'

    switch (state) {
      case ClientToolCallState.success:
        return `${getActionText('past')}${nameText}`
      case ClientToolCallState.executing:
        return `${getActionText('gerund')}${nameText}`
      case ClientToolCallState.generating:
        return `${getActionText('gerund')}${nameText}`
      case ClientToolCallState.pending:
        return `${getActionText('present')}${nameText}?`
      case ClientToolCallState.error:
        return `Failed to ${getActionText('present')?.toLowerCase()}${nameText}`
      case ClientToolCallState.aborted:
        return `Aborted ${getActionText('gerund')?.toLowerCase()}${nameText}`
      case ClientToolCallState.rejected:
        return `Skipped ${getActionText('gerund')?.toLowerCase()}${nameText}`
    }
    return undefined
  },
}

const META_manage_mcp_tool: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: {
      text: 'Managing MCP tool',
      icon: Loader2,
    },
    [ClientToolCallState.pending]: { text: 'Manage MCP tool?', icon: Server },
    [ClientToolCallState.executing]: { text: 'Managing MCP tool', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Managed MCP tool', icon: Check },
    [ClientToolCallState.error]: { text: 'Failed to manage MCP tool', icon: X },
    [ClientToolCallState.aborted]: {
      text: 'Aborted managing MCP tool',
      icon: XCircle,
    },
    [ClientToolCallState.rejected]: {
      text: 'Skipped managing MCP tool',
      icon: XCircle,
    },
  },
  interrupt: {
    accept: { text: 'Allow', icon: Check },
    reject: { text: 'Skip', icon: XCircle },
  },
  getDynamicText: (params, state) => {
    const operation = params?.operation as 'add' | 'edit' | 'delete' | undefined

    if (!operation) return undefined

    const serverName = params?.config?.name || params?.serverName

    const getActionText = (verb: 'present' | 'past' | 'gerund') => {
      switch (operation) {
        case 'add':
          return verb === 'present' ? 'Add' : verb === 'past' ? 'Added' : 'Adding'
        case 'edit':
          return verb === 'present' ? 'Edit' : verb === 'past' ? 'Edited' : 'Editing'
        case 'delete':
          return verb === 'present' ? 'Delete' : verb === 'past' ? 'Deleted' : 'Deleting'
      }
    }

    const shouldShowServerName = (currentState: ClientToolCallState) => {
      if (operation === 'add') {
        return currentState === ClientToolCallState.success
      }
      return true
    }

    const nameText = shouldShowServerName(state) && serverName ? ` ${serverName}` : ' MCP tool'

    switch (state) {
      case ClientToolCallState.success:
        return `${getActionText('past')}${nameText}`
      case ClientToolCallState.executing:
        return `${getActionText('gerund')}${nameText}`
      case ClientToolCallState.generating:
        return `${getActionText('gerund')}${nameText}`
      case ClientToolCallState.pending:
        return `${getActionText('present')}${nameText}?`
      case ClientToolCallState.error:
        return `Failed to ${getActionText('present')?.toLowerCase()}${nameText}`
      case ClientToolCallState.aborted:
        return `Aborted ${getActionText('gerund')?.toLowerCase()}${nameText}`
      case ClientToolCallState.rejected:
        return `Skipped ${getActionText('gerund')?.toLowerCase()}${nameText}`
    }
    return undefined
  },
}

const META_mark_todo_in_progress: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Marking todo in progress', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Marking todo in progress', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Marking todo in progress', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Marked todo in progress', icon: Loader2 },
    [ClientToolCallState.error]: { text: 'Failed to mark in progress', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted marking in progress', icon: MinusCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped marking in progress', icon: MinusCircle },
  },
}

const META_open_resource: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Opening resource', icon: Eye },
    [ClientToolCallState.pending]: { text: 'Opening resource', icon: Eye },
    [ClientToolCallState.executing]: { text: 'Opening resource', icon: Eye },
    [ClientToolCallState.success]: { text: 'Opened resource', icon: Eye },
    [ClientToolCallState.error]: { text: 'Failed to open resource', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped opening resource', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted opening resource', icon: XCircle },
  },
}

const META_navigate_ui: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: {
      text: 'Preparing to open',
      icon: Loader2,
    },
    [ClientToolCallState.pending]: { text: 'Open?', icon: Navigation },
    [ClientToolCallState.executing]: { text: 'Opening', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Opened', icon: Navigation },
    [ClientToolCallState.error]: { text: 'Failed to open', icon: X },
    [ClientToolCallState.aborted]: {
      text: 'Aborted opening',
      icon: XCircle,
    },
    [ClientToolCallState.rejected]: {
      text: 'Skipped opening',
      icon: XCircle,
    },
  },
  interrupt: {
    accept: { text: 'Open', icon: Navigation },
    reject: { text: 'Skip', icon: XCircle },
  },
  getDynamicText: (params, state) => {
    const destination = params?.destination as NavigationDestination | undefined
    const workflowName = params?.workflowName

    const action = 'open'
    const actionCapitalized = 'Open'
    const actionPast = 'opened'
    const actionIng = 'opening'
    let target = ''

    if (destination === 'workflow' && workflowName) {
      target = ` workflow "${workflowName}"`
    } else if (destination === 'workflow') {
      target = ' workflows'
    } else if (destination === 'logs') {
      target = ' logs'
    } else if (destination === 'templates') {
      target = ' templates'
    } else if (destination === 'vector_db') {
      target = ' vector database'
    } else if (destination === 'settings') {
      target = ' settings'
    }

    const fullAction = `${action}${target}`
    const fullActionCapitalized = `${actionCapitalized}${target}`
    const fullActionPast = `${actionPast}${target}`
    const fullActionIng = `${actionIng}${target}`

    switch (state) {
      case ClientToolCallState.success:
        return fullActionPast.charAt(0).toUpperCase() + fullActionPast.slice(1)
      case ClientToolCallState.executing:
        return fullActionIng.charAt(0).toUpperCase() + fullActionIng.slice(1)
      case ClientToolCallState.generating:
        return `Preparing to ${fullAction}`
      case ClientToolCallState.pending:
        return `${fullActionCapitalized}?`
      case ClientToolCallState.error:
        return `Failed to ${fullAction}`
      case ClientToolCallState.aborted:
        return `Aborted ${fullAction}`
      case ClientToolCallState.rejected:
        return `Skipped ${fullAction}`
    }
    return undefined
  },
}

const META_oauth_request_access: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Requesting integration access', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Requesting integration access', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Requesting integration access', icon: Loader2 },
    [ClientToolCallState.rejected]: { text: 'Skipped integration access', icon: MinusCircle },
    [ClientToolCallState.success]: { text: 'Requested integration access', icon: CheckCircle },
    [ClientToolCallState.error]: { text: 'Failed to request integration access', icon: X },
    [ClientToolCallState.aborted]: { text: 'Aborted integration access request', icon: XCircle },
  },
  interrupt: {
    accept: { text: 'Connect', icon: PlugZap },
    reject: { text: 'Skip', icon: MinusCircle },
  },
  getDynamicText: (params, state) => {
    if (params.providerName) {
      const name = params.providerName
      switch (state) {
        case ClientToolCallState.generating:
        case ClientToolCallState.pending:
        case ClientToolCallState.executing:
          return `Requesting ${name} access`
        case ClientToolCallState.rejected:
          return `Skipped ${name} access`
        case ClientToolCallState.success:
          return `Requested ${name} access`
        case ClientToolCallState.error:
          return `Failed to request ${name} access`
        case ClientToolCallState.aborted:
          return `Aborted ${name} access request`
      }
    }
    return undefined
  },
}

const META_redeploy: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Redeploying workflow', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Redeploy workflow', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Redeploying workflow', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Redeployed workflow', icon: Rocket },
    [ClientToolCallState.error]: { text: 'Failed to redeploy workflow', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted redeploy', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped redeploy', icon: XCircle },
  },
  interrupt: undefined,
}

const META_research: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Researching', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Researching', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Researching', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Researched', icon: Search },
    [ClientToolCallState.error]: { text: 'Failed to research', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped research', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted research', icon: XCircle },
  },
  uiConfig: {
    subagent: {
      streamingLabel: 'Researching',
      completedLabel: 'Researched',
      shouldCollapse: true,
      outputArtifacts: [],
    },
  },
}

const META_generate_api_key: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Preparing to generate API key', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Generate API key?', icon: KeyRound },
    [ClientToolCallState.executing]: { text: 'Generating API key', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Generated API key', icon: KeyRound },
    [ClientToolCallState.error]: { text: 'Failed to generate API key', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped generating API key', icon: MinusCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted generating API key', icon: XCircle },
  },
  interrupt: {
    accept: { text: 'Generate', icon: KeyRound },
    reject: { text: 'Skip', icon: MinusCircle },
  },
  uiConfig: {
    interrupt: {
      accept: { text: 'Generate', icon: KeyRound },
      reject: { text: 'Skip', icon: MinusCircle },
      showAllowOnce: true,
      showAllowAlways: true,
    },
  },
  getDynamicText: (params, state) => {
    const name = params?.name
    if (name && typeof name === 'string') {
      switch (state) {
        case ClientToolCallState.success:
          return `Generated API key "${name}"`
        case ClientToolCallState.executing:
          return `Generating API key "${name}"`
        case ClientToolCallState.generating:
          return `Preparing to generate "${name}"`
        case ClientToolCallState.pending:
          return `Generate API key "${name}"?`
        case ClientToolCallState.error:
          return `Failed to generate "${name}"`
      }
    }
    return undefined
  },
}

const META_run_block: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Preparing to run block', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Run block?', icon: Play },
    [ClientToolCallState.executing]: { text: 'Running block', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Ran block', icon: Play },
    [ClientToolCallState.error]: { text: 'Failed to run block', icon: XCircle },
    [ClientToolCallState.cancelled]: { text: 'Stopped by user', icon: MinusCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped running block', icon: MinusCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted running block', icon: MinusCircle },
    [ClientToolCallState.background]: { text: 'Running block in background', icon: Play },
  },
  interrupt: {
    accept: { text: 'Run', icon: Play },
    reject: { text: 'Skip', icon: MinusCircle },
  },
  uiConfig: {
    isSpecial: true,
    interrupt: {
      accept: { text: 'Run', icon: Play },
      reject: { text: 'Skip', icon: MinusCircle },
      showAllowOnce: true,
      showAllowAlways: true,
    },
    secondaryAction: {
      text: 'Move to Background',
      title: 'Move to Background',
      variant: 'tertiary',
      showInStates: [ClientToolCallState.executing],
      completionMessage:
        'The user has chosen to move the block execution to the background. Check back with them later to know when the block execution is complete',
      targetState: ClientToolCallState.background,
    },
  },
  getDynamicText: (params, state) => {
    const blockId = params?.blockId || params?.block_id
    if (blockId && typeof blockId === 'string') {
      const name = resolveBlockName(blockId) || blockId
      switch (state) {
        case ClientToolCallState.success:
          return `Ran ${name}`
        case ClientToolCallState.executing:
          return `Running ${name}`
        case ClientToolCallState.generating:
          return `Preparing to run ${name}`
        case ClientToolCallState.pending:
          return `Run ${name}?`
        case ClientToolCallState.error:
          return `Failed to run ${name}`
        case ClientToolCallState.cancelled:
          return `Stopped running ${name}`
        case ClientToolCallState.rejected:
          return `Skipped running ${name}`
        case ClientToolCallState.aborted:
          return `Aborted running ${name}`
        case ClientToolCallState.background:
          return `Running ${name} in background`
      }
    }
    return undefined
  },
}

const META_run_from_block: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Preparing to run from block', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Run from block?', icon: Play },
    [ClientToolCallState.executing]: { text: 'Running from block', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Ran from block', icon: Play },
    [ClientToolCallState.error]: { text: 'Failed to run from block', icon: XCircle },
    [ClientToolCallState.cancelled]: { text: 'Stopped by user', icon: MinusCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped running from block', icon: MinusCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted running from block', icon: MinusCircle },
    [ClientToolCallState.background]: { text: 'Running from block in background', icon: Play },
  },
  interrupt: {
    accept: { text: 'Run', icon: Play },
    reject: { text: 'Skip', icon: MinusCircle },
  },
  uiConfig: {
    isSpecial: true,
    interrupt: {
      accept: { text: 'Run', icon: Play },
      reject: { text: 'Skip', icon: MinusCircle },
      showAllowOnce: true,
      showAllowAlways: true,
    },
    secondaryAction: {
      text: 'Move to Background',
      title: 'Move to Background',
      variant: 'tertiary',
      showInStates: [ClientToolCallState.executing],
      completionMessage:
        'The user has chosen to move the workflow execution to the background. Check back with them later to know when the workflow execution is complete',
      targetState: ClientToolCallState.background,
    },
  },
  getDynamicText: (params, state) => {
    const blockId = params?.startBlockId || params?.start_block_id
    if (blockId && typeof blockId === 'string') {
      const name = resolveBlockName(blockId) || blockId
      switch (state) {
        case ClientToolCallState.success:
          return `Ran from ${name}`
        case ClientToolCallState.executing:
          return `Running from ${name}`
        case ClientToolCallState.generating:
          return `Preparing to run from ${name}`
        case ClientToolCallState.pending:
          return `Run from ${name}?`
        case ClientToolCallState.error:
          return `Failed to run from ${name}`
        case ClientToolCallState.cancelled:
          return `Stopped running from ${name}`
        case ClientToolCallState.rejected:
          return `Skipped running from ${name}`
        case ClientToolCallState.aborted:
          return `Aborted running from ${name}`
        case ClientToolCallState.background:
          return `Running from ${name} in background`
      }
    }
    return undefined
  },
}

const META_run_workflow_until_block: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Preparing to run until block', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Run until block?', icon: Play },
    [ClientToolCallState.executing]: { text: 'Running until block', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Ran until block', icon: Play },
    [ClientToolCallState.error]: { text: 'Failed to run until block', icon: XCircle },
    [ClientToolCallState.cancelled]: { text: 'Stopped by user', icon: MinusCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped running until block', icon: MinusCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted running until block', icon: MinusCircle },
    [ClientToolCallState.background]: { text: 'Running until block in background', icon: Play },
  },
  interrupt: {
    accept: { text: 'Run', icon: Play },
    reject: { text: 'Skip', icon: MinusCircle },
  },
  uiConfig: {
    isSpecial: true,
    interrupt: {
      accept: { text: 'Run', icon: Play },
      reject: { text: 'Skip', icon: MinusCircle },
      showAllowOnce: true,
      showAllowAlways: true,
    },
    secondaryAction: {
      text: 'Move to Background',
      title: 'Move to Background',
      variant: 'tertiary',
      showInStates: [ClientToolCallState.executing],
      completionMessage:
        'The user has chosen to move the workflow execution to the background. Check back with them later to know when the workflow execution is complete',
      targetState: ClientToolCallState.background,
    },
  },
  getDynamicText: (params, state) => {
    const blockId = params?.stopAfterBlockId || params?.stop_after_block_id
    if (blockId && typeof blockId === 'string') {
      const name = resolveBlockName(blockId) || blockId
      switch (state) {
        case ClientToolCallState.success:
          return `Ran until ${name}`
        case ClientToolCallState.executing:
          return `Running until ${name}`
        case ClientToolCallState.generating:
          return `Preparing to run until ${name}`
        case ClientToolCallState.pending:
          return `Run until ${name}?`
        case ClientToolCallState.error:
          return `Failed to run until ${name}`
        case ClientToolCallState.cancelled:
          return `Stopped running until ${name}`
        case ClientToolCallState.rejected:
          return `Skipped running until ${name}`
        case ClientToolCallState.aborted:
          return `Aborted running until ${name}`
        case ClientToolCallState.background:
          return `Running until ${name} in background`
      }
    }
    return undefined
  },
}

const META_run_workflow: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Preparing to run your workflow', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Run this workflow?', icon: Play },
    [ClientToolCallState.executing]: { text: 'Running your workflow', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Executed workflow', icon: Play },
    [ClientToolCallState.error]: { text: 'Errored running workflow', icon: XCircle },
    [ClientToolCallState.cancelled]: { text: 'Stopped by user', icon: MinusCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped workflow execution', icon: MinusCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted workflow execution', icon: MinusCircle },
    [ClientToolCallState.background]: { text: 'Running in background', icon: Play },
  },
  interrupt: {
    accept: { text: 'Run', icon: Play },
    reject: { text: 'Skip', icon: MinusCircle },
  },
  uiConfig: {
    isSpecial: true,
    interrupt: {
      accept: { text: 'Run', icon: Play },
      reject: { text: 'Skip', icon: MinusCircle },
      showAllowOnce: true,
      showAllowAlways: true,
    },
    secondaryAction: {
      text: 'Move to Background',
      title: 'Move to Background',
      variant: 'tertiary',
      showInStates: [ClientToolCallState.executing],
      completionMessage:
        'The user has chosen to move the workflow execution to the background. Check back with them later to know when the workflow execution is complete',
      targetState: ClientToolCallState.background,
    },
    paramsTable: {
      columns: [
        { key: 'input', label: 'Input', width: '36%' },
        { key: 'value', label: 'Value', width: '64%', editable: true, mono: true },
      ],
      extractRows: (params: Record<string, any>): Array<[string, ...any[]]> => {
        let inputs = params.input || params.inputs || params.workflow_input
        if (typeof inputs === 'string') {
          try {
            inputs = JSON.parse(inputs)
          } catch {
            inputs = {}
          }
        }
        if (params.workflow_input && typeof params.workflow_input === 'object') {
          inputs = params.workflow_input
        }
        if (!inputs || typeof inputs !== 'object') {
          const { workflowId, workflow_input, ...rest } = params
          inputs = rest
        }
        const safeInputs = inputs && typeof inputs === 'object' ? inputs : {}
        return Object.entries(safeInputs).map(([key, value]) => [key, key, String(value)])
      },
    },
  },
  getDynamicText: (params, state) => {
    const workflowId = params?.workflowId || useWorkflowRegistry.getState().activeWorkflowId
    const workspaceId = getScopedWorkspaceId(params)
    if (workflowId && workspaceId) {
      const workflowName = getWorkflowById(workspaceId, workflowId)?.name
      if (workflowName) {
        switch (state) {
          case ClientToolCallState.success:
            return `Ran ${workflowName}`
          case ClientToolCallState.executing:
            return `Running ${workflowName}`
          case ClientToolCallState.generating:
            return `Preparing to run ${workflowName}`
          case ClientToolCallState.pending:
            return `Run ${workflowName}?`
          case ClientToolCallState.error:
            return `Failed to run ${workflowName}`
          case ClientToolCallState.cancelled:
            return `Stopped ${workflowName}`
          case ClientToolCallState.rejected:
            return `Skipped running ${workflowName}`
          case ClientToolCallState.aborted:
            return `Aborted running ${workflowName}`
          case ClientToolCallState.background:
            return `Running ${workflowName} in background`
        }
      }
    }
    return undefined
  },
}

const META_scrape_page: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Scraping page', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Scraping page', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Scraping page', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Scraped page', icon: Globe },
    [ClientToolCallState.error]: { text: 'Failed to scrape page', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted scraping page', icon: MinusCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped scraping page', icon: MinusCircle },
  },
  interrupt: undefined,
  getDynamicText: (params, state) => {
    if (params?.url && typeof params.url === 'string') {
      const url = params.url

      switch (state) {
        case ClientToolCallState.success:
          return `Scraped ${url}`
        case ClientToolCallState.executing:
        case ClientToolCallState.generating:
        case ClientToolCallState.pending:
          return `Scraping ${url}`
        case ClientToolCallState.error:
          return `Failed to scrape ${url}`
        case ClientToolCallState.aborted:
          return `Aborted scraping ${url}`
        case ClientToolCallState.rejected:
          return `Skipped scraping ${url}`
      }
    }
    return undefined
  },
}

const META_search_documentation: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Searching documentation', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Searching documentation', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Searching documentation', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Completed documentation search', icon: BookOpen },
    [ClientToolCallState.error]: { text: 'Failed to search docs', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted documentation search', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped documentation search', icon: MinusCircle },
  },
  getDynamicText: (params, state) => {
    if (params?.query && typeof params.query === 'string') {
      const query = params.query

      switch (state) {
        case ClientToolCallState.success:
          return `Searched docs for ${query}`
        case ClientToolCallState.executing:
        case ClientToolCallState.generating:
        case ClientToolCallState.pending:
          return `Searching docs for ${query}`
        case ClientToolCallState.error:
          return `Failed to search docs for ${query}`
        case ClientToolCallState.aborted:
          return `Aborted searching docs for ${query}`
        case ClientToolCallState.rejected:
          return `Skipped searching docs for ${query}`
      }
    }
    return undefined
  },
}

const META_search_library_docs: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Reading docs', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Reading docs', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Reading docs', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Read docs', icon: BookOpen },
    [ClientToolCallState.error]: { text: 'Failed to read docs', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted reading docs', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped reading docs', icon: MinusCircle },
  },
  getDynamicText: (params, state) => {
    const libraryName = params?.library_name
    if (libraryName && typeof libraryName === 'string') {
      switch (state) {
        case ClientToolCallState.success:
          return `Read ${libraryName} docs`
        case ClientToolCallState.executing:
        case ClientToolCallState.generating:
        case ClientToolCallState.pending:
          return `Reading ${libraryName} docs`
        case ClientToolCallState.error:
          return `Failed to read ${libraryName} docs`
        case ClientToolCallState.aborted:
          return `Aborted reading ${libraryName} docs`
        case ClientToolCallState.rejected:
          return `Skipped reading ${libraryName} docs`
      }
    }
    return undefined
  },
}

const META_search_online: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Searching online', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Searching online', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Searching online', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Completed online search', icon: Globe },
    [ClientToolCallState.error]: { text: 'Failed to search online', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped online search', icon: MinusCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted online search', icon: XCircle },
  },
  interrupt: undefined,
  getDynamicText: (params, state) => {
    if (params?.query && typeof params.query === 'string') {
      const query = params.query

      switch (state) {
        case ClientToolCallState.success:
          return `Searched online for ${query}`
        case ClientToolCallState.executing:
        case ClientToolCallState.generating:
        case ClientToolCallState.pending:
          return `Searching online for ${query}`
        case ClientToolCallState.error:
          return `Failed to search online for ${query}`
        case ClientToolCallState.aborted:
          return `Aborted searching online for ${query}`
        case ClientToolCallState.rejected:
          return `Skipped searching online for ${query}`
      }
    }
    return undefined
  },
}

const META_search_patterns: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Searching workflow patterns', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Searching workflow patterns', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Searching workflow patterns', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Found workflow patterns', icon: Search },
    [ClientToolCallState.error]: { text: 'Failed to search patterns', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted pattern search', icon: MinusCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped pattern search', icon: MinusCircle },
  },
  interrupt: undefined,
  getDynamicText: (params, state) => {
    if (params?.queries && Array.isArray(params.queries) && params.queries.length > 0) {
      const firstQuery = String(params.queries[0])

      switch (state) {
        case ClientToolCallState.success:
          return `Searched ${firstQuery}`
        case ClientToolCallState.executing:
        case ClientToolCallState.generating:
        case ClientToolCallState.pending:
          return `Searching ${firstQuery}`
        case ClientToolCallState.error:
          return `Failed to search ${firstQuery}`
        case ClientToolCallState.aborted:
          return `Aborted searching ${firstQuery}`
        case ClientToolCallState.rejected:
          return `Skipped searching ${firstQuery}`
      }
    }
    return undefined
  },
}

const META_set_environment_variables: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: {
      text: 'Preparing to set environment variables',
      icon: Loader2,
    },
    [ClientToolCallState.pending]: { text: 'Set environment variables?', icon: Settings2 },
    [ClientToolCallState.executing]: { text: 'Setting environment variables', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Set environment variables', icon: Settings2 },
    [ClientToolCallState.error]: { text: 'Failed to set environment variables', icon: X },
    [ClientToolCallState.aborted]: {
      text: 'Aborted setting environment variables',
      icon: XCircle,
    },
    [ClientToolCallState.rejected]: {
      text: 'Skipped setting environment variables',
      icon: XCircle,
    },
  },
  interrupt: {
    accept: { text: 'Apply', icon: Settings2 },
    reject: { text: 'Skip', icon: XCircle },
  },
  uiConfig: {
    alwaysExpanded: true,
    interrupt: {
      accept: { text: 'Apply', icon: Settings2 },
      reject: { text: 'Skip', icon: XCircle },
      showAllowOnce: true,
      showAllowAlways: true,
    },
    paramsTable: {
      columns: [
        { key: 'name', label: 'Variable', width: '36%', editable: true },
        { key: 'value', label: 'Value', width: '64%', editable: true, mono: true },
      ],
      extractRows: (params: Record<string, any>): Array<[string, ...any[]]> => {
        const variables = params.variables || {}
        const entries = Array.isArray(variables)
          ? variables.map((v: any, i: number) => [String(i), v.name || `var_${i}`, v.value || ''])
          : Object.entries(variables).map(([key, val]) => {
              if (typeof val === 'object' && val !== null && 'value' in (val as any)) {
                return [key, key, (val as any).value]
              }
              return [key, key, val]
            })
        return entries as Array<[string, ...any[]]>
      },
    },
  },
  getDynamicText: (params, state) => {
    if (params?.variables && typeof params.variables === 'object') {
      const count = Object.keys(params.variables).length
      const varText = count === 1 ? 'variable' : 'variables'

      switch (state) {
        case ClientToolCallState.success:
          return `Set ${count} ${varText}`
        case ClientToolCallState.executing:
          return `Setting ${count} ${varText}`
        case ClientToolCallState.generating:
          return `Preparing to set ${count} ${varText}`
        case ClientToolCallState.pending:
          return `Set ${count} ${varText}?`
        case ClientToolCallState.error:
          return `Failed to set ${count} ${varText}`
        case ClientToolCallState.aborted:
          return `Aborted setting ${count} ${varText}`
        case ClientToolCallState.rejected:
          return `Skipped setting ${count} ${varText}`
      }
    }
    return undefined
  },
}

const META_set_global_workflow_variables: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: {
      text: 'Preparing to set workflow variables',
      icon: Loader2,
    },
    [ClientToolCallState.pending]: { text: 'Set workflow variables?', icon: Settings2 },
    [ClientToolCallState.executing]: { text: 'Setting workflow variables', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Updated workflow variables', icon: Settings2 },
    [ClientToolCallState.error]: { text: 'Failed to set workflow variables', icon: X },
    [ClientToolCallState.aborted]: { text: 'Aborted setting variables', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped setting variables', icon: XCircle },
  },
  interrupt: {
    accept: { text: 'Apply', icon: Settings2 },
    reject: { text: 'Skip', icon: XCircle },
  },
  uiConfig: {
    interrupt: {
      accept: { text: 'Apply', icon: Settings2 },
      reject: { text: 'Skip', icon: XCircle },
      showAllowOnce: true,
      showAllowAlways: true,
    },
    paramsTable: {
      columns: [
        { key: 'name', label: 'Name', width: '40%', editable: true, mono: true },
        { key: 'value', label: 'Value', width: '60%', editable: true, mono: true },
      ],
      extractRows: (params: Record<string, any>): Array<[string, ...any[]]> => {
        const operations = params.operations || []
        return operations.map((op: any, idx: number) => [
          String(idx),
          op.name || '',
          String(op.value ?? ''),
        ])
      },
    },
  },
  getDynamicText: (params, state) => {
    if (params?.operations && Array.isArray(params.operations)) {
      const varNames = params.operations
        .slice(0, 2)
        .map((op: any) => op.name)
        .filter(Boolean)

      if (varNames.length > 0) {
        const varList = varNames.join(', ')
        const more = params.operations.length > 2 ? '...' : ''
        const displayText = `${varList}${more}`

        switch (state) {
          case ClientToolCallState.success:
            return `Set ${displayText}`
          case ClientToolCallState.executing:
            return `Setting ${displayText}`
          case ClientToolCallState.generating:
            return `Preparing to set ${displayText}`
          case ClientToolCallState.pending:
            return `Set ${displayText}?`
          case ClientToolCallState.error:
            return `Failed to set ${displayText}`
          case ClientToolCallState.aborted:
            return `Aborted setting ${displayText}`
          case ClientToolCallState.rejected:
            return `Skipped setting ${displayText}`
        }
      }
    }
    return undefined
  },
}

const META_sleep: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Preparing to sleep', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Sleeping', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Sleeping', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Finished sleeping', icon: Moon },
    [ClientToolCallState.error]: { text: 'Interrupted sleep', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped sleep', icon: MinusCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted sleep', icon: MinusCircle },
    [ClientToolCallState.background]: { text: 'Resumed', icon: Moon },
  },
  uiConfig: {
    secondaryAction: {
      text: 'Wake',
      title: 'Wake',
      variant: 'tertiary',
      showInStates: [ClientToolCallState.executing],
      targetState: ClientToolCallState.background,
    },
  },
  // No interrupt - auto-execute immediately
  getDynamicText: (params, state) => {
    const seconds = params?.seconds
    if (typeof seconds === 'number' && seconds > 0) {
      const displayTime = formatDuration(seconds)
      switch (state) {
        case ClientToolCallState.success:
          return `Slept for ${displayTime}`
        case ClientToolCallState.executing:
        case ClientToolCallState.pending:
          return `Sleeping for ${displayTime}`
        case ClientToolCallState.generating:
          return `Preparing to sleep for ${displayTime}`
        case ClientToolCallState.error:
          return `Failed to sleep for ${displayTime}`
        case ClientToolCallState.rejected:
          return `Skipped sleeping for ${displayTime}`
        case ClientToolCallState.aborted:
          return `Aborted sleeping for ${displayTime}`
        case ClientToolCallState.background: {
          // Calculate elapsed time from when sleep started
          const elapsedSeconds = params?._elapsedSeconds
          if (typeof elapsedSeconds === 'number' && elapsedSeconds > 0) {
            return `Resumed after ${formatDuration(Math.round(elapsedSeconds))}`
          }
          return 'Resumed early'
        }
      }
    }
    return undefined
  },
}

const META_summarize_conversation: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Summarizing conversation', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Summarizing conversation', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Summarizing conversation', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Summarized conversation', icon: PencilLine },
    [ClientToolCallState.error]: { text: 'Failed to summarize conversation', icon: XCircle },
    [ClientToolCallState.aborted]: {
      text: 'Aborted summarizing conversation',
      icon: MinusCircle,
    },
    [ClientToolCallState.rejected]: {
      text: 'Skipped summarizing conversation',
      icon: MinusCircle,
    },
  },
  interrupt: undefined,
}

const META_superagent: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Superagent working', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Superagent working', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Superagent working', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Superagent completed', icon: Sparkles },
    [ClientToolCallState.error]: { text: 'Superagent failed', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Superagent skipped', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Superagent aborted', icon: XCircle },
  },
  uiConfig: {
    subagent: {
      streamingLabel: 'Superagent working',
      completedLabel: 'Superagent completed',
      shouldCollapse: true,
      outputArtifacts: [],
    },
  },
}

const META_plan: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Planning', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Planning', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Planning', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Planned', icon: ClipboardList },
    [ClientToolCallState.error]: { text: 'Failed to plan', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped planning', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted planning', icon: XCircle },
  },
  uiConfig: {
    subagent: {
      streamingLabel: 'Planning',
      completedLabel: 'Planned',
      shouldCollapse: true,
      outputArtifacts: [],
    },
  },
}

const META_edit: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Editing', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Editing', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Editing', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Edited', icon: PencilLine },
    [ClientToolCallState.error]: { text: 'Failed to edit', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped editing', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted editing', icon: XCircle },
  },
  uiConfig: {
    subagent: {
      streamingLabel: 'Editing',
      completedLabel: 'Edited',
      shouldCollapse: true,
      outputArtifacts: [],
    },
  },
}

const META_fast_edit: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Building', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Building', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Building', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Built', icon: Wrench },
    [ClientToolCallState.error]: { text: 'Failed to build', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped build', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted build', icon: XCircle },
  },
  uiConfig: {
    subagent: {
      streamingLabel: 'Building',
      completedLabel: 'Built',
      shouldCollapse: true,
      outputArtifacts: [],
    },
  },
}

const META_debug: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Debugging', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Debugging', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Debugging', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Debugged', icon: Bug },
    [ClientToolCallState.error]: { text: 'Failed to debug', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped debugging', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted debugging', icon: XCircle },
  },
  uiConfig: {
    subagent: {
      streamingLabel: 'Debugging',
      completedLabel: 'Debugged',
      shouldCollapse: true,
      outputArtifacts: [],
    },
  },
}

const META_table: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Managing tables', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Managing tables', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Managing tables', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Tables updated', icon: Table },
    [ClientToolCallState.error]: { text: 'Failed to manage tables', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped table operation', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted table operation', icon: XCircle },
  },
  uiConfig: {
    subagent: {
      streamingLabel: 'Managing tables',
      completedLabel: 'Tables updated',
      shouldCollapse: true,
      outputArtifacts: [],
    },
  },
}

const META_run: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Running', icon: Loader2 },
    [ClientToolCallState.pending]: { text: 'Running', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Running', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Ran', icon: Play },
    [ClientToolCallState.error]: { text: 'Failed to run', icon: XCircle },
    [ClientToolCallState.rejected]: { text: 'Skipped run', icon: XCircle },
    [ClientToolCallState.aborted]: { text: 'Aborted run', icon: XCircle },
  },
  uiConfig: {
    subagent: {
      streamingLabel: 'Running',
      completedLabel: 'Ran',
      shouldCollapse: true,
      outputArtifacts: [],
    },
  },
}

const META_get_deployed_workflow_state: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Checking deployed state', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Checking deployed state', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Retrieved deployed state', icon: Eye },
    [ClientToolCallState.error]: { text: 'Failed to get deployed state', icon: XCircle },
  },
}

const META_list_user_workspaces: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Listing workspaces', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Listing workspaces', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Listed workspaces', icon: Grid2x2 },
    [ClientToolCallState.error]: { text: 'Failed to list workspaces', icon: XCircle },
  },
}

const META_list_folders: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Listing folders', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Listing folders', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Listed folders', icon: FolderPlus },
    [ClientToolCallState.error]: { text: 'Failed to list folders', icon: XCircle },
  },
}

const META_create_workflow: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Creating workflow', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Creating workflow', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Created workflow', icon: Plus },
    [ClientToolCallState.error]: { text: 'Failed to create workflow', icon: XCircle },
  },
}

const META_create_folder: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Creating folder', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Creating folder', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Created folder', icon: FolderPlus },
    [ClientToolCallState.error]: { text: 'Failed to create folder', icon: XCircle },
  },
}

const META_rename_workflow: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Renaming workflow', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Renaming workflow', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Renamed workflow', icon: PencilLine },
    [ClientToolCallState.error]: { text: 'Failed to rename workflow', icon: XCircle },
  },
}

const META_move_workflow: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Moving workflow', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Moving workflow', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Moved workflow', icon: Navigation },
    [ClientToolCallState.error]: { text: 'Failed to move workflow', icon: XCircle },
  },
}

const META_move_folder: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Moving folder', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Moving folder', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Moved folder', icon: Navigation },
    [ClientToolCallState.error]: { text: 'Failed to move folder', icon: XCircle },
  },
}

const META_oauth_get_auth_link: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Getting auth link', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Getting auth link', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Got auth link', icon: Link },
    [ClientToolCallState.error]: { text: 'Failed to get auth link', icon: XCircle },
  },
}

const META_user_memory: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Accessing memory', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Accessing memory', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Accessed memory', icon: BookOpen },
    [ClientToolCallState.error]: { text: 'Failed to access memory', icon: XCircle },
  },
}

const META_user_table: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Querying table', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Querying table', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Table operation complete', icon: Database },
    [ClientToolCallState.error]: { text: 'Table operation failed', icon: XCircle },
  },
}

const META_tool_search_tool_regex: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Searching tools', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Searching tools', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Found tools', icon: Search },
    [ClientToolCallState.error]: { text: 'Tool search failed', icon: XCircle },
  },
}

const META_grep: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Searching', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Searching', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Search complete', icon: FileSearch },
    [ClientToolCallState.error]: { text: 'Search failed', icon: XCircle },
  },
}

const META_glob: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Finding files', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Finding files', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Files found', icon: FileSearch },
    [ClientToolCallState.error]: { text: 'File search failed', icon: XCircle },
  },
}

const META_read: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Reading', icon: Loader2 },
    [ClientToolCallState.executing]: { text: 'Reading', icon: Loader2 },
    [ClientToolCallState.success]: { text: 'Read complete', icon: FileText },
    [ClientToolCallState.error]: { text: 'Read failed', icon: XCircle },
  },
}

const META_context_compaction: ToolMetadata = {
  displayNames: {
    [ClientToolCallState.generating]: { text: 'Compacting context', icon: Sparkles },
    [ClientToolCallState.pending]: { text: 'Compacting context', icon: Sparkles },
    [ClientToolCallState.executing]: { text: 'Compacting context', icon: Sparkles },
    [ClientToolCallState.success]: { text: 'Compacted context', icon: Sparkles },
    [ClientToolCallState.error]: { text: 'Failed to compact context', icon: XCircle },
  },
}

const TOOL_METADATA_BY_ID: Record<string, ToolMetadata> = {
  auth: META_auth,
  context_compaction: META_context_compaction,
  check_deployment_status: META_check_deployment_status,
  checkoff_todo: META_checkoff_todo,
  crawl_website: META_crawl_website,
  create_workspace_mcp_server: META_create_workspace_mcp_server,
  build: META_build,
  create_folder: META_create_folder,
  create_workflow: META_create_workflow,
  agent: META_agent,
  custom_tool: META_custom_tool,
  debug: META_debug,
  deploy: META_deploy,
  deploy_api: META_deploy_api,
  deploy_chat: META_deploy_chat,
  deploy_mcp: META_deploy_mcp,
  edit: META_edit,
  fast_edit: META_fast_edit,
  edit_workflow: META_edit_workflow,
  get_block_outputs: META_get_block_outputs,
  get_block_upstream_references: META_get_block_upstream_references,
  generate_api_key: META_generate_api_key,
  get_deployed_workflow_state: META_get_deployed_workflow_state,
  get_examples_rag: META_get_examples_rag,
  get_operations_examples: META_get_operations_examples,
  get_page_contents: META_get_page_contents,
  get_platform_actions: META_get_platform_actions,
  get_trigger_examples: META_get_trigger_examples,
  get_workflow_logs: META_get_workflow_logs,
  get_workflow_data: META_get_workflow_data,
  glob: META_glob,
  grep: META_grep,
  knowledge: META_knowledge,
  knowledge_base: META_knowledge_base,
  list_folders: META_list_folders,
  list_user_workspaces: META_list_user_workspaces,
  list_workspace_mcp_servers: META_list_workspace_mcp_servers,
  make_api_request: META_make_api_request,
  manage_custom_tool: META_manage_custom_tool,
  manage_mcp_tool: META_manage_mcp_tool,
  manage_skill: META_manage_skill,
  mark_todo_in_progress: META_mark_todo_in_progress,
  move_folder: META_move_folder,
  move_workflow: META_move_workflow,
  navigate_ui: META_navigate_ui,
  oauth_get_auth_link: META_oauth_get_auth_link,
  oauth_request_access: META_oauth_request_access,
  open_resource: META_open_resource,
  plan: META_plan,
  read: META_read,
  redeploy: META_redeploy,
  rename_workflow: META_rename_workflow,
  research: META_research,
  run: META_run,
  run_block: META_run_block,
  run_from_block: META_run_from_block,
  run_workflow: META_run_workflow,
  run_workflow_until_block: META_run_workflow_until_block,
  scrape_page: META_scrape_page,
  search_documentation: META_search_documentation,
  search_library_docs: META_search_library_docs,
  search_online: META_search_online,
  search_patterns: META_search_patterns,
  set_environment_variables: META_set_environment_variables,
  set_global_workflow_variables: META_set_global_workflow_variables,
  sleep: META_sleep,
  summarize_conversation: META_summarize_conversation,
  superagent: META_superagent,
  table: META_table,
  tool_search_tool_regex: META_tool_search_tool_regex,
  user_memory: META_user_memory,
  user_table: META_user_table,
}

export const TOOL_DISPLAY_REGISTRY: Record<string, ToolDisplayEntry> = Object.fromEntries(
  Object.entries(TOOL_METADATA_BY_ID).map(([toolName, metadata]) => [
    toolName,
    toToolDisplayEntry(metadata),
  ])
)
