@gradio/client 0.1.3 → 0.1.4
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 +6 -0
- package/dist/client.d.ts +19 -9
- package/dist/client.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +438 -418
- package/dist/types.d.ts +8 -8
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/client.ts +534 -503
- package/src/globals.d.ts +1 -1
- package/src/index.ts +7 -1
- package/src/types.ts +1 -1
package/src/client.ts
CHANGED
@@ -58,62 +58,8 @@ type SubmitReturn = {
|
|
58
58
|
const QUEUE_FULL_MSG = "This application is too busy. Keep trying!";
|
59
59
|
const BROKEN_CONNECTION_MSG = "Connection errored out.";
|
60
60
|
|
61
|
-
export async function post_data(
|
62
|
-
url: string,
|
63
|
-
body: unknown,
|
64
|
-
token?: `hf_${string}`
|
65
|
-
): Promise<[PostResponse, number]> {
|
66
|
-
const headers: {
|
67
|
-
Authorization?: string;
|
68
|
-
"Content-Type": "application/json";
|
69
|
-
} = { "Content-Type": "application/json" };
|
70
|
-
if (token) {
|
71
|
-
headers.Authorization = `Bearer ${token}`;
|
72
|
-
}
|
73
|
-
try {
|
74
|
-
var response = await fetch(url, {
|
75
|
-
method: "POST",
|
76
|
-
body: JSON.stringify(body),
|
77
|
-
headers
|
78
|
-
});
|
79
|
-
} catch (e) {
|
80
|
-
return [{ error: BROKEN_CONNECTION_MSG }, 500];
|
81
|
-
}
|
82
|
-
const output: PostResponse = await response.json();
|
83
|
-
return [output, response.status];
|
84
|
-
}
|
85
|
-
|
86
61
|
export let NodeBlob;
|
87
62
|
|
88
|
-
export async function upload_files(
|
89
|
-
root: string,
|
90
|
-
files: Array<File>,
|
91
|
-
token?: `hf_${string}`
|
92
|
-
): Promise<UploadResponse> {
|
93
|
-
const headers: {
|
94
|
-
Authorization?: string;
|
95
|
-
} = {};
|
96
|
-
if (token) {
|
97
|
-
headers.Authorization = `Bearer ${token}`;
|
98
|
-
}
|
99
|
-
|
100
|
-
const formData = new FormData();
|
101
|
-
files.forEach((file) => {
|
102
|
-
formData.append("files", file);
|
103
|
-
});
|
104
|
-
try {
|
105
|
-
var response = await fetch(`${root}/upload`, {
|
106
|
-
method: "POST",
|
107
|
-
body: formData,
|
108
|
-
headers
|
109
|
-
});
|
110
|
-
} catch (e) {
|
111
|
-
return { error: BROKEN_CONNECTION_MSG };
|
112
|
-
}
|
113
|
-
const output: UploadResponse["files"] = await response.json();
|
114
|
-
return { files: output };
|
115
|
-
}
|
116
|
-
|
117
63
|
export async function duplicate(
|
118
64
|
app_reference: string,
|
119
65
|
options: {
|
@@ -197,489 +143,615 @@ export async function duplicate(
|
|
197
143
|
}
|
198
144
|
}
|
199
145
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
146
|
+
/**
|
147
|
+
* We need to inject a customized fetch implementation for the Wasm version.
|
148
|
+
*/
|
149
|
+
export function api_factory(fetch_implementation: typeof fetch) {
|
150
|
+
return { post_data, upload_files, client, handle_blob };
|
151
|
+
|
152
|
+
async function post_data(
|
153
|
+
url: string,
|
154
|
+
body: unknown,
|
155
|
+
token?: `hf_${string}`
|
156
|
+
): Promise<[PostResponse, number]> {
|
157
|
+
const headers: {
|
158
|
+
Authorization?: string;
|
159
|
+
"Content-Type": "application/json";
|
160
|
+
} = { "Content-Type": "application/json" };
|
161
|
+
if (token) {
|
162
|
+
headers.Authorization = `Bearer ${token}`;
|
163
|
+
}
|
164
|
+
try {
|
165
|
+
var response = await fetch_implementation(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: PostResponse = await response.json();
|
174
|
+
return [output, response.status];
|
175
|
+
}
|
216
176
|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
177
|
+
async function upload_files(
|
178
|
+
root: string,
|
179
|
+
files: Array<File>,
|
180
|
+
token?: `hf_${string}`
|
181
|
+
): Promise<UploadResponse> {
|
182
|
+
const headers: {
|
183
|
+
Authorization?: string;
|
184
|
+
} = {};
|
185
|
+
if (token) {
|
186
|
+
headers.Authorization = `Bearer ${token}`;
|
223
187
|
}
|
224
188
|
|
225
|
-
const
|
226
|
-
|
189
|
+
const formData = new FormData();
|
190
|
+
files.forEach((file) => {
|
191
|
+
formData.append("files", file);
|
192
|
+
});
|
193
|
+
try {
|
194
|
+
var response = await fetch_implementation(`${root}/upload`, {
|
195
|
+
method: "POST",
|
196
|
+
body: formData,
|
197
|
+
headers
|
198
|
+
});
|
199
|
+
} catch (e) {
|
200
|
+
return { error: BROKEN_CONNECTION_MSG };
|
201
|
+
}
|
202
|
+
const output: UploadResponse["files"] = await response.json();
|
203
|
+
return { files: output };
|
204
|
+
}
|
227
205
|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
206
|
+
async function client(
|
207
|
+
app_reference: string,
|
208
|
+
options: {
|
209
|
+
hf_token?: `hf_${string}`;
|
210
|
+
status_callback?: SpaceStatusCallback;
|
211
|
+
normalise_files?: boolean;
|
212
|
+
} = { normalise_files: true }
|
213
|
+
): Promise<client_return> {
|
214
|
+
return new Promise(async (res) => {
|
215
|
+
const { status_callback, hf_token, normalise_files } = options;
|
216
|
+
const return_obj = {
|
217
|
+
predict,
|
218
|
+
submit,
|
219
|
+
view_api
|
220
|
+
// duplicate
|
221
|
+
};
|
232
222
|
|
233
|
-
|
223
|
+
const transform_files = normalise_files ?? true;
|
224
|
+
if (typeof window === "undefined" || !("WebSocket" in window)) {
|
225
|
+
const ws = await import("ws");
|
226
|
+
NodeBlob = (await import("node:buffer")).Blob;
|
227
|
+
//@ts-ignore
|
228
|
+
global.WebSocket = ws.WebSocket;
|
229
|
+
}
|
234
230
|
|
235
|
-
|
236
|
-
|
237
|
-
}
|
231
|
+
const { ws_protocol, http_protocol, host, space_id } =
|
232
|
+
await process_endpoint(app_reference, hf_token);
|
238
233
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
234
|
+
const session_hash = Math.random().toString(36).substring(2);
|
235
|
+
const last_status: Record<string, Status["stage"]> = {};
|
236
|
+
let config: Config;
|
237
|
+
let api_map: Record<string, number> = {};
|
238
|
+
|
239
|
+
let jwt: false | string = false;
|
240
|
+
|
241
|
+
if (hf_token && space_id) {
|
242
|
+
jwt = await get_jwt(space_id, hf_token);
|
246
243
|
}
|
247
244
|
|
248
|
-
|
249
|
-
config
|
250
|
-
|
251
|
-
};
|
252
|
-
}
|
253
|
-
let api: ApiInfo<JsApiData>;
|
254
|
-
async function handle_space_sucess(status: SpaceStatus) {
|
255
|
-
if (status_callback) status_callback(status);
|
256
|
-
if (status.status === "running")
|
245
|
+
async function config_success(_config: Config) {
|
246
|
+
config = _config;
|
247
|
+
api_map = map_names_to_ids(_config?.dependencies || []);
|
257
248
|
try {
|
258
|
-
|
259
|
-
|
260
|
-
const _config = await config_success(config);
|
261
|
-
res(_config);
|
249
|
+
api = await view_api(config);
|
262
250
|
} catch (e) {
|
263
|
-
|
264
|
-
status_callback({
|
265
|
-
status: "error",
|
266
|
-
message: "Could not load this space.",
|
267
|
-
load_status: "error",
|
268
|
-
detail: "NOT_FOUND"
|
269
|
-
});
|
270
|
-
}
|
251
|
+
console.error(`Could not get api details: ${e.message}`);
|
271
252
|
}
|
272
|
-
}
|
273
|
-
|
274
|
-
try {
|
275
|
-
config = await resolve_config(`${http_protocol}//${host}`, hf_token);
|
276
253
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
check_space_status(
|
282
|
-
space_id,
|
283
|
-
RE_SPACE_NAME.test(space_id) ? "space_name" : "subdomain",
|
284
|
-
handle_space_sucess
|
285
|
-
);
|
286
|
-
} else {
|
287
|
-
if (status_callback)
|
288
|
-
status_callback({
|
289
|
-
status: "error",
|
290
|
-
message: "Could not load this space.",
|
291
|
-
load_status: "error",
|
292
|
-
detail: "NOT_FOUND"
|
293
|
-
});
|
254
|
+
return {
|
255
|
+
config,
|
256
|
+
...return_obj
|
257
|
+
};
|
294
258
|
}
|
295
|
-
|
259
|
+
let api: ApiInfo<JsApiData>;
|
260
|
+
async function handle_space_sucess(status: SpaceStatus) {
|
261
|
+
if (status_callback) status_callback(status);
|
262
|
+
if (status.status === "running")
|
263
|
+
try {
|
264
|
+
config = await resolve_config(
|
265
|
+
fetch_implementation,
|
266
|
+
`${http_protocol}//${host}`,
|
267
|
+
hf_token
|
268
|
+
);
|
296
269
|
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
app
|
310
|
-
.on("data", (d) => {
|
311
|
-
data_returned = true;
|
312
|
-
if (status_complete) {
|
313
|
-
app.destroy();
|
314
|
-
}
|
315
|
-
res(d);
|
316
|
-
})
|
317
|
-
.on("status", (status) => {
|
318
|
-
if (status.stage === "error") rej(status);
|
319
|
-
if (status.stage === "complete" && data_returned) {
|
320
|
-
app.destroy();
|
321
|
-
}
|
322
|
-
if (status.stage === "complete") {
|
323
|
-
status_complete = true;
|
270
|
+
const _config = await config_success(config);
|
271
|
+
res(_config);
|
272
|
+
} catch (e) {
|
273
|
+
console.error(e);
|
274
|
+
if (status_callback) {
|
275
|
+
status_callback({
|
276
|
+
status: "error",
|
277
|
+
message: "Could not load this space.",
|
278
|
+
load_status: "error",
|
279
|
+
detail: "NOT_FOUND"
|
280
|
+
});
|
324
281
|
}
|
325
|
-
}
|
326
|
-
}
|
327
|
-
}
|
282
|
+
}
|
283
|
+
}
|
328
284
|
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
let api_info;
|
336
|
-
|
337
|
-
if (typeof endpoint === "number") {
|
338
|
-
fn_index = endpoint;
|
339
|
-
api_info = api.unnamed_endpoints[fn_index];
|
340
|
-
} else {
|
341
|
-
const trimmed_endpoint = endpoint.replace(/^\//, "");
|
285
|
+
try {
|
286
|
+
config = await resolve_config(
|
287
|
+
fetch_implementation,
|
288
|
+
`${http_protocol}//${host}`,
|
289
|
+
hf_token
|
290
|
+
);
|
342
291
|
|
343
|
-
|
344
|
-
|
292
|
+
const _config = await config_success(config);
|
293
|
+
res(_config);
|
294
|
+
} catch (e) {
|
295
|
+
console.error(e);
|
296
|
+
if (space_id) {
|
297
|
+
check_space_status(
|
298
|
+
space_id,
|
299
|
+
RE_SPACE_NAME.test(space_id) ? "space_name" : "subdomain",
|
300
|
+
handle_space_sucess
|
301
|
+
);
|
302
|
+
} else {
|
303
|
+
if (status_callback)
|
304
|
+
status_callback({
|
305
|
+
status: "error",
|
306
|
+
message: "Could not load this space.",
|
307
|
+
load_status: "error",
|
308
|
+
detail: "NOT_FOUND"
|
309
|
+
});
|
310
|
+
}
|
345
311
|
}
|
346
312
|
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
313
|
+
/**
|
314
|
+
* Run a prediction.
|
315
|
+
* @param endpoint - The prediction endpoint to use.
|
316
|
+
* @param status_callback - A function that is called with the current status of the prediction immediately and every time it updates.
|
317
|
+
* @return Returns the data for the prediction or an error message.
|
318
|
+
*/
|
319
|
+
function predict(
|
320
|
+
endpoint: string,
|
321
|
+
data: unknown[],
|
322
|
+
event_data?: unknown
|
323
|
+
) {
|
324
|
+
let data_returned = false;
|
325
|
+
let status_complete = false;
|
326
|
+
return new Promise((res, rej) => {
|
327
|
+
const app = submit(endpoint, data, event_data);
|
328
|
+
|
329
|
+
app
|
330
|
+
.on("data", (d) => {
|
331
|
+
data_returned = true;
|
332
|
+
if (status_complete) {
|
333
|
+
app.destroy();
|
334
|
+
}
|
335
|
+
res(d);
|
336
|
+
})
|
337
|
+
.on("status", (status) => {
|
338
|
+
if (status.stage === "error") rej(status);
|
339
|
+
if (status.stage === "complete" && data_returned) {
|
340
|
+
app.destroy();
|
341
|
+
}
|
342
|
+
if (status.stage === "complete") {
|
343
|
+
status_complete = true;
|
344
|
+
}
|
345
|
+
});
|
346
|
+
});
|
351
347
|
}
|
352
348
|
|
353
|
-
|
349
|
+
function submit(
|
350
|
+
endpoint: string | number,
|
351
|
+
data: unknown[],
|
352
|
+
event_data?: unknown
|
353
|
+
): SubmitReturn {
|
354
|
+
let fn_index: number;
|
355
|
+
let api_info;
|
356
|
+
|
357
|
+
if (typeof endpoint === "number") {
|
358
|
+
fn_index = endpoint;
|
359
|
+
api_info = api.unnamed_endpoints[fn_index];
|
360
|
+
} else {
|
361
|
+
const trimmed_endpoint = endpoint.replace(/^\//, "");
|
354
362
|
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
const listener_map: ListenerMap<EventType> = {};
|
363
|
+
fn_index = api_map[trimmed_endpoint];
|
364
|
+
api_info = api.named_endpoints[endpoint.trim()];
|
365
|
+
}
|
359
366
|
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
).then((_payload) => {
|
366
|
-
payload = { data: _payload || [], event_data, fn_index };
|
367
|
-
if (skip_queue(fn_index, config)) {
|
368
|
-
fire_event({
|
369
|
-
type: "status",
|
370
|
-
endpoint: _endpoint,
|
371
|
-
stage: "pending",
|
372
|
-
queue: false,
|
373
|
-
fn_index,
|
374
|
-
time: new Date()
|
375
|
-
});
|
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
|
+
}
|
376
372
|
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
fn_index,
|
401
|
-
data: data,
|
402
|
-
time: new Date()
|
403
|
-
});
|
373
|
+
let websocket: WebSocket;
|
374
|
+
|
375
|
+
const _endpoint = typeof endpoint === "number" ? "/predict" : endpoint;
|
376
|
+
let payload: Payload;
|
377
|
+
let complete: false | Record<string, any> = false;
|
378
|
+
const listener_map: ListenerMap<EventType> = {};
|
379
|
+
|
380
|
+
handle_blob(
|
381
|
+
`${http_protocol}//${host + config.path}`,
|
382
|
+
data,
|
383
|
+
api_info,
|
384
|
+
hf_token
|
385
|
+
).then((_payload) => {
|
386
|
+
payload = { data: _payload || [], event_data, fn_index };
|
387
|
+
if (skip_queue(fn_index, config)) {
|
388
|
+
fire_event({
|
389
|
+
type: "status",
|
390
|
+
endpoint: _endpoint,
|
391
|
+
stage: "pending",
|
392
|
+
queue: false,
|
393
|
+
fn_index,
|
394
|
+
time: new Date()
|
395
|
+
});
|
404
396
|
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
397
|
+
post_data(
|
398
|
+
`${http_protocol}//${host + config.path}/run${
|
399
|
+
_endpoint.startsWith("/") ? _endpoint : `/${_endpoint}`
|
400
|
+
}`,
|
401
|
+
{
|
402
|
+
...payload,
|
403
|
+
session_hash
|
404
|
+
},
|
405
|
+
hf_token
|
406
|
+
)
|
407
|
+
.then(([output, status_code]) => {
|
408
|
+
const data = transform_files
|
409
|
+
? transform_output(
|
410
|
+
output.data,
|
411
|
+
api_info,
|
412
|
+
config.root,
|
413
|
+
config.root_url
|
414
|
+
)
|
415
|
+
: output.data;
|
416
|
+
if (status_code == 200) {
|
417
|
+
fire_event({
|
418
|
+
type: "data",
|
419
|
+
endpoint: _endpoint,
|
420
|
+
fn_index,
|
421
|
+
data: data,
|
422
|
+
time: new Date()
|
423
|
+
});
|
424
|
+
|
425
|
+
fire_event({
|
426
|
+
type: "status",
|
427
|
+
endpoint: _endpoint,
|
428
|
+
fn_index,
|
429
|
+
stage: "complete",
|
430
|
+
eta: output.average_duration,
|
431
|
+
queue: false,
|
432
|
+
time: new Date()
|
433
|
+
});
|
434
|
+
} else {
|
435
|
+
fire_event({
|
436
|
+
type: "status",
|
437
|
+
stage: "error",
|
438
|
+
endpoint: _endpoint,
|
439
|
+
fn_index,
|
440
|
+
message: output.error,
|
441
|
+
queue: false,
|
442
|
+
time: new Date()
|
443
|
+
});
|
444
|
+
}
|
445
|
+
})
|
446
|
+
.catch((e) => {
|
415
447
|
fire_event({
|
416
448
|
type: "status",
|
417
449
|
stage: "error",
|
450
|
+
message: e.message,
|
418
451
|
endpoint: _endpoint,
|
419
452
|
fn_index,
|
420
|
-
message: output.error,
|
421
453
|
queue: false,
|
422
454
|
time: new Date()
|
423
455
|
});
|
424
|
-
}
|
425
|
-
})
|
426
|
-
.catch((e) => {
|
427
|
-
fire_event({
|
428
|
-
type: "status",
|
429
|
-
stage: "error",
|
430
|
-
message: e.message,
|
431
|
-
endpoint: _endpoint,
|
432
|
-
fn_index,
|
433
|
-
queue: false,
|
434
|
-
time: new Date()
|
435
456
|
});
|
457
|
+
} else {
|
458
|
+
fire_event({
|
459
|
+
type: "status",
|
460
|
+
stage: "pending",
|
461
|
+
queue: true,
|
462
|
+
endpoint: _endpoint,
|
463
|
+
fn_index,
|
464
|
+
time: new Date()
|
436
465
|
});
|
437
|
-
} else {
|
438
|
-
fire_event({
|
439
|
-
type: "status",
|
440
|
-
stage: "pending",
|
441
|
-
queue: true,
|
442
|
-
endpoint: _endpoint,
|
443
|
-
fn_index,
|
444
|
-
time: new Date()
|
445
|
-
});
|
446
|
-
|
447
|
-
let url = new URL(`${ws_protocol}://${host}${config.path}
|
448
|
-
/queue/join`);
|
449
466
|
|
450
|
-
|
451
|
-
|
452
|
-
}
|
467
|
+
let url = new URL(`${ws_protocol}://${host}${config.path}
|
468
|
+
/queue/join`);
|
453
469
|
|
454
|
-
|
455
|
-
|
456
|
-
websocket.onclose = (evt) => {
|
457
|
-
if (!evt.wasClean) {
|
458
|
-
fire_event({
|
459
|
-
type: "status",
|
460
|
-
stage: "error",
|
461
|
-
message: BROKEN_CONNECTION_MSG,
|
462
|
-
queue: true,
|
463
|
-
endpoint: _endpoint,
|
464
|
-
fn_index,
|
465
|
-
time: new Date()
|
466
|
-
});
|
470
|
+
if (jwt) {
|
471
|
+
url.searchParams.set("__sign", jwt);
|
467
472
|
}
|
468
|
-
};
|
469
473
|
|
470
|
-
|
471
|
-
const _data = JSON.parse(event.data);
|
472
|
-
const { type, status, data } = handle_message(
|
473
|
-
_data,
|
474
|
-
last_status[fn_index]
|
475
|
-
);
|
474
|
+
websocket = new WebSocket(url);
|
476
475
|
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
476
|
+
websocket.onclose = (evt) => {
|
477
|
+
if (!evt.wasClean) {
|
478
|
+
fire_event({
|
479
|
+
type: "status",
|
480
|
+
stage: "error",
|
481
|
+
message: BROKEN_CONNECTION_MSG,
|
482
|
+
queue: true,
|
483
|
+
endpoint: _endpoint,
|
484
|
+
fn_index,
|
485
|
+
time: new Date()
|
486
|
+
});
|
488
487
|
}
|
489
|
-
}
|
490
|
-
websocket.send(JSON.stringify({ fn_index, session_hash }));
|
491
|
-
return;
|
492
|
-
} else if (type === "data") {
|
493
|
-
websocket.send(JSON.stringify({ ...payload, session_hash }));
|
494
|
-
} else if (type === "complete") {
|
495
|
-
complete = status;
|
496
|
-
} else if (type === "generating") {
|
497
|
-
fire_event({
|
498
|
-
type: "status",
|
499
|
-
time: new Date(),
|
500
|
-
...status,
|
501
|
-
stage: status?.stage!,
|
502
|
-
queue: true,
|
503
|
-
endpoint: _endpoint,
|
504
|
-
fn_index
|
505
|
-
});
|
506
|
-
}
|
507
|
-
if (data) {
|
508
|
-
fire_event({
|
509
|
-
type: "data",
|
510
|
-
time: new Date(),
|
511
|
-
data: transform_files
|
512
|
-
? transform_output(
|
513
|
-
data.data,
|
514
|
-
api_info,
|
515
|
-
config.root,
|
516
|
-
config.root_url
|
517
|
-
)
|
518
|
-
: data.data,
|
519
|
-
endpoint: _endpoint,
|
520
|
-
fn_index
|
521
|
-
});
|
488
|
+
};
|
522
489
|
|
523
|
-
|
490
|
+
websocket.onmessage = function (event) {
|
491
|
+
const _data = JSON.parse(event.data);
|
492
|
+
const { type, status, data } = handle_message(
|
493
|
+
_data,
|
494
|
+
last_status[fn_index]
|
495
|
+
);
|
496
|
+
|
497
|
+
if (type === "update" && status && !complete) {
|
498
|
+
// call 'status' listeners
|
499
|
+
fire_event({
|
500
|
+
type: "status",
|
501
|
+
endpoint: _endpoint,
|
502
|
+
fn_index,
|
503
|
+
time: new Date(),
|
504
|
+
...status
|
505
|
+
});
|
506
|
+
if (status.stage === "error") {
|
507
|
+
websocket.close();
|
508
|
+
}
|
509
|
+
} else if (type === "hash") {
|
510
|
+
websocket.send(JSON.stringify({ fn_index, session_hash }));
|
511
|
+
return;
|
512
|
+
} else if (type === "data") {
|
513
|
+
websocket.send(JSON.stringify({ ...payload, session_hash }));
|
514
|
+
} else if (type === "complete") {
|
515
|
+
complete = status;
|
516
|
+
} else if (type === "generating") {
|
524
517
|
fire_event({
|
525
518
|
type: "status",
|
526
519
|
time: new Date(),
|
527
|
-
...
|
520
|
+
...status,
|
528
521
|
stage: status?.stage!,
|
529
522
|
queue: true,
|
530
523
|
endpoint: _endpoint,
|
531
524
|
fn_index
|
532
525
|
});
|
533
|
-
websocket.close();
|
534
526
|
}
|
535
|
-
|
536
|
-
|
527
|
+
if (data) {
|
528
|
+
fire_event({
|
529
|
+
type: "data",
|
530
|
+
time: new Date(),
|
531
|
+
data: transform_files
|
532
|
+
? transform_output(
|
533
|
+
data.data,
|
534
|
+
api_info,
|
535
|
+
config.root,
|
536
|
+
config.root_url
|
537
|
+
)
|
538
|
+
: data.data,
|
539
|
+
endpoint: _endpoint,
|
540
|
+
fn_index
|
541
|
+
});
|
537
542
|
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
543
|
+
if (complete) {
|
544
|
+
fire_event({
|
545
|
+
type: "status",
|
546
|
+
time: new Date(),
|
547
|
+
...complete,
|
548
|
+
stage: status?.stage!,
|
549
|
+
queue: true,
|
550
|
+
endpoint: _endpoint,
|
551
|
+
fn_index
|
552
|
+
});
|
553
|
+
websocket.close();
|
554
|
+
}
|
555
|
+
}
|
556
|
+
};
|
557
|
+
|
558
|
+
// different ws contract for gradio versions older than 3.6.0
|
559
|
+
//@ts-ignore
|
560
|
+
if (semiver(config.version || "2.0.0", "3.6") < 0) {
|
561
|
+
addEventListener("open", () =>
|
562
|
+
websocket.send(JSON.stringify({ hash: session_hash }))
|
563
|
+
);
|
564
|
+
}
|
544
565
|
}
|
545
|
-
}
|
546
|
-
});
|
566
|
+
});
|
547
567
|
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
568
|
+
function fire_event<K extends EventType>(event: Event<K>) {
|
569
|
+
const narrowed_listener_map: ListenerMap<K> = listener_map;
|
570
|
+
const listeners = narrowed_listener_map[event.type] || [];
|
571
|
+
listeners?.forEach((l) => l(event));
|
572
|
+
}
|
553
573
|
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
574
|
+
function on<K extends EventType>(
|
575
|
+
eventType: K,
|
576
|
+
listener: EventListener<K>
|
577
|
+
) {
|
578
|
+
const narrowed_listener_map: ListenerMap<K> = listener_map;
|
579
|
+
const listeners = narrowed_listener_map[eventType] || [];
|
580
|
+
narrowed_listener_map[eventType] = listeners;
|
581
|
+
listeners?.push(listener);
|
562
582
|
|
563
|
-
|
564
|
-
|
583
|
+
return { on, off, cancel, destroy };
|
584
|
+
}
|
565
585
|
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
586
|
+
function off<K extends EventType>(
|
587
|
+
eventType: K,
|
588
|
+
listener: EventListener<K>
|
589
|
+
) {
|
590
|
+
const narrowed_listener_map: ListenerMap<K> = listener_map;
|
591
|
+
let listeners = narrowed_listener_map[eventType] || [];
|
592
|
+
listeners = listeners?.filter((l) => l !== listener);
|
593
|
+
narrowed_listener_map[eventType] = listeners;
|
574
594
|
|
575
|
-
|
576
|
-
|
595
|
+
return { on, off, cancel, destroy };
|
596
|
+
}
|
577
597
|
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
598
|
+
async function cancel() {
|
599
|
+
const _status: Status = {
|
600
|
+
stage: "complete",
|
601
|
+
queue: false,
|
602
|
+
time: new Date()
|
603
|
+
};
|
604
|
+
complete = _status;
|
605
|
+
fire_event({
|
606
|
+
..._status,
|
607
|
+
type: "status",
|
608
|
+
endpoint: _endpoint,
|
609
|
+
fn_index: fn_index
|
610
|
+
});
|
591
611
|
|
592
|
-
|
593
|
-
|
612
|
+
if (websocket && websocket.readyState === 0) {
|
613
|
+
websocket.addEventListener("open", () => {
|
614
|
+
websocket.close();
|
615
|
+
});
|
616
|
+
} else {
|
594
617
|
websocket.close();
|
595
|
-
}
|
596
|
-
|
597
|
-
|
618
|
+
}
|
619
|
+
|
620
|
+
try {
|
621
|
+
await fetch_implementation(
|
622
|
+
`${http_protocol}//${host + config.path}/reset`,
|
623
|
+
{
|
624
|
+
headers: { "Content-Type": "application/json" },
|
625
|
+
method: "POST",
|
626
|
+
body: JSON.stringify({ fn_index, session_hash })
|
627
|
+
}
|
628
|
+
);
|
629
|
+
} catch (e) {
|
630
|
+
console.warn(
|
631
|
+
"The `/reset` endpoint could not be called. Subsequent endpoint results may be unreliable."
|
632
|
+
);
|
633
|
+
}
|
598
634
|
}
|
599
635
|
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
}
|
606
|
-
} catch (e) {
|
607
|
-
console.warn(
|
608
|
-
"The `/reset` endpoint could not be called. Subsequent endpoint results may be unreliable."
|
609
|
-
);
|
636
|
+
function destroy() {
|
637
|
+
for (const event_type in listener_map) {
|
638
|
+
listener_map[event_type as "data" | "status"].forEach((fn) => {
|
639
|
+
off(event_type as "data" | "status", fn);
|
640
|
+
});
|
641
|
+
}
|
610
642
|
}
|
643
|
+
|
644
|
+
return {
|
645
|
+
on,
|
646
|
+
off,
|
647
|
+
cancel,
|
648
|
+
destroy
|
649
|
+
};
|
611
650
|
}
|
612
651
|
|
613
|
-
function
|
614
|
-
|
615
|
-
|
616
|
-
|
652
|
+
async function view_api(config?: Config): Promise<ApiInfo<JsApiData>> {
|
653
|
+
if (api) return api;
|
654
|
+
|
655
|
+
const headers: {
|
656
|
+
Authorization?: string;
|
657
|
+
"Content-Type": "application/json";
|
658
|
+
} = { "Content-Type": "application/json" };
|
659
|
+
if (hf_token) {
|
660
|
+
headers.Authorization = `Bearer ${hf_token}`;
|
661
|
+
}
|
662
|
+
let response: Response;
|
663
|
+
// @ts-ignore
|
664
|
+
if (semiver(config.version || "2.0.0", "3.30") < 0) {
|
665
|
+
response = await fetch_implementation(
|
666
|
+
"https://gradio-space-api-fetcher-v2.hf.space/api",
|
667
|
+
{
|
668
|
+
method: "POST",
|
669
|
+
body: JSON.stringify({
|
670
|
+
serialize: false,
|
671
|
+
config: JSON.stringify(config)
|
672
|
+
}),
|
673
|
+
headers
|
674
|
+
}
|
675
|
+
);
|
676
|
+
} else {
|
677
|
+
response = await fetch_implementation(`${config.root}/info`, {
|
678
|
+
headers
|
617
679
|
});
|
618
680
|
}
|
619
|
-
}
|
620
681
|
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
cancel,
|
625
|
-
destroy
|
626
|
-
};
|
627
|
-
}
|
682
|
+
if (!response.ok) {
|
683
|
+
throw new Error(BROKEN_CONNECTION_MSG);
|
684
|
+
}
|
628
685
|
|
629
|
-
|
630
|
-
|
686
|
+
let api_info = (await response.json()) as
|
687
|
+
| ApiInfo<ApiData>
|
688
|
+
| { api: ApiInfo<ApiData> };
|
689
|
+
if ("api" in api_info) {
|
690
|
+
api_info = api_info.api;
|
691
|
+
}
|
631
692
|
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
}
|
639
|
-
let response: Response;
|
640
|
-
// @ts-ignore
|
641
|
-
if (semiver(config.version || "2.0.0", "3.30") < 0) {
|
642
|
-
response = await fetch(
|
643
|
-
"https://gradio-space-api-fetcher-v2.hf.space/api",
|
644
|
-
{
|
645
|
-
method: "POST",
|
646
|
-
body: JSON.stringify({
|
647
|
-
serialize: false,
|
648
|
-
config: JSON.stringify(config)
|
649
|
-
}),
|
650
|
-
headers
|
651
|
-
}
|
652
|
-
);
|
653
|
-
} else {
|
654
|
-
response = await fetch(`${config.root}/info`, {
|
655
|
-
headers
|
656
|
-
});
|
657
|
-
}
|
693
|
+
if (
|
694
|
+
api_info.named_endpoints["/predict"] &&
|
695
|
+
!api_info.unnamed_endpoints["0"]
|
696
|
+
) {
|
697
|
+
api_info.unnamed_endpoints[0] = api_info.named_endpoints["/predict"];
|
698
|
+
}
|
658
699
|
|
659
|
-
|
660
|
-
|
700
|
+
const x = transform_api_info(api_info, config, api_map);
|
701
|
+
return x;
|
661
702
|
}
|
703
|
+
});
|
704
|
+
}
|
662
705
|
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
706
|
+
async function handle_blob(
|
707
|
+
endpoint: string,
|
708
|
+
data: unknown[],
|
709
|
+
api_info,
|
710
|
+
token?: `hf_${string}`
|
711
|
+
): Promise<unknown[]> {
|
712
|
+
const blob_refs = await walk_and_store_blobs(
|
713
|
+
data,
|
714
|
+
undefined,
|
715
|
+
[],
|
716
|
+
true,
|
717
|
+
api_info
|
718
|
+
);
|
669
719
|
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
720
|
+
return Promise.all(
|
721
|
+
blob_refs.map(async ({ path, blob, data, type }) => {
|
722
|
+
if (blob) {
|
723
|
+
const file_url = (await upload_files(endpoint, [blob], token))
|
724
|
+
.files[0];
|
725
|
+
return { path, file_url, type };
|
726
|
+
} else {
|
727
|
+
return { path, base64: data, type };
|
728
|
+
}
|
729
|
+
})
|
730
|
+
).then((r) => {
|
731
|
+
r.forEach(({ path, file_url, base64, type }) => {
|
732
|
+
if (base64) {
|
733
|
+
update_object(data, base64, path);
|
734
|
+
} else if (type === "Gallery") {
|
735
|
+
update_object(data, file_url, path);
|
736
|
+
} else if (file_url) {
|
737
|
+
const o = {
|
738
|
+
is_file: true,
|
739
|
+
name: `${file_url}`,
|
740
|
+
data: null
|
741
|
+
// orig_name: "file.csv"
|
742
|
+
};
|
743
|
+
update_object(data, o, path);
|
744
|
+
}
|
745
|
+
});
|
676
746
|
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
});
|
747
|
+
return data;
|
748
|
+
});
|
749
|
+
}
|
681
750
|
}
|
682
751
|
|
752
|
+
export const { post_data, upload_files, client, handle_blob } =
|
753
|
+
api_factory(fetch);
|
754
|
+
|
683
755
|
function transform_output(
|
684
756
|
data: any[],
|
685
757
|
api_info: any,
|
@@ -902,50 +974,6 @@ async function get_jwt(
|
|
902
974
|
}
|
903
975
|
}
|
904
976
|
|
905
|
-
export async function handle_blob(
|
906
|
-
endpoint: string,
|
907
|
-
data: unknown[],
|
908
|
-
api_info,
|
909
|
-
token?: `hf_${string}`
|
910
|
-
): Promise<unknown[]> {
|
911
|
-
const blob_refs = await walk_and_store_blobs(
|
912
|
-
data,
|
913
|
-
undefined,
|
914
|
-
[],
|
915
|
-
true,
|
916
|
-
api_info
|
917
|
-
);
|
918
|
-
|
919
|
-
return Promise.all(
|
920
|
-
blob_refs.map(async ({ path, blob, data, type }) => {
|
921
|
-
if (blob) {
|
922
|
-
const file_url = (await upload_files(endpoint, [blob], token)).files[0];
|
923
|
-
return { path, file_url, type };
|
924
|
-
} else {
|
925
|
-
return { path, base64: data, type };
|
926
|
-
}
|
927
|
-
})
|
928
|
-
).then((r) => {
|
929
|
-
r.forEach(({ path, file_url, base64, type }) => {
|
930
|
-
if (base64) {
|
931
|
-
update_object(data, base64, path);
|
932
|
-
} else if (type === "Gallery") {
|
933
|
-
update_object(data, file_url, path);
|
934
|
-
} else if (file_url) {
|
935
|
-
const o = {
|
936
|
-
is_file: true,
|
937
|
-
name: `${file_url}`,
|
938
|
-
data: null
|
939
|
-
// orig_name: "file.csv"
|
940
|
-
};
|
941
|
-
update_object(data, o, path);
|
942
|
-
}
|
943
|
-
});
|
944
|
-
|
945
|
-
return data;
|
946
|
-
});
|
947
|
-
}
|
948
|
-
|
949
977
|
function update_object(object, newValue, stack) {
|
950
978
|
while (stack.length > 1) {
|
951
979
|
object = object[stack.shift()];
|
@@ -1051,6 +1079,7 @@ function skip_queue(id: number, config: Config) {
|
|
1051
1079
|
}
|
1052
1080
|
|
1053
1081
|
async function resolve_config(
|
1082
|
+
fetch_implementation: typeof fetch,
|
1054
1083
|
endpoint?: string,
|
1055
1084
|
token?: `hf_${string}`
|
1056
1085
|
): Promise<Config> {
|
@@ -1068,7 +1097,9 @@ async function resolve_config(
|
|
1068
1097
|
config.root = endpoint + config.root;
|
1069
1098
|
return { ...config, path: path };
|
1070
1099
|
} else if (endpoint) {
|
1071
|
-
let response = await
|
1100
|
+
let response = await fetch_implementation(`${endpoint}/config`, {
|
1101
|
+
headers
|
1102
|
+
});
|
1072
1103
|
|
1073
1104
|
if (response.status === 200) {
|
1074
1105
|
const config = await response.json();
|