@gradio/client 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/LICENSE +201 -0
- package/README.md +323 -30
- package/dist/client.d.ts +35 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1016 -0
- package/dist/types.d.ts +85 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils.d.ts +21 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/wrapper-b7460963.js +3468 -0
- package/package.json +26 -3
- package/src/client.node-test.ts +172 -0
- package/src/client.ts +785 -151
- package/src/globals.d.ts +31 -0
- package/src/index.ts +2 -2
- package/src/types.ts +9 -4
- package/src/utils.ts +121 -11
- package/tsconfig.json +14 -0
- package/vite.config.js +23 -0
package/dist/index.js
ADDED
@@ -0,0 +1,1016 @@
|
|
1
|
+
import semiver from "semiver";
|
2
|
+
function determine_protocol(endpoint) {
|
3
|
+
if (endpoint.startsWith("http")) {
|
4
|
+
const { protocol, host } = new URL(endpoint);
|
5
|
+
if (host.endsWith("hf.space")) {
|
6
|
+
return {
|
7
|
+
ws_protocol: "wss",
|
8
|
+
host,
|
9
|
+
http_protocol: protocol
|
10
|
+
};
|
11
|
+
} else {
|
12
|
+
return {
|
13
|
+
ws_protocol: protocol === "https:" ? "wss" : "ws",
|
14
|
+
http_protocol: protocol,
|
15
|
+
host
|
16
|
+
};
|
17
|
+
}
|
18
|
+
}
|
19
|
+
return {
|
20
|
+
ws_protocol: "wss",
|
21
|
+
http_protocol: "https:",
|
22
|
+
host: endpoint
|
23
|
+
};
|
24
|
+
}
|
25
|
+
const RE_SPACE_NAME = /^[^\/]*\/[^\/]*$/;
|
26
|
+
const RE_SPACE_DOMAIN = /.*hf\.space\/{0,1}$/;
|
27
|
+
async function process_endpoint(app_reference, token) {
|
28
|
+
const headers = {};
|
29
|
+
if (token) {
|
30
|
+
headers.Authorization = `Bearer ${token}`;
|
31
|
+
}
|
32
|
+
const _app_reference = app_reference.trim();
|
33
|
+
if (RE_SPACE_NAME.test(_app_reference)) {
|
34
|
+
try {
|
35
|
+
const res = await fetch(
|
36
|
+
`https://huggingface.co/api/spaces/${_app_reference}/host`,
|
37
|
+
{ headers }
|
38
|
+
);
|
39
|
+
if (res.status !== 200)
|
40
|
+
throw new Error("Space metadata could not be loaded.");
|
41
|
+
const _host = (await res.json()).host;
|
42
|
+
return {
|
43
|
+
space_id: app_reference,
|
44
|
+
...determine_protocol(_host)
|
45
|
+
};
|
46
|
+
} catch (e) {
|
47
|
+
throw new Error("Space metadata could not be loaded." + e.message);
|
48
|
+
}
|
49
|
+
}
|
50
|
+
if (RE_SPACE_DOMAIN.test(_app_reference)) {
|
51
|
+
const { ws_protocol, http_protocol, host } = determine_protocol(_app_reference);
|
52
|
+
return {
|
53
|
+
space_id: host.replace(".hf.space", ""),
|
54
|
+
ws_protocol,
|
55
|
+
http_protocol,
|
56
|
+
host
|
57
|
+
};
|
58
|
+
}
|
59
|
+
return {
|
60
|
+
space_id: false,
|
61
|
+
...determine_protocol(_app_reference)
|
62
|
+
};
|
63
|
+
}
|
64
|
+
function map_names_to_ids(fns) {
|
65
|
+
let apis = {};
|
66
|
+
fns.forEach(({ api_name }, i) => {
|
67
|
+
if (api_name)
|
68
|
+
apis[api_name] = i;
|
69
|
+
});
|
70
|
+
return apis;
|
71
|
+
}
|
72
|
+
const RE_DISABLED_DISCUSSION = /^(?=[^]*\b[dD]iscussions{0,1}\b)(?=[^]*\b[dD]isabled\b)[^]*$/;
|
73
|
+
async function discussions_enabled(space_id) {
|
74
|
+
try {
|
75
|
+
const r = await fetch(
|
76
|
+
`https://huggingface.co/api/spaces/${space_id}/discussions`,
|
77
|
+
{
|
78
|
+
method: "HEAD"
|
79
|
+
}
|
80
|
+
);
|
81
|
+
const error = r.headers.get("x-error-message");
|
82
|
+
if (error && RE_DISABLED_DISCUSSION.test(error))
|
83
|
+
return false;
|
84
|
+
else
|
85
|
+
return true;
|
86
|
+
} catch (e) {
|
87
|
+
return false;
|
88
|
+
}
|
89
|
+
}
|
90
|
+
async function get_space_hardware(space_id, token) {
|
91
|
+
const headers = {};
|
92
|
+
if (token) {
|
93
|
+
headers.Authorization = `Bearer ${token}`;
|
94
|
+
}
|
95
|
+
try {
|
96
|
+
const res = await fetch(
|
97
|
+
`https://huggingface.co/api/spaces/${space_id}/runtime`,
|
98
|
+
{ headers }
|
99
|
+
);
|
100
|
+
if (res.status !== 200)
|
101
|
+
throw new Error("Space hardware could not be obtained.");
|
102
|
+
const { hardware } = await res.json();
|
103
|
+
return hardware;
|
104
|
+
} catch (e) {
|
105
|
+
throw new Error(e.message);
|
106
|
+
}
|
107
|
+
}
|
108
|
+
async function set_space_hardware(space_id, new_hardware, token) {
|
109
|
+
const headers = {};
|
110
|
+
if (token) {
|
111
|
+
headers.Authorization = `Bearer ${token}`;
|
112
|
+
}
|
113
|
+
try {
|
114
|
+
const res = await fetch(
|
115
|
+
`https://huggingface.co/api/spaces/${space_id}/hardware`,
|
116
|
+
{ headers, body: JSON.stringify(new_hardware) }
|
117
|
+
);
|
118
|
+
if (res.status !== 200)
|
119
|
+
throw new Error(
|
120
|
+
"Space hardware could not be set. Please ensure the space hardware provided is valid and that a Hugging Face token is passed in."
|
121
|
+
);
|
122
|
+
const { hardware } = await res.json();
|
123
|
+
return hardware;
|
124
|
+
} catch (e) {
|
125
|
+
throw new Error(e.message);
|
126
|
+
}
|
127
|
+
}
|
128
|
+
async function set_space_timeout(space_id, timeout, token) {
|
129
|
+
const headers = {};
|
130
|
+
if (token) {
|
131
|
+
headers.Authorization = `Bearer ${token}`;
|
132
|
+
}
|
133
|
+
try {
|
134
|
+
const res = await fetch(
|
135
|
+
`https://huggingface.co/api/spaces/${space_id}/hardware`,
|
136
|
+
{ headers, body: JSON.stringify({ seconds: timeout }) }
|
137
|
+
);
|
138
|
+
if (res.status !== 200)
|
139
|
+
throw new Error(
|
140
|
+
"Space hardware could not be set. Please ensure the space hardware provided is valid and that a Hugging Face token is passed in."
|
141
|
+
);
|
142
|
+
const { hardware } = await res.json();
|
143
|
+
return hardware;
|
144
|
+
} catch (e) {
|
145
|
+
throw new Error(e.message);
|
146
|
+
}
|
147
|
+
}
|
148
|
+
const hardware_types = [
|
149
|
+
"cpu-basic",
|
150
|
+
"cpu-upgrade",
|
151
|
+
"t4-small",
|
152
|
+
"t4-medium",
|
153
|
+
"a10g-small",
|
154
|
+
"a10g-large",
|
155
|
+
"a100-large"
|
156
|
+
];
|
157
|
+
const QUEUE_FULL_MSG = "This application is too busy. Keep trying!";
|
158
|
+
const BROKEN_CONNECTION_MSG = "Connection errored out.";
|
159
|
+
async function post_data(url, body, token) {
|
160
|
+
const headers = { "Content-Type": "application/json" };
|
161
|
+
if (token) {
|
162
|
+
headers.Authorization = `Bearer ${token}`;
|
163
|
+
}
|
164
|
+
try {
|
165
|
+
var response = await fetch(url, {
|
166
|
+
method: "POST",
|
167
|
+
body: JSON.stringify(body),
|
168
|
+
headers
|
169
|
+
});
|
170
|
+
} catch (e) {
|
171
|
+
return [{ error: BROKEN_CONNECTION_MSG }, 500];
|
172
|
+
}
|
173
|
+
const output = await response.json();
|
174
|
+
return [output, response.status];
|
175
|
+
}
|
176
|
+
let NodeBlob;
|
177
|
+
async function upload_files(root, files, token) {
|
178
|
+
const headers = {};
|
179
|
+
if (token) {
|
180
|
+
headers.Authorization = `Bearer ${token}`;
|
181
|
+
}
|
182
|
+
const formData = new FormData();
|
183
|
+
files.forEach((file) => {
|
184
|
+
formData.append("files", file);
|
185
|
+
});
|
186
|
+
try {
|
187
|
+
var response = await fetch(`${root}/upload`, {
|
188
|
+
method: "POST",
|
189
|
+
body: formData,
|
190
|
+
headers
|
191
|
+
});
|
192
|
+
} catch (e) {
|
193
|
+
return { error: BROKEN_CONNECTION_MSG };
|
194
|
+
}
|
195
|
+
const output = await response.json();
|
196
|
+
return { files: output };
|
197
|
+
}
|
198
|
+
async function duplicate(app_reference, options) {
|
199
|
+
const { hf_token, private: _private, hardware, timeout } = options;
|
200
|
+
if (hardware && !hardware_types.includes(hardware)) {
|
201
|
+
throw new Error(
|
202
|
+
`Invalid hardware type provided. Valid types are: ${hardware_types.map((v) => `"${v}"`).join(",")}.`
|
203
|
+
);
|
204
|
+
}
|
205
|
+
const headers = {
|
206
|
+
Authorization: `Bearer ${hf_token}`
|
207
|
+
};
|
208
|
+
const user = (await (await fetch(`https://huggingface.co/api/whoami-v2`, {
|
209
|
+
headers
|
210
|
+
})).json()).name;
|
211
|
+
const space_name = app_reference.split("/")[1];
|
212
|
+
const body = {
|
213
|
+
repository: `${user}/${space_name}`
|
214
|
+
};
|
215
|
+
if (_private) {
|
216
|
+
body.private = true;
|
217
|
+
}
|
218
|
+
try {
|
219
|
+
const response = await fetch(
|
220
|
+
`https://huggingface.co/api/spaces/${app_reference}/duplicate`,
|
221
|
+
{
|
222
|
+
method: "POST",
|
223
|
+
headers: { "Content-Type": "application/json", ...headers },
|
224
|
+
body: JSON.stringify(body)
|
225
|
+
}
|
226
|
+
);
|
227
|
+
if (response.status === 409) {
|
228
|
+
return client(`${user}/${space_name}`, options);
|
229
|
+
} else {
|
230
|
+
const duplicated_space = await response.json();
|
231
|
+
let original_hardware;
|
232
|
+
if (!hardware) {
|
233
|
+
original_hardware = await get_space_hardware(app_reference, hf_token);
|
234
|
+
}
|
235
|
+
const requested_hardware = hardware || original_hardware || "cpu-basic";
|
236
|
+
await set_space_hardware(
|
237
|
+
`${user}/${space_name}`,
|
238
|
+
requested_hardware,
|
239
|
+
hf_token
|
240
|
+
);
|
241
|
+
await set_space_timeout(
|
242
|
+
`${user}/${space_name}`,
|
243
|
+
timeout || 300,
|
244
|
+
hf_token
|
245
|
+
);
|
246
|
+
return client(duplicated_space.url, options);
|
247
|
+
}
|
248
|
+
} catch (e) {
|
249
|
+
throw new Error(e);
|
250
|
+
}
|
251
|
+
}
|
252
|
+
async function client(app_reference, options = {}) {
|
253
|
+
return new Promise(async (res) => {
|
254
|
+
const { status_callback, hf_token } = options;
|
255
|
+
const return_obj = {
|
256
|
+
predict,
|
257
|
+
submit,
|
258
|
+
view_api
|
259
|
+
// duplicate
|
260
|
+
};
|
261
|
+
if (typeof window === "undefined" || !("WebSocket" in window)) {
|
262
|
+
const ws = await import("./wrapper-b7460963.js");
|
263
|
+
NodeBlob = (await import("node:buffer")).Blob;
|
264
|
+
global.WebSocket = ws.WebSocket;
|
265
|
+
}
|
266
|
+
const { ws_protocol, http_protocol, host, space_id } = await process_endpoint(app_reference, hf_token);
|
267
|
+
const session_hash = Math.random().toString(36).substring(2);
|
268
|
+
const last_status = {};
|
269
|
+
let config;
|
270
|
+
let api_map = {};
|
271
|
+
const listener_map = {};
|
272
|
+
let jwt = false;
|
273
|
+
if (hf_token && space_id) {
|
274
|
+
jwt = await get_jwt(space_id, hf_token);
|
275
|
+
}
|
276
|
+
async function config_success(_config) {
|
277
|
+
config = _config;
|
278
|
+
api_map = map_names_to_ids((_config == null ? void 0 : _config.dependencies) || []);
|
279
|
+
try {
|
280
|
+
api = await view_api(config);
|
281
|
+
} catch (e) {
|
282
|
+
console.error(`Could not get api details: ${e.message}`);
|
283
|
+
}
|
284
|
+
return {
|
285
|
+
config,
|
286
|
+
...return_obj
|
287
|
+
};
|
288
|
+
}
|
289
|
+
let api;
|
290
|
+
async function handle_space_sucess(status) {
|
291
|
+
if (status_callback)
|
292
|
+
status_callback(status);
|
293
|
+
if (status.status === "running")
|
294
|
+
try {
|
295
|
+
config = await resolve_config(`${http_protocol}//${host}`, hf_token);
|
296
|
+
const _config = await config_success(config);
|
297
|
+
res(_config);
|
298
|
+
} catch (e) {
|
299
|
+
if (status_callback) {
|
300
|
+
status_callback({
|
301
|
+
status: "error",
|
302
|
+
message: "Could not load this space.",
|
303
|
+
load_status: "error",
|
304
|
+
detail: "NOT_FOUND"
|
305
|
+
});
|
306
|
+
}
|
307
|
+
}
|
308
|
+
}
|
309
|
+
try {
|
310
|
+
console.log(`${http_protocol}//${host}`);
|
311
|
+
config = await resolve_config(`${http_protocol}//${host}`, hf_token);
|
312
|
+
console.log(config);
|
313
|
+
const _config = await config_success(config);
|
314
|
+
res(_config);
|
315
|
+
} catch (e) {
|
316
|
+
console.log(space_id, e);
|
317
|
+
if (space_id) {
|
318
|
+
check_space_status(
|
319
|
+
space_id,
|
320
|
+
RE_SPACE_NAME.test(space_id) ? "space_name" : "subdomain",
|
321
|
+
handle_space_sucess
|
322
|
+
);
|
323
|
+
} else {
|
324
|
+
if (status_callback)
|
325
|
+
status_callback({
|
326
|
+
status: "error",
|
327
|
+
message: "Could not load this space.",
|
328
|
+
load_status: "error",
|
329
|
+
detail: "NOT_FOUND"
|
330
|
+
});
|
331
|
+
}
|
332
|
+
}
|
333
|
+
function predict(endpoint, data, event_data) {
|
334
|
+
let data_returned = false;
|
335
|
+
let status_complete = false;
|
336
|
+
return new Promise((res2, rej) => {
|
337
|
+
const app = submit(endpoint, data, event_data);
|
338
|
+
app.on("data", (d) => {
|
339
|
+
data_returned = true;
|
340
|
+
if (status_complete) {
|
341
|
+
app.destroy();
|
342
|
+
}
|
343
|
+
res2(d);
|
344
|
+
}).on("status", (status) => {
|
345
|
+
if (status.stage === "error")
|
346
|
+
rej(status);
|
347
|
+
if (status.stage === "complete" && data_returned) {
|
348
|
+
app.destroy();
|
349
|
+
}
|
350
|
+
if (status.stage === "complete") {
|
351
|
+
status_complete = true;
|
352
|
+
}
|
353
|
+
});
|
354
|
+
});
|
355
|
+
}
|
356
|
+
function submit(endpoint, data, event_data) {
|
357
|
+
let fn_index;
|
358
|
+
let api_info;
|
359
|
+
if (typeof endpoint === "number") {
|
360
|
+
fn_index = endpoint;
|
361
|
+
api_info = api.unnamed_endpoints[fn_index];
|
362
|
+
} else {
|
363
|
+
const trimmed_endpoint = endpoint.replace(/^\//, "");
|
364
|
+
fn_index = api_map[trimmed_endpoint];
|
365
|
+
api_info = api.named_endpoints[endpoint.trim()];
|
366
|
+
}
|
367
|
+
if (typeof fn_index !== "number") {
|
368
|
+
throw new Error(
|
369
|
+
"There is no endpoint matching that name of fn_index matching that number."
|
370
|
+
);
|
371
|
+
}
|
372
|
+
let websocket;
|
373
|
+
const _endpoint = typeof endpoint === "number" ? "/predict" : endpoint;
|
374
|
+
let payload;
|
375
|
+
handle_blob(
|
376
|
+
`${http_protocol}//${host + config.path}`,
|
377
|
+
data,
|
378
|
+
api_info,
|
379
|
+
hf_token
|
380
|
+
).then((_payload) => {
|
381
|
+
payload = { data: _payload || [], event_data, fn_index };
|
382
|
+
if (skip_queue(fn_index, config)) {
|
383
|
+
fire_event({
|
384
|
+
type: "status",
|
385
|
+
endpoint: _endpoint,
|
386
|
+
stage: "pending",
|
387
|
+
queue: false,
|
388
|
+
fn_index,
|
389
|
+
time: /* @__PURE__ */ new Date()
|
390
|
+
});
|
391
|
+
post_data(
|
392
|
+
`${http_protocol}//${host + config.path}/run${_endpoint.startsWith("/") ? _endpoint : `/${_endpoint}`}`,
|
393
|
+
{
|
394
|
+
...payload,
|
395
|
+
session_hash
|
396
|
+
},
|
397
|
+
hf_token
|
398
|
+
).then(([output, status_code]) => {
|
399
|
+
if (status_code == 200) {
|
400
|
+
fire_event({
|
401
|
+
type: "status",
|
402
|
+
endpoint: _endpoint,
|
403
|
+
fn_index,
|
404
|
+
stage: "complete",
|
405
|
+
eta: output.average_duration,
|
406
|
+
queue: false,
|
407
|
+
time: /* @__PURE__ */ new Date()
|
408
|
+
});
|
409
|
+
fire_event({
|
410
|
+
type: "data",
|
411
|
+
endpoint: _endpoint,
|
412
|
+
fn_index,
|
413
|
+
data: output.data,
|
414
|
+
time: /* @__PURE__ */ new Date()
|
415
|
+
});
|
416
|
+
} else {
|
417
|
+
fire_event({
|
418
|
+
type: "status",
|
419
|
+
stage: "error",
|
420
|
+
endpoint: _endpoint,
|
421
|
+
fn_index,
|
422
|
+
message: output.error,
|
423
|
+
queue: false,
|
424
|
+
time: /* @__PURE__ */ new Date()
|
425
|
+
});
|
426
|
+
}
|
427
|
+
}).catch((e) => {
|
428
|
+
fire_event({
|
429
|
+
type: "status",
|
430
|
+
stage: "error",
|
431
|
+
message: e.message,
|
432
|
+
endpoint: _endpoint,
|
433
|
+
fn_index,
|
434
|
+
queue: false,
|
435
|
+
time: /* @__PURE__ */ new Date()
|
436
|
+
});
|
437
|
+
});
|
438
|
+
} else {
|
439
|
+
fire_event({
|
440
|
+
type: "status",
|
441
|
+
stage: "pending",
|
442
|
+
queue: true,
|
443
|
+
endpoint: _endpoint,
|
444
|
+
fn_index,
|
445
|
+
time: /* @__PURE__ */ new Date()
|
446
|
+
});
|
447
|
+
let url = new URL(`${ws_protocol}://${host}${config.path}
|
448
|
+
/queue/join`);
|
449
|
+
if (jwt) {
|
450
|
+
url.searchParams.set("__sign", jwt);
|
451
|
+
}
|
452
|
+
websocket = new WebSocket(url);
|
453
|
+
websocket.onclose = (evt) => {
|
454
|
+
if (!evt.wasClean) {
|
455
|
+
fire_event({
|
456
|
+
type: "status",
|
457
|
+
stage: "error",
|
458
|
+
message: BROKEN_CONNECTION_MSG,
|
459
|
+
queue: true,
|
460
|
+
endpoint: _endpoint,
|
461
|
+
fn_index,
|
462
|
+
time: /* @__PURE__ */ new Date()
|
463
|
+
});
|
464
|
+
}
|
465
|
+
};
|
466
|
+
websocket.onmessage = function(event) {
|
467
|
+
const _data = JSON.parse(event.data);
|
468
|
+
const { type, status, data: data2 } = handle_message(
|
469
|
+
_data,
|
470
|
+
last_status[fn_index]
|
471
|
+
);
|
472
|
+
if (type === "update" && status) {
|
473
|
+
fire_event({
|
474
|
+
type: "status",
|
475
|
+
endpoint: _endpoint,
|
476
|
+
fn_index,
|
477
|
+
time: /* @__PURE__ */ new Date(),
|
478
|
+
...status
|
479
|
+
});
|
480
|
+
if (status.stage === "error") {
|
481
|
+
websocket.close();
|
482
|
+
}
|
483
|
+
} else if (type === "hash") {
|
484
|
+
websocket.send(JSON.stringify({ fn_index, session_hash }));
|
485
|
+
return;
|
486
|
+
} else if (type === "data") {
|
487
|
+
websocket.send(JSON.stringify({ ...payload, session_hash }));
|
488
|
+
} else if (type === "complete") {
|
489
|
+
fire_event({
|
490
|
+
type: "status",
|
491
|
+
time: /* @__PURE__ */ new Date(),
|
492
|
+
...status,
|
493
|
+
stage: status == null ? void 0 : status.stage,
|
494
|
+
queue: true,
|
495
|
+
endpoint: _endpoint,
|
496
|
+
fn_index
|
497
|
+
});
|
498
|
+
websocket.close();
|
499
|
+
} else if (type === "generating") {
|
500
|
+
fire_event({
|
501
|
+
type: "status",
|
502
|
+
time: /* @__PURE__ */ new Date(),
|
503
|
+
...status,
|
504
|
+
stage: status == null ? void 0 : status.stage,
|
505
|
+
queue: true,
|
506
|
+
endpoint: _endpoint,
|
507
|
+
fn_index
|
508
|
+
});
|
509
|
+
}
|
510
|
+
if (data2) {
|
511
|
+
fire_event({
|
512
|
+
type: "data",
|
513
|
+
time: /* @__PURE__ */ new Date(),
|
514
|
+
data: data2.data,
|
515
|
+
endpoint: _endpoint,
|
516
|
+
fn_index
|
517
|
+
});
|
518
|
+
}
|
519
|
+
};
|
520
|
+
if (semiver(config.version || "2.0.0", "3.6") < 0) {
|
521
|
+
addEventListener(
|
522
|
+
"open",
|
523
|
+
() => websocket.send(JSON.stringify({ hash: session_hash }))
|
524
|
+
);
|
525
|
+
}
|
526
|
+
}
|
527
|
+
});
|
528
|
+
function fire_event(event) {
|
529
|
+
const narrowed_listener_map = listener_map;
|
530
|
+
let listeners = narrowed_listener_map[event.type] || [];
|
531
|
+
listeners == null ? void 0 : listeners.forEach((l) => l(event));
|
532
|
+
}
|
533
|
+
function on(eventType, listener) {
|
534
|
+
const narrowed_listener_map = listener_map;
|
535
|
+
let listeners = narrowed_listener_map[eventType] || [];
|
536
|
+
narrowed_listener_map[eventType] = listeners;
|
537
|
+
listeners == null ? void 0 : listeners.push(listener);
|
538
|
+
return { on, off, cancel, destroy };
|
539
|
+
}
|
540
|
+
function off(eventType, listener) {
|
541
|
+
const narrowed_listener_map = listener_map;
|
542
|
+
let listeners = narrowed_listener_map[eventType] || [];
|
543
|
+
listeners = listeners == null ? void 0 : listeners.filter((l) => l !== listener);
|
544
|
+
narrowed_listener_map[eventType] = listeners;
|
545
|
+
return { on, off, cancel, destroy };
|
546
|
+
}
|
547
|
+
async function cancel() {
|
548
|
+
fire_event({
|
549
|
+
type: "status",
|
550
|
+
endpoint: _endpoint,
|
551
|
+
fn_index,
|
552
|
+
stage: "complete",
|
553
|
+
queue: false,
|
554
|
+
time: /* @__PURE__ */ new Date()
|
555
|
+
});
|
556
|
+
try {
|
557
|
+
await fetch(`${http_protocol}//${host + config.path}/reset`, {
|
558
|
+
method: "POST",
|
559
|
+
body: JSON.stringify(session_hash)
|
560
|
+
});
|
561
|
+
} catch (e) {
|
562
|
+
console.warn(
|
563
|
+
"The `/reset` endpoint could not be called. Subsequent endpoint results may be unreliable."
|
564
|
+
);
|
565
|
+
}
|
566
|
+
if (websocket && websocket.readyState === 0) {
|
567
|
+
websocket.addEventListener("open", () => {
|
568
|
+
websocket.close();
|
569
|
+
});
|
570
|
+
} else {
|
571
|
+
websocket.close();
|
572
|
+
}
|
573
|
+
destroy();
|
574
|
+
}
|
575
|
+
function destroy() {
|
576
|
+
for (const event_type in listener_map) {
|
577
|
+
listener_map[event_type].forEach((fn) => {
|
578
|
+
off(event_type, fn);
|
579
|
+
});
|
580
|
+
}
|
581
|
+
}
|
582
|
+
return {
|
583
|
+
on,
|
584
|
+
off,
|
585
|
+
cancel,
|
586
|
+
destroy
|
587
|
+
};
|
588
|
+
}
|
589
|
+
async function view_api(config2) {
|
590
|
+
if (api)
|
591
|
+
return api;
|
592
|
+
const headers = { "Content-Type": "application/json" };
|
593
|
+
if (hf_token) {
|
594
|
+
headers.Authorization = `Bearer ${hf_token}`;
|
595
|
+
}
|
596
|
+
try {
|
597
|
+
let response;
|
598
|
+
if (semiver(config2.version || "2.0.0", "3.30") < 0) {
|
599
|
+
response = await fetch(
|
600
|
+
"https://gradio-space-api-fetcher-v2.hf.space/api",
|
601
|
+
{
|
602
|
+
method: "POST",
|
603
|
+
body: JSON.stringify({
|
604
|
+
serialize: false,
|
605
|
+
config: JSON.stringify(config2)
|
606
|
+
}),
|
607
|
+
headers
|
608
|
+
}
|
609
|
+
);
|
610
|
+
} else {
|
611
|
+
response = await fetch(`${http_protocol}//${host}/info`, {
|
612
|
+
headers
|
613
|
+
});
|
614
|
+
}
|
615
|
+
let api_info = await response.json();
|
616
|
+
if ("api" in api_info) {
|
617
|
+
api_info = api_info.api;
|
618
|
+
}
|
619
|
+
if (api_info.named_endpoints["/predict"] && !api_info.unnamed_endpoints["0"]) {
|
620
|
+
api_info.unnamed_endpoints[0] = api_info.named_endpoints["/predict"];
|
621
|
+
}
|
622
|
+
const x = transform_api_info(api_info, config2, api_map);
|
623
|
+
return x;
|
624
|
+
} catch (e) {
|
625
|
+
return [{ error: BROKEN_CONNECTION_MSG }, 500];
|
626
|
+
}
|
627
|
+
}
|
628
|
+
});
|
629
|
+
}
|
630
|
+
function get_type(type, component, serializer, signature_type) {
|
631
|
+
switch (type.type) {
|
632
|
+
case "string":
|
633
|
+
return "string";
|
634
|
+
case "boolean":
|
635
|
+
return "boolean";
|
636
|
+
case "number":
|
637
|
+
return "number";
|
638
|
+
}
|
639
|
+
if (serializer === "JSONSerializable" || serializer === "StringSerializable") {
|
640
|
+
return "any";
|
641
|
+
} else if (serializer === "ListStringSerializable") {
|
642
|
+
return "string[]";
|
643
|
+
} else if (component === "Image") {
|
644
|
+
return signature_type === "parameter" ? "Blob | File | Buffer" : "string";
|
645
|
+
} else if (serializer === "FileSerializable") {
|
646
|
+
if ((type == null ? void 0 : type.type) === "array") {
|
647
|
+
return signature_type === "parameter" ? "(Blob | File | Buffer)[]" : `{ name: string; data: string; size?: number; is_file?: boolean; orig_name?: string}[]`;
|
648
|
+
} else {
|
649
|
+
return signature_type === "parameter" ? "Blob | File | Buffer" : `{ name: string; data: string; size?: number; is_file?: boolean; orig_name?: string}`;
|
650
|
+
}
|
651
|
+
} else if (serializer === "GallerySerializable") {
|
652
|
+
return signature_type === "parameter" ? "[(Blob | File | Buffer), (string | null)][]" : `[{ name: string; data: string; size?: number; is_file?: boolean; orig_name?: string}, (string | null))][]`;
|
653
|
+
}
|
654
|
+
}
|
655
|
+
function get_description(type, serializer) {
|
656
|
+
if (serializer === "GallerySerializable") {
|
657
|
+
return "array of [file, label] tuples";
|
658
|
+
} else if (serializer === "ListStringSerializable") {
|
659
|
+
return "array of strings";
|
660
|
+
} else if (serializer === "FileSerializable") {
|
661
|
+
return "array of files or single file";
|
662
|
+
} else {
|
663
|
+
return type.description;
|
664
|
+
}
|
665
|
+
}
|
666
|
+
function transform_api_info(api_info, config, api_map) {
|
667
|
+
const new_data = {
|
668
|
+
named_endpoints: {},
|
669
|
+
unnamed_endpoints: {}
|
670
|
+
};
|
671
|
+
for (const key in api_info) {
|
672
|
+
const cat = api_info[key];
|
673
|
+
for (const endpoint in cat) {
|
674
|
+
const dep_index = config.dependencies[endpoint] ? endpoint : api_map[endpoint.replace("/", "")];
|
675
|
+
const info = cat[endpoint];
|
676
|
+
new_data[key][endpoint] = {};
|
677
|
+
new_data[key][endpoint].parameters = {};
|
678
|
+
new_data[key][endpoint].returns = {};
|
679
|
+
new_data[key][endpoint].type = config.dependencies[dep_index].types;
|
680
|
+
new_data[key][endpoint].parameters = info.parameters.map(
|
681
|
+
({ label, component, type, serializer }) => ({
|
682
|
+
label,
|
683
|
+
component,
|
684
|
+
type: get_type(type, component, serializer, "parameter"),
|
685
|
+
description: get_description(type, serializer)
|
686
|
+
})
|
687
|
+
);
|
688
|
+
new_data[key][endpoint].returns = info.returns.map(
|
689
|
+
({ label, component, type, serializer }) => ({
|
690
|
+
label,
|
691
|
+
component,
|
692
|
+
type: get_type(type, component, serializer, "return"),
|
693
|
+
description: get_description(type, serializer)
|
694
|
+
})
|
695
|
+
);
|
696
|
+
}
|
697
|
+
}
|
698
|
+
return new_data;
|
699
|
+
}
|
700
|
+
async function get_jwt(space, token) {
|
701
|
+
try {
|
702
|
+
const r = await fetch(`https://huggingface.co/api/spaces/${space}/jwt`, {
|
703
|
+
headers: {
|
704
|
+
Authorization: `Bearer ${token}`
|
705
|
+
}
|
706
|
+
});
|
707
|
+
const jwt = (await r.json()).token;
|
708
|
+
return jwt || false;
|
709
|
+
} catch (e) {
|
710
|
+
console.error(e);
|
711
|
+
return false;
|
712
|
+
}
|
713
|
+
}
|
714
|
+
async function handle_blob(endpoint, data, api_info, token) {
|
715
|
+
const blob_refs = await walk_and_store_blobs(
|
716
|
+
data,
|
717
|
+
void 0,
|
718
|
+
[],
|
719
|
+
true,
|
720
|
+
api_info
|
721
|
+
);
|
722
|
+
return new Promise((res) => {
|
723
|
+
Promise.all(
|
724
|
+
blob_refs.map(async ({ path, blob, data: data2, type }) => {
|
725
|
+
if (blob) {
|
726
|
+
const file_url = (await upload_files(endpoint, [blob], token)).files[0];
|
727
|
+
return { path, file_url, type };
|
728
|
+
} else {
|
729
|
+
return { path, base64: data2, type };
|
730
|
+
}
|
731
|
+
})
|
732
|
+
).then((r) => {
|
733
|
+
r.forEach(({ path, file_url, base64, type }) => {
|
734
|
+
if (base64) {
|
735
|
+
update_object(data, base64, path);
|
736
|
+
} else if (type === "Gallery") {
|
737
|
+
update_object(data, file_url, path);
|
738
|
+
} else if (file_url) {
|
739
|
+
const o = {
|
740
|
+
is_file: true,
|
741
|
+
name: `${file_url}`,
|
742
|
+
data: null
|
743
|
+
// orig_name: "file.csv"
|
744
|
+
};
|
745
|
+
update_object(data, o, path);
|
746
|
+
}
|
747
|
+
});
|
748
|
+
res(data);
|
749
|
+
}).catch(console.log);
|
750
|
+
});
|
751
|
+
}
|
752
|
+
function update_object(object, newValue, stack) {
|
753
|
+
while (stack.length > 1) {
|
754
|
+
object = object[stack.shift()];
|
755
|
+
}
|
756
|
+
object[stack.shift()] = newValue;
|
757
|
+
}
|
758
|
+
async function walk_and_store_blobs(param, type = void 0, path = [], root = false, api_info = void 0) {
|
759
|
+
if (Array.isArray(param)) {
|
760
|
+
let blob_refs = [];
|
761
|
+
await Promise.all(
|
762
|
+
param.map(async (v, i) => {
|
763
|
+
var _a;
|
764
|
+
let new_path = path.slice();
|
765
|
+
new_path.push(i);
|
766
|
+
const array_refs = await walk_and_store_blobs(
|
767
|
+
param[i],
|
768
|
+
root ? ((_a = api_info == null ? void 0 : api_info.parameters[i]) == null ? void 0 : _a.component) || void 0 : type,
|
769
|
+
new_path,
|
770
|
+
false,
|
771
|
+
api_info
|
772
|
+
);
|
773
|
+
blob_refs = blob_refs.concat(array_refs);
|
774
|
+
})
|
775
|
+
);
|
776
|
+
return blob_refs;
|
777
|
+
} else if (globalThis.Buffer && param instanceof globalThis.Buffer) {
|
778
|
+
const is_image = type === "Image";
|
779
|
+
return [
|
780
|
+
{
|
781
|
+
path,
|
782
|
+
blob: is_image ? false : new NodeBlob([param]),
|
783
|
+
data: is_image ? `${param.toString("base64")}` : false,
|
784
|
+
type
|
785
|
+
}
|
786
|
+
];
|
787
|
+
} else if (param instanceof Blob || typeof window !== "undefined" && param instanceof File) {
|
788
|
+
if (type === "Image") {
|
789
|
+
let data;
|
790
|
+
if (typeof window !== "undefined") {
|
791
|
+
data = await image_to_data_uri(param);
|
792
|
+
} else {
|
793
|
+
const buffer = await param.arrayBuffer();
|
794
|
+
data = Buffer.from(buffer).toString("base64");
|
795
|
+
}
|
796
|
+
return [{ path, data, type }];
|
797
|
+
} else {
|
798
|
+
return [{ path, blob: param, type }];
|
799
|
+
}
|
800
|
+
} else if (typeof param === "object") {
|
801
|
+
let blob_refs = [];
|
802
|
+
for (let key in param) {
|
803
|
+
if (param.hasOwnProperty(key)) {
|
804
|
+
let new_path = path.slice();
|
805
|
+
new_path.push(key);
|
806
|
+
blob_refs = blob_refs.concat(
|
807
|
+
await walk_and_store_blobs(
|
808
|
+
param[key],
|
809
|
+
void 0,
|
810
|
+
new_path,
|
811
|
+
false,
|
812
|
+
api_info
|
813
|
+
)
|
814
|
+
);
|
815
|
+
}
|
816
|
+
}
|
817
|
+
return blob_refs;
|
818
|
+
} else {
|
819
|
+
return [];
|
820
|
+
}
|
821
|
+
}
|
822
|
+
function image_to_data_uri(blob) {
|
823
|
+
return new Promise((resolve, _) => {
|
824
|
+
const reader = new FileReader();
|
825
|
+
reader.onloadend = () => resolve(reader.result);
|
826
|
+
reader.readAsDataURL(blob);
|
827
|
+
});
|
828
|
+
}
|
829
|
+
function skip_queue(id, config) {
|
830
|
+
var _a, _b, _c, _d;
|
831
|
+
return !(((_b = (_a = config == null ? void 0 : config.dependencies) == null ? void 0 : _a[id]) == null ? void 0 : _b.queue) === null ? config.enable_queue : (_d = (_c = config == null ? void 0 : config.dependencies) == null ? void 0 : _c[id]) == null ? void 0 : _d.queue) || false;
|
832
|
+
}
|
833
|
+
async function resolve_config(endpoint, token) {
|
834
|
+
const headers = {};
|
835
|
+
if (token) {
|
836
|
+
headers.Authorization = `Bearer ${token}`;
|
837
|
+
}
|
838
|
+
if (typeof window !== "undefined" && window.gradio_config && location.origin !== "http://localhost:9876") {
|
839
|
+
const path = window.gradio_config.root;
|
840
|
+
const config = window.gradio_config;
|
841
|
+
config.root = endpoint + config.root;
|
842
|
+
return { ...config, path };
|
843
|
+
} else if (endpoint) {
|
844
|
+
console.log(`${endpoint}/config`, headers);
|
845
|
+
let response = await fetch(`${endpoint}/config`, { headers });
|
846
|
+
console.log(response);
|
847
|
+
if (response.status === 200) {
|
848
|
+
const config = await response.json();
|
849
|
+
config.path = config.path ?? "";
|
850
|
+
config.root = endpoint;
|
851
|
+
return config;
|
852
|
+
} else {
|
853
|
+
throw new Error("Could not get config.");
|
854
|
+
}
|
855
|
+
}
|
856
|
+
throw new Error("No config or app endpoint found");
|
857
|
+
}
|
858
|
+
async function check_space_status(id, type, status_callback) {
|
859
|
+
let endpoint = type === "subdomain" ? `https://huggingface.co/api/spaces/by-subdomain/${id}` : `https://huggingface.co/api/spaces/${id}`;
|
860
|
+
let response;
|
861
|
+
let _status;
|
862
|
+
try {
|
863
|
+
response = await fetch(endpoint);
|
864
|
+
_status = response.status;
|
865
|
+
if (_status !== 200) {
|
866
|
+
throw new Error();
|
867
|
+
}
|
868
|
+
response = await response.json();
|
869
|
+
} catch (e) {
|
870
|
+
status_callback({
|
871
|
+
status: "error",
|
872
|
+
load_status: "error",
|
873
|
+
message: "Could not get space status",
|
874
|
+
detail: "NOT_FOUND"
|
875
|
+
});
|
876
|
+
return;
|
877
|
+
}
|
878
|
+
if (!response || _status !== 200)
|
879
|
+
return;
|
880
|
+
const {
|
881
|
+
runtime: { stage },
|
882
|
+
id: space_name
|
883
|
+
} = response;
|
884
|
+
switch (stage) {
|
885
|
+
case "STOPPED":
|
886
|
+
case "SLEEPING":
|
887
|
+
status_callback({
|
888
|
+
status: "sleeping",
|
889
|
+
load_status: "pending",
|
890
|
+
message: "Space is asleep. Waking it up...",
|
891
|
+
detail: stage
|
892
|
+
});
|
893
|
+
setTimeout(() => {
|
894
|
+
check_space_status(id, type, status_callback);
|
895
|
+
}, 1e3);
|
896
|
+
break;
|
897
|
+
case "RUNNING":
|
898
|
+
case "RUNNING_BUILDING":
|
899
|
+
status_callback({
|
900
|
+
status: "running",
|
901
|
+
load_status: "complete",
|
902
|
+
message: "",
|
903
|
+
detail: stage
|
904
|
+
});
|
905
|
+
break;
|
906
|
+
case "BUILDING":
|
907
|
+
status_callback({
|
908
|
+
status: "building",
|
909
|
+
load_status: "pending",
|
910
|
+
message: "Space is building...",
|
911
|
+
detail: stage
|
912
|
+
});
|
913
|
+
setTimeout(() => {
|
914
|
+
check_space_status(id, type, status_callback);
|
915
|
+
}, 1e3);
|
916
|
+
break;
|
917
|
+
default:
|
918
|
+
status_callback({
|
919
|
+
status: "space_error",
|
920
|
+
load_status: "error",
|
921
|
+
message: "This space is experiencing an issue.",
|
922
|
+
detail: stage,
|
923
|
+
discussions_enabled: await discussions_enabled(space_name)
|
924
|
+
});
|
925
|
+
break;
|
926
|
+
}
|
927
|
+
}
|
928
|
+
function handle_message(data, last_status) {
|
929
|
+
const queue = true;
|
930
|
+
switch (data.msg) {
|
931
|
+
case "send_data":
|
932
|
+
return { type: "data" };
|
933
|
+
case "send_hash":
|
934
|
+
return { type: "hash" };
|
935
|
+
case "queue_full":
|
936
|
+
return {
|
937
|
+
type: "update",
|
938
|
+
status: {
|
939
|
+
queue,
|
940
|
+
message: QUEUE_FULL_MSG,
|
941
|
+
stage: "error",
|
942
|
+
code: data.code,
|
943
|
+
success: data.success
|
944
|
+
}
|
945
|
+
};
|
946
|
+
case "estimation":
|
947
|
+
return {
|
948
|
+
type: "update",
|
949
|
+
status: {
|
950
|
+
queue,
|
951
|
+
stage: last_status || "pending",
|
952
|
+
code: data.code,
|
953
|
+
size: data.queue_size,
|
954
|
+
position: data.rank,
|
955
|
+
eta: data.rank_eta,
|
956
|
+
success: data.success
|
957
|
+
}
|
958
|
+
};
|
959
|
+
case "progress":
|
960
|
+
return {
|
961
|
+
type: "update",
|
962
|
+
status: {
|
963
|
+
queue,
|
964
|
+
stage: "pending",
|
965
|
+
code: data.code,
|
966
|
+
progress_data: data.progress_data,
|
967
|
+
success: data.success
|
968
|
+
}
|
969
|
+
};
|
970
|
+
case "process_generating":
|
971
|
+
return {
|
972
|
+
type: "generating",
|
973
|
+
status: {
|
974
|
+
queue,
|
975
|
+
message: !data.success ? data.output.error : null,
|
976
|
+
stage: data.success ? "generating" : "error",
|
977
|
+
code: data.code,
|
978
|
+
progress_data: data.progress_data,
|
979
|
+
eta: data.average_duration
|
980
|
+
},
|
981
|
+
data: data.success ? data.output : null
|
982
|
+
};
|
983
|
+
case "process_completed":
|
984
|
+
return {
|
985
|
+
type: "complete",
|
986
|
+
status: {
|
987
|
+
queue,
|
988
|
+
message: !data.success ? data.output.error : void 0,
|
989
|
+
stage: data.success ? "complete" : "error",
|
990
|
+
code: data.code,
|
991
|
+
progress_data: data.progress_data,
|
992
|
+
eta: data.output.average_duration
|
993
|
+
},
|
994
|
+
data: data.success ? data.output : null
|
995
|
+
};
|
996
|
+
case "process_starts":
|
997
|
+
return {
|
998
|
+
type: "update",
|
999
|
+
status: {
|
1000
|
+
queue,
|
1001
|
+
stage: "pending",
|
1002
|
+
code: data.code,
|
1003
|
+
size: data.rank,
|
1004
|
+
position: 0,
|
1005
|
+
success: data.success
|
1006
|
+
}
|
1007
|
+
};
|
1008
|
+
}
|
1009
|
+
return { type: "none", status: { stage: "error", queue } };
|
1010
|
+
}
|
1011
|
+
export {
|
1012
|
+
client,
|
1013
|
+
duplicate,
|
1014
|
+
post_data,
|
1015
|
+
upload_files
|
1016
|
+
};
|