import { useParams } from 'common' import { Loader2 } from 'lucide-react' import { Button, cn } from 'ui' import { Admonition } from 'ui-patterns/Admonition' import { CodeBlock } from 'ui-patterns/CodeBlock' import { AssistantNotebookPreview } from './AssistantNotebookPreview' import { toAssistantQueryResult } from './AssistantQueryCell.utils' import { Confirm } from './Confirm' import type { ConfirmFooterApprovalState } from './Confirm.utils' import { runNotebookInputSchema } from './Message.utils' import { AlertError } from '@/components/ui/AlertError' import { useNotebookQuery } from '@/data/content/notebooks/notebook-query' import { toWireNotebook } from '@/data/content/notebooks/notebook-schema' import { notebookRunOutputSchema } from '@/lib/ai/tools/notebook-run-output' export type NotebookRunState = | 'input-available' | 'approval-requested' | 'approval-responded' | 'output-denied' | 'output-available' | 'output-error' export interface NotebookRunRendererProps { state: NotebookRunState input: unknown output: unknown confirmState?: ConfirmFooterApprovalState onApprove?: () => void onDeny?: () => void } export const NotebookRunRenderer = ({ state, input, output, confirmState, onApprove, onDeny, }: NotebookRunRendererProps) => { const { ref } = useParams() const parsedInput = runNotebookInputSchema.safeParse(input) const { data: notebook, isLoading, isError, error, } = useNotebookQuery( { projectRef: ref, id: parsedInput.success ? parsedInput.data.id : undefined }, { enabled: parsedInput.success } ) if (!parsedInput.success) { return (
) } const loadingStatus = (
{isLoading && ( <> Loading notebook... )}
) if (isLoading) { return <>{loadingStatus} } if (isError || !notebook) { const loadError = if (confirmState === 'approval-requested') { return ( <> {loadingStatus}
{loadError}
) } return ( <> {loadingStatus}
{loadError} {confirmState !== undefined && ( )}
) } const entries = toWireNotebook(notebook.content).cells.map((cell) => ({ _tag: 'unchanged' as const, cell, })) const parsedOutput = notebookRunOutputSchema.safeParse(output) const isHistoricalRun = state === 'output-available' || state === 'output-error' const referencedUpdatedAt = state === 'output-available' && parsedOutput.success ? parsedOutput.data.updated_at : parsedInput.data.expected_updated_at const hasNotebookChanged = notebook.updated_at !== referencedUpdatedAt const results = parsedOutput.success ? Object.fromEntries( parsedOutput.data.cells.map((cell) => [ cell.cell_id, cell.status === 'error' ? { error: { message: cell.error?.message ?? 'Failed to run query' } } : (toAssistantQueryResult(cell.rows ?? []) ?? { rows: [] }), ]) ) : undefined return ( <> {loadingStatus} {hasNotebookChanged && (
)}
) }