supermemory/apps/web/hooks/use-research-status.ts
MaheshtheDev e39ba92cb4 feat(brain): add /brain Slack-first onboarding entry (#1310)
New /brain route creates the org straight from signup and redirects into the Slack install, so onboarding has no domain-confirmation step. Returning from OAuth shows an Open Slack handoff instead of a toast.

Also models the terminal research error state: polling stops, the UI retries once, and the docked header no longer gates Continue on research finishing.
2026-07-21 21:19:54 +00:00

66 lines
1.6 KiB
TypeScript

"use client"
import { useQuery } from "@tanstack/react-query"
import { useAuth } from "@lib/auth-context"
const BACKEND =
process.env.NEXT_PUBLIC_BACKEND_URL ?? "https://api.supermemory.ai"
const POLL_INTERVAL_MS = 2_000
const MAX_POLLS = 150
export type ResearchStat = { label: string; value: string }
export type ResearchEvent = {
aspect: string
label: string
status: "in_progress" | "complete" | "error" | string
detail: string | null
stats: ResearchStat[]
highlights: string[]
sources: string[]
createdAt: number
}
export type ResearchState = {
status: "queued" | "running" | "done" | "error" | null
domain: string | null
findings: number
events: ResearchEvent[]
}
const EMPTY: ResearchState = {
status: null,
domain: null,
findings: 0,
events: [],
}
export function useResearchStatus(enabled = true) {
const { org } = useAuth()
const orgId = org?.id
const { data } = useQuery<ResearchState>({
queryKey: ["brain-research-status", orgId],
queryFn: async () => {
const res = await fetch(`${BACKEND}/brain/research/status`, {
credentials: "include",
headers: { "X-App-Source": "nova" },
})
if (!res.ok) return EMPTY
return (await res.json()) as ResearchState
},
enabled: Boolean(enabled && orgId),
refetchInterval: (query) => {
const status = query.state.data?.status
const polls = query.state.dataUpdateCount
// error is terminal too — keep polling only while it can still progress.
if (status === "done" || status === "error" || polls >= MAX_POLLS)
return false
return POLL_INTERVAL_MS
},
staleTime: 0,
})
return data ?? EMPTY
}