Spaces:
Running
Running
| import { | |
| RUNTIME_URL, | |
| SLEEPTIME_URL, | |
| SPACE_STATUS_ERROR_MSG | |
| } from "../constants"; | |
| import type { SpaceStatusCallback } from "../types"; | |
| export async function check_space_status( | |
| id: string, | |
| type: "subdomain" | "space_name", | |
| status_callback: SpaceStatusCallback | |
| ): Promise<void> { | |
| let endpoint = | |
| type === "subdomain" | |
| ? `https://huggingface.co/api/spaces/by-subdomain/${id}` | |
| : `https://huggingface.co/api/spaces/${id}`; | |
| let response; | |
| let _status; | |
| try { | |
| response = await fetch(endpoint); | |
| _status = response.status; | |
| if (_status !== 200) { | |
| throw new Error(); | |
| } | |
| response = await response.json(); | |
| } catch (e) { | |
| status_callback({ | |
| status: "error", | |
| load_status: "error", | |
| message: SPACE_STATUS_ERROR_MSG, | |
| detail: "NOT_FOUND" | |
| }); | |
| return; | |
| } | |
| if (!response || _status !== 200) return; | |
| const { | |
| runtime: { stage }, | |
| id: space_name | |
| } = response; | |
| switch (stage) { | |
| case "STOPPED": | |
| case "SLEEPING": | |
| status_callback({ | |
| status: "sleeping", | |
| load_status: "pending", | |
| message: "Space is asleep. Waking it up...", | |
| detail: stage | |
| }); | |
| setTimeout(() => { | |
| check_space_status(id, type, status_callback); | |
| }, 1000); // poll for status | |
| break; | |
| case "PAUSED": | |
| status_callback({ | |
| status: "paused", | |
| load_status: "error", | |
| message: | |
| "This space has been paused by the author. If you would like to try this demo, consider duplicating the space.", | |
| detail: stage, | |
| discussions_enabled: await discussions_enabled(space_name) | |
| }); | |
| break; | |
| case "RUNNING": | |
| case "RUNNING_BUILDING": | |
| status_callback({ | |
| status: "running", | |
| load_status: "complete", | |
| message: "", | |
| detail: stage | |
| }); | |
| break; | |
| case "BUILDING": | |
| status_callback({ | |
| status: "building", | |
| load_status: "pending", | |
| message: "Space is building...", | |
| detail: stage | |
| }); | |
| setTimeout(() => { | |
| check_space_status(id, type, status_callback); | |
| }, 1000); | |
| break; | |
| default: | |
| status_callback({ | |
| status: "space_error", | |
| load_status: "error", | |
| message: "This space is experiencing an issue.", | |
| detail: stage, | |
| discussions_enabled: await discussions_enabled(space_name) | |
| }); | |
| break; | |
| } | |
| } | |
| const RE_DISABLED_DISCUSSION = | |
| /^(?=[^]*\b[dD]iscussions{0,1}\b)(?=[^]*\b[dD]isabled\b)[^]*$/; | |
| export async function discussions_enabled(space_id: string): Promise<boolean> { | |
| try { | |
| const r = await fetch( | |
| `https://huggingface.co/api/spaces/${space_id}/discussions`, | |
| { | |
| method: "HEAD" | |
| } | |
| ); | |
| const error = r.headers.get("x-error-message"); | |
| if (!r.ok || (error && RE_DISABLED_DISCUSSION.test(error))) return false; | |
| return true; | |
| } catch (e) { | |
| return false; | |
| } | |
| } | |
| export async function get_space_hardware( | |
| space_id: string, | |
| hf_token?: `hf_${string}` | undefined | |
| ): Promise<(typeof hardware_types)[number]> { | |
| const headers: { Authorization?: string } = {}; | |
| if (hf_token) { | |
| headers.Authorization = `Bearer ${hf_token}`; | |
| } | |
| try { | |
| const res = await fetch( | |
| `https://huggingface.co/api/spaces/${space_id}/${RUNTIME_URL}`, | |
| { headers } | |
| ); | |
| if (res.status !== 200) | |
| throw new Error("Space hardware could not be obtained."); | |
| const { hardware } = await res.json(); | |
| return hardware.current; | |
| } catch (e: any) { | |
| throw new Error(e.message); | |
| } | |
| } | |
| export async function set_space_timeout( | |
| space_id: string, | |
| timeout: number, | |
| hf_token?: `hf_${string}` | |
| ): Promise<any> { | |
| const headers: { Authorization?: string } = {}; | |
| if (hf_token) { | |
| headers.Authorization = `Bearer ${hf_token}`; | |
| } | |
| const body: { | |
| seconds?: number; | |
| } = { | |
| seconds: timeout | |
| }; | |
| try { | |
| const res = await fetch( | |
| `https://huggingface.co/api/spaces/${space_id}/${SLEEPTIME_URL}`, | |
| { | |
| method: "POST", | |
| headers: { "Content-Type": "application/json", ...headers }, | |
| body: JSON.stringify(body) | |
| } | |
| ); | |
| if (res.status !== 200) { | |
| throw new Error( | |
| "Could not set sleep timeout on duplicated Space. Please visit *ADD HF LINK TO SETTINGS* to set a timeout manually to reduce billing charges." | |
| ); | |
| } | |
| const response = await res.json(); | |
| return response; | |
| } catch (e: any) { | |
| throw new Error(e.message); | |
| } | |
| } | |
| export const hardware_types = [ | |
| "cpu-basic", | |
| "cpu-upgrade", | |
| "cpu-xl", | |
| "t4-small", | |
| "t4-medium", | |
| "a10g-small", | |
| "a10g-large", | |
| "a10g-largex2", | |
| "a10g-largex4", | |
| "a100-large", | |
| "zero-a10g", | |
| "h100", | |
| "h100x8" | |
| ] as const; | |