import React, { useState } from 'react'; import { useCopilotAction } from '@copilotkit/react-core'; import DiffPreview from './DiffPreview'; import { apiClient } from '../../api/client'; interface HallucinationCheckerProps { buildFullMarkdown: () => string; buildUpdatedMarkdownForClaim: (claimText: string, supportingUrl?: string) => { original: string; updated: string; updatedMarkdown: string; }; applyClaimFix: (claimText: string, supportingUrl?: string) => void; } const useCopilotActionTyped = useCopilotAction as any; export const HallucinationChecker: React.FC = ({ buildFullMarkdown, buildUpdatedMarkdownForClaim, applyClaimFix }) => { const [hallucinationResult, setHallucinationResult] = useState(null); useCopilotActionTyped({ name: 'runHallucinationCheck', description: 'Run hallucination detector on full draft and view claims', parameters: [], handler: async () => { const content = buildFullMarkdown(); const res = await apiClient.post('/api/blog/quality/hallucination-check', { text: content }); const data = res.data; setHallucinationResult(data); return { success: true, total_claims: data?.total_claims }; }, renderAndWaitForResponse: ({ respond, result }: any) => { if (!result) return null; const claims = hallucinationResult?.claims || []; return (
Hallucination Check
Total claims: {hallucinationResult?.total_claims ?? 0}
    {claims.slice(0, 5).map((c: any, i: number) => { const supporting = (c.supporting_sources && c.supporting_sources[0]?.url) || undefined; const { original, updated } = buildUpdatedMarkdownForClaim(c.text, supporting); return (
  • [{c.assessment}] {c.text} (conf: {Math.round((c.confidence || 0)*100)/100})
    {original && updated ? ( { applyClaimFix(c.text, supporting); respond?.('applied'); }} onDiscard={() => { respond?.('discarded'); }} /> ) : (
    No matching sentence found for preview.
    )}
  • ); })}
); } }); return null; // This component only provides the copilot action }; export default HallucinationChecker;