Spaces:
Sleeping
Sleeping
File size: 1,711 Bytes
9dfccd9 e646563 9dfccd9 e646563 9dfccd9 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | import { useState } from 'react'
import { apiFetch, ApiError } from '@/lib/http'
import { useUIStore } from '@/stores/uiStore'
interface Props {
/** Specific chunk IDs to process. When omitted, all pending chunks are processed. */
chunkIds?: string[]
teamId?: string
}
export function GraphIngestButton({ chunkIds, teamId = 'default' }: Props) {
const [loading, setLoading] = useState(false)
const addToast = useUIStore((s) => s.addToast)
const run = async () => {
setLoading(true)
try {
const body: Record<string, unknown> = { team_id: teamId }
if (chunkIds) body.chunk_ids = chunkIds
const res = await apiFetch('/graph/ingest', {
method: 'POST',
body: JSON.stringify(body),
})
const data = await res.json() as { ingested: number; total: number; failed: number }
addToast({
type: 'success',
message: data.failed > 0
? `Graph extraction: ${data.ingested}/${data.total} chunks ingested, ${data.failed} failed`
: `Ingested ${data.ingested} chunk${data.ingested === 1 ? '' : 's'} into knowledge graph`,
})
} catch (err) {
if (!(err instanceof ApiError)) {
addToast({ type: 'error', message: 'Graph extraction failed' })
}
} finally {
setLoading(false)
}
}
return (
<button
onClick={run}
disabled={loading}
className="flex items-center gap-2 rounded-lg bg-brand px-4 py-2 text-sm font-medium text-white hover:bg-brand-dark disabled:opacity-60"
>
{loading && <span className="animate-spin" aria-hidden>⟳</span>}
{loading ? 'Extracting entities…' : 'Run graph extraction'}
</button>
)
}
|