Spaces:
Running
Running
Download src/components/NodeError.tsx from mrfakename/flow: direct link, hf CLI and curl.
- Browser
- Download file 3.71 kB
-
https://huggingface.co/spaces/mrfakename/flow/resolve/main/src/components/NodeError.tsx
- Command line
-
hf download hf://spaces/mrfakename/flow/src/components/NodeError.tsx
-
curl -L -o NodeError.tsx https://huggingface.co/spaces/mrfakename/flow/resolve/main/src/components/NodeError.tsx
3.71 kB
| import { useCanvasStore } from "../store/useCanvasStore"; | |
| import { askCopilot } from "../store/useCopilotStore"; | |
| import { useAuthStore } from "../store/useAuthStore"; | |
| import { hubUrl, isUsable } from "../lib/hub"; | |
| import type { CanvasNodeData, NodeDef, SpaceEntry } from "../lib/types"; | |
| interface Action { | |
| label: string; | |
| run?: () => void; | |
| href?: string; | |
| } | |
| const BILLING = "https://huggingface.co/settings/billing"; | |
| /** The one tap that could fix a Space's problem: wake it, sign in, grant access, or go see it on the Hub. */ | |
| export function spaceAction(spaceId: string | null, entry: SpaceEntry | undefined, message: string): Action | null { | |
| const s = useCanvasStore.getState(); | |
| const auth = useAuthStore.getState(); | |
| const msg = message.toLowerCase(); | |
| const stage = entry?.summary.stage; | |
| if (/private|not found|sign in|sign-in|grant access/.test(msg)) { | |
| if (!auth.token()) return { label: "Sign in", run: () => void auth.login() }; | |
| if (!auth.hasScope("read-repos")) return { label: "Grant access", run: () => void auth.reauth() }; | |
| return spaceId ? { label: "Open on Hub", href: hubUrl(spaceId) } : null; | |
| } | |
| if (/401|403|unauthori[sz]ed|forbidden|gated/.test(msg)) { | |
| if (!auth.token()) return { label: "Sign in", run: () => void auth.login() }; | |
| return { label: "Usage & billing", href: BILLING }; | |
| } | |
| if (/quota|zerogpu|gpu.*(limit|exceed|exhaust)|(limit|exceed|exhaust).*gpu|too many requests|429/.test(msg)) return { label: "See usage", href: BILLING }; | |
| if (spaceId && (stage === "SLEEPING" || stage === "APP_STARTING" || stage === "BUILDING" || /asleep|sleep|starting up|not running|wak(e|ing)|did not wake/.test(msg))) { | |
| return { label: stage === "SLEEPING" || !stage ? "Wake it" : "Wait for it", run: () => void s.wakeSpace(spaceId) }; | |
| } | |
| if (spaceId && stage && !isUsable(stage) && stage !== "UNKNOWN") return { label: "Open on Hub", href: hubUrl(spaceId) }; | |
| if (spaceId && /crashed|paused|stopped|broken|owner/.test(msg)) return { label: "Open on Hub", href: hubUrl(spaceId) }; | |
| if (spaceId && (/not loaded|could not reach|network|cors|disconnected|closed the stream|result stream|timed out/.test(msg) || entry?.status === "error")) { | |
| return { label: "Retry", run: () => void s.refreshSpace(spaceId) }; | |
| } | |
| return null; | |
| } | |
| /** One tap that could fix the error, derived from the message and the Space's state. */ | |
| export function errorAction(data: CanvasNodeData, def: NodeDef): Action | null { | |
| const spaceId = def.space?.id ?? (def.type.startsWith("space:") ? def.type.slice(6).split("/").slice(0, 2).join("/") : null); | |
| const entry = spaceId ? useCanvasStore.getState().spaces[spaceId] : undefined; | |
| return spaceAction(spaceId, entry, data.error ?? ""); | |
| } | |
| /** The red error box under a node: the message, the best next action, and "Ask copilot why". */ | |
| export function NodeError({ data, def, className = "" }: { data: CanvasNodeData; def: NodeDef; className?: string }) { | |
| if (data.status !== "error" || !data.error) return null; | |
| const action = errorAction(data, def); | |
| return ( | |
| <div className={`node-error ${className}`}> | |
| {data.error} | |
| <div className="node-error__actions"> | |
| {action && | |
| (action.href ? ( | |
| <a className="node-error__act" href={action.href} target="_blank" rel="noreferrer"> | |
| {action.label} | |
| </a> | |
| ) : ( | |
| <button type="button" className="node-error__act" onClick={action.run}> | |
| {action.label} | |
| </button> | |
| ))} | |
| <button type="button" className="node-error__ask" onClick={() => askCopilot(data.title ?? def.title)}> | |
| Ask copilot why | |
| </button> | |
| </div> | |
| </div> | |
| ); | |
| } | |