|
import {
|
|
get_space_hardware,
|
|
hardware_types,
|
|
set_space_timeout
|
|
} from "../helpers/spaces";
|
|
import type { DuplicateOptions } from "../types";
|
|
import { Client } from "../client";
|
|
import { SPACE_METADATA_ERROR_MSG } from "../constants";
|
|
import {
|
|
get_cookie_header,
|
|
parse_and_set_cookies
|
|
} from "../helpers/init_helpers";
|
|
import { process_endpoint } from "../helpers/api_info";
|
|
|
|
export async function duplicate(
|
|
app_reference: string,
|
|
options: DuplicateOptions
|
|
): Promise<Client> {
|
|
const { hf_token, private: _private, hardware, timeout, auth } = options;
|
|
|
|
if (hardware && !hardware_types.includes(hardware)) {
|
|
throw new Error(
|
|
`Invalid hardware type provided. Valid types are: ${hardware_types
|
|
.map((v) => `"${v}"`)
|
|
.join(",")}.`
|
|
);
|
|
}
|
|
|
|
const { http_protocol, host } = await process_endpoint(
|
|
app_reference,
|
|
hf_token
|
|
);
|
|
|
|
let cookies: string[] | null = null;
|
|
|
|
if (auth) {
|
|
const cookie_header = await get_cookie_header(
|
|
http_protocol,
|
|
host,
|
|
auth,
|
|
fetch
|
|
);
|
|
|
|
if (cookie_header) cookies = parse_and_set_cookies(cookie_header);
|
|
}
|
|
|
|
const headers = {
|
|
Authorization: `Bearer ${hf_token}`,
|
|
"Content-Type": "application/json",
|
|
...(cookies ? { Cookie: cookies.join("; ") } : {})
|
|
};
|
|
|
|
const user = (
|
|
await (
|
|
await fetch(`https://huggingface.co/api/whoami-v2`, {
|
|
headers
|
|
})
|
|
).json()
|
|
).name;
|
|
|
|
const space_name = app_reference.split("/")[1];
|
|
const body: {
|
|
repository: string;
|
|
private?: boolean;
|
|
hardware?: string;
|
|
} = {
|
|
repository: `${user}/${space_name}`
|
|
};
|
|
|
|
if (_private) {
|
|
body.private = true;
|
|
}
|
|
|
|
let original_hardware;
|
|
|
|
try {
|
|
if (!hardware) {
|
|
original_hardware = await get_space_hardware(app_reference, hf_token);
|
|
}
|
|
} catch (e) {
|
|
throw Error(SPACE_METADATA_ERROR_MSG + (e as Error).message);
|
|
}
|
|
|
|
const requested_hardware = hardware || original_hardware || "cpu-basic";
|
|
|
|
body.hardware = requested_hardware;
|
|
|
|
try {
|
|
const response = await fetch(
|
|
`https://huggingface.co/api/spaces/${app_reference}/duplicate`,
|
|
{
|
|
method: "POST",
|
|
headers,
|
|
body: JSON.stringify(body)
|
|
}
|
|
);
|
|
|
|
if (response.status === 409) {
|
|
try {
|
|
const client = await Client.connect(`${user}/${space_name}`, options);
|
|
return client;
|
|
} catch (error) {
|
|
console.error("Failed to connect Client instance:", error);
|
|
throw error;
|
|
}
|
|
} else if (response.status !== 200) {
|
|
throw new Error(response.statusText);
|
|
}
|
|
|
|
const duplicated_space = await response.json();
|
|
|
|
await set_space_timeout(`${user}/${space_name}`, timeout || 300, hf_token);
|
|
|
|
return await Client.connect(
|
|
get_space_reference(duplicated_space.url),
|
|
options
|
|
);
|
|
} catch (e: any) {
|
|
throw new Error(e);
|
|
}
|
|
}
|
|
|
|
function get_space_reference(url: string): any {
|
|
const regex = /https:\/\/huggingface.co\/spaces\/([^/]+\/[^/]+)/;
|
|
const match = url.match(regex);
|
|
if (match) {
|
|
return match[1];
|
|
}
|
|
}
|
|
|