import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'; import { RestClient, type AiArtifact, type AiJobResult } from '@insignia/iios-kernel-client'; const AiContext = createContext(null); export function AiProvider({ serviceUrl, token, children, }: { serviceUrl: string; token: string; children: React.ReactNode; }): React.ReactElement { const client = useMemo(() => new RestClient({ serviceUrl, token }), [serviceUrl, token]); return {children}; } function useClient(): RestClient { const c = useContext(AiContext); if (!c) throw new Error('AI hooks must be used within '); return c; } /** Run an AI worker (proposal only). Returns the job + proposed artifact (or null on abstain/fail). */ export function useRunJob(): (interactionId: string, jobType: 'CLASSIFY' | 'SUMMARIZE' | 'EXTRACT') => Promise { const client = useClient(); return (interactionId, jobType) => client.runAiJob({ interactionId, jobType }); } /** List AI proposals + human accept/reject feedback. */ export function useAiProposals(opts?: { interactionId?: string; status?: string; pollMs?: number }): { artifacts: AiArtifact[]; refresh: () => Promise; accept: (id: string) => Promise; reject: (id: string) => Promise; } { const client = useClient(); const [artifacts, setArtifacts] = useState([]); const refresh = useCallback(async () => { try { setArtifacts(await client.listArtifacts({ interactionId: opts?.interactionId, status: opts?.status })); } catch { /* transient */ } }, [client, opts?.interactionId, opts?.status]); useEffect(() => { void refresh(); if (!opts?.pollMs) return; const t = setInterval(() => void refresh(), opts.pollMs); return () => clearInterval(t); }, [refresh, opts?.pollMs]); const accept = async (id: string) => { await client.acceptArtifact(id); await refresh(); }; const reject = async (id: string) => { await client.rejectArtifact(id); await refresh(); }; return { artifacts, refresh, accept, reject }; } /** Full artifact detail (claims + evidence + model run) for explainability. */ export function useArtifact(id: string | null): { artifact: AiArtifact | null; refresh: () => Promise } { const client = useClient(); const [artifact, setArtifact] = useState(null); const refresh = useCallback(async () => { if (!id) { setArtifact(null); return; } try { setArtifact(await client.getArtifact(id)); } catch { /* transient */ } }, [client, id]); useEffect(() => { void refresh(); }, [refresh]); return { artifact, refresh }; }