supermemory/apps/web/hooks/use-brain-models.ts
sreedharsreeram 9824f0c9cd feat(web): configure Company Brain reasoning effort (#1307)
## Stack context

Stacks on #1306, which moves Company Brain settings into the revamped Configure page.

Backend contract and runtime support: supermemoryai/mono#2581. The UI safely hides any effort controls omitted by an older backend response.

## What changed

- Adds independent Low, Medium, High, and Extra high reasoning controls for Main, Triage, and Research.
- Saves model and reasoning edits together through the existing partial PATCH.
- Keeps controls visible but disabled for non-admin members.
- Explains that Extra high maps to High for Grok and GPT providers.

## Validation

- `bunx biome check apps/web/hooks/use-brain-models.ts apps/web/components/settings/company-brain-models.tsx`
- `bun run build` in `apps/web`
- `git diff --check`

The standalone web TypeScript command still reports pre-existing unrelated errors outside these files.

---
**Session Details**
- Session: [View Session](https://supermemory.us1.vorflux.com/agent-sessions/1c4f3ec7-a536-4105-bbe7-8b19e61f245f)
- Requested by: Sreeram Sreedhar (sreeram@supermemory.com)
- Address comments on this PR. Add `(aside)` to your comment to have me ignore it.
2026-07-18 19:12:45 +00:00

68 lines
2.1 KiB
TypeScript

import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
import { toast } from "sonner"
import { useAuth } from "@lib/auth-context"
const BACKEND =
process.env.NEXT_PUBLIC_BACKEND_URL ?? "https://api.supermemory.ai"
const BASE = `${BACKEND}/brain/models`
export type BrainModelRole = "main" | "triage" | "research"
export type BrainReasoningEffort = "low" | "medium" | "high" | "xhigh"
export type BrainReasoningKey = "mainEffort" | "triageEffort" | "researchEffort"
export type BrainModelConfig = Record<BrainModelRole, string> &
Partial<Record<BrainReasoningKey, BrainReasoningEffort>>
export type BrainModelsResponse = {
resolved: BrainModelConfig
defaults: BrainModelConfig
choices: Record<BrainModelRole, string[]> &
Partial<Record<BrainReasoningKey, BrainReasoningEffort[]>>
}
export function useBrainModels(enabled: boolean) {
const { org } = useAuth()
return useQuery({
queryKey: ["brain", "models", org?.id],
queryFn: async (): Promise<BrainModelsResponse> => {
const res = await fetch(`${BASE}/`, { credentials: "include" })
if (!res.ok) throw new Error("Failed to load models")
return res.json()
},
enabled,
staleTime: 60_000,
})
}
export function useUpdateBrainModels() {
const { org } = useAuth()
const queryClient = useQueryClient()
return useMutation({
mutationFn: async (patch: Partial<BrainModelConfig>) => {
const res = await fetch(`${BASE}/`, {
method: "PATCH",
credentials: "include",
headers: { "Content-Type": "application/json", "X-App-Source": "nova" },
body: JSON.stringify(patch),
})
if (res.status === 403)
throw new Error("Only admins can change brain models.")
if (!res.ok) {
const b = (await res.json().catch(() => ({}))) as {
message?: string
error?: string
}
throw new Error(b.message ?? b.error ?? "Failed to save models")
}
return res.json()
},
onSuccess: () => {
void queryClient.invalidateQueries({
queryKey: ["brain", "models", org?.id],
})
toast.success("Brain models saved")
},
onError: (err) =>
toast.error(err instanceof Error ? err.message : "Failed to save models"),
})
}