import React, { useMemo, useState } from 'react'; import { Text, View } from 'react-native'; import { Database } from 'lucide-react-native'; import { useAgentBi } from '../../analytics/mixpanelContext'; import type { SuperagentToolRendererProps } from '../../types'; import { getEntityName, getEntitySummary, getRecordArg, PREVIOUS_APPROVAL_NOTE, toKeyValueItems, } from '../entityWidgetUtils'; import { ApprovalCard } from '../primitives/ApprovalCard'; import { ExpandableSection } from '../primitives/ExpandableSection'; import { KeyValueList } from '../primitives/KeyValueList'; import { ToolWidgetRow } from '../primitives/ToolWidgetRow'; import { toolWidgetStyles } from '../primitives/toolWidgetStyles'; import { getWidgetStatus, isActionableTurn, parseToolArgs } from '../toolWidgetUtils'; import { useApprovalSubmit } from '../useApprovalSubmit'; const COPY = { delete_entities: { active: 'Deleting', base: 'Delete', done: 'Deleted' }, update_entities: { active: 'Updating', base: 'Update', done: 'Updated' }, } as const; // update_entities — native port of the web UpdateEntities card. export function UpdateEntitiesWidget(props: SuperagentToolRendererProps) { return ; } // delete_entities — native port of the web DeleteEntities card. export function DeleteEntitiesWidget(props: SuperagentToolRendererProps) { return ; } function EntityWriteWidget({ isLastAssistantMessage, submitToolCallInput, toolCall, toolName, }: SuperagentToolRendererProps & { toolName: keyof typeof COPY }) { const args = useMemo(() => parseToolArgs(toolCall), [toolCall]); const status = getWidgetStatus(toolCall.status); const [expanded, setExpanded] = useState(false); const hasDetails = hasEntityWriteDetails(toolName, args); if (status === 'waiting') { return ( ); } const copy = COPY[toolName]; const title = status === 'running' ? copy.active : status === 'success' ? copy.done : copy.base; const rejected = status === 'stopped' && Boolean(toolCall.requires_user_input); return ( setExpanded((current) => !current) : undefined} status={status} title={title} > ); } export function hasEntityWriteDetails(toolName: string, args: Record | null): boolean { if (Object.keys(getRecordArg(args, 'query')).length > 0) return true; return toolName === 'update_entities' && Object.keys(getRecordArg(args, 'data')).length > 0; } /** Query / "Update with" sections — the web EntityExpandableContent. */ export function EntityWriteDetails({ args, toolName, }: { args: Record | null; toolName: string; }) { const queryItems = toKeyValueItems(getRecordArg(args, 'query')); const dataItems = toolName === 'update_entities' ? toKeyValueItems(getRecordArg(args, 'data')) : []; return ( {queryItems.length > 0 ? ( Query: ) : null} {dataItems.length > 0 ? ( Update with: ) : null} ); } /** Single pending update/delete — the web EntityApprovalCard path. */ function EntityApprovalSingleCard({ args, isLastAssistantMessage, submitToolCallInput, toolCall, toolName, }: { args: Record | null; isLastAssistantMessage: SuperagentToolRendererProps['isLastAssistantMessage']; submitToolCallInput: SuperagentToolRendererProps['submitToolCallInput']; toolCall: SuperagentToolRendererProps['toolCall']; toolName: string; }) { const { canAct, error, isSubmitting, submit } = useApprovalSubmit(toolCall, submitToolCallInput); const bi = useAgentBi(); const summary = getEntitySummary(toolName, args); // Stale turn (web EntityApprovalCard parity): keep the summary, drop the buttons. const actionable = canAct && isActionableTurn(isLastAssistantMessage); return ( { if (await submit(true)) void bi.trackEditor('Entity Write Approval', { batch: false, decision: 'approved' }); } : undefined} onReject={actionable ? async () => { if (await submit(false)) void bi.trackEditor('Entity Write Approval', { batch: false, decision: 'rejected' }); } : undefined} rejectLabel="Reject" title="Approval Required" unavailableNote={isActionableTurn(isLastAssistantMessage) ? undefined : PREVIOUS_APPROVAL_NOTE} > {hasEntityWriteDetails(toolName, args) ? ( ) : ( {summary} )} ); }