@gradio/client 0.17.0 → 0.19.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.
Files changed (69) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +10 -6
  3. package/dist/client.d.ts +18 -7
  4. package/dist/client.d.ts.map +1 -1
  5. package/dist/constants.d.ts +8 -2
  6. package/dist/constants.d.ts.map +1 -1
  7. package/dist/helpers/api_info.d.ts +22 -0
  8. package/dist/helpers/api_info.d.ts.map +1 -1
  9. package/dist/helpers/data.d.ts +2 -2
  10. package/dist/helpers/data.d.ts.map +1 -1
  11. package/dist/helpers/init_helpers.d.ts.map +1 -1
  12. package/dist/helpers/spaces.d.ts.map +1 -1
  13. package/dist/index.d.ts +1 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +275 -183
  16. package/dist/test/handlers.d.ts +3 -0
  17. package/dist/test/handlers.d.ts.map +1 -0
  18. package/dist/test/mock_eventsource.d.ts +2 -0
  19. package/dist/test/mock_eventsource.d.ts.map +1 -0
  20. package/dist/test/server.d.ts +2 -0
  21. package/dist/test/server.d.ts.map +1 -0
  22. package/dist/test/test_data.d.ts +76 -0
  23. package/dist/test/test_data.d.ts.map +1 -0
  24. package/dist/types.d.ts +23 -7
  25. package/dist/types.d.ts.map +1 -1
  26. package/dist/upload.d.ts +2 -2
  27. package/dist/upload.d.ts.map +1 -1
  28. package/dist/utils/duplicate.d.ts.map +1 -1
  29. package/dist/utils/predict.d.ts +1 -1
  30. package/dist/utils/predict.d.ts.map +1 -1
  31. package/dist/utils/stream.d.ts +2 -2
  32. package/dist/utils/stream.d.ts.map +1 -1
  33. package/dist/utils/submit.d.ts +1 -1
  34. package/dist/utils/submit.d.ts.map +1 -1
  35. package/dist/utils/upload_files.d.ts.map +1 -1
  36. package/dist/utils/view_api.d.ts.map +1 -1
  37. package/package.json +8 -2
  38. package/src/client.ts +53 -28
  39. package/src/constants.ts +9 -2
  40. package/src/helpers/api_info.ts +75 -4
  41. package/src/helpers/data.ts +46 -28
  42. package/src/helpers/init_helpers.ts +7 -11
  43. package/src/helpers/spaces.ts +8 -3
  44. package/src/index.ts +1 -1
  45. package/src/test/api_info.test.ts +567 -0
  46. package/src/test/data.test.ts +281 -0
  47. package/src/test/handlers.ts +438 -0
  48. package/src/test/init.test.ts +139 -0
  49. package/src/test/init_helpers.test.ts +94 -0
  50. package/src/test/mock_eventsource.ts +13 -0
  51. package/src/test/post_data.test.ts +45 -0
  52. package/src/test/server.ts +6 -0
  53. package/src/test/spaces.test.ts +145 -0
  54. package/src/test/stream.test.ts +79 -0
  55. package/src/test/test_data.ts +557 -0
  56. package/src/test/upload_files.test.ts +42 -0
  57. package/src/test/view_api.test.ts +53 -0
  58. package/src/types.ts +36 -17
  59. package/src/upload.ts +4 -8
  60. package/src/utils/duplicate.ts +20 -3
  61. package/src/utils/handle_blob.ts +1 -1
  62. package/src/utils/post_data.ts +1 -1
  63. package/src/utils/predict.ts +2 -2
  64. package/src/utils/stream.ts +30 -21
  65. package/src/utils/submit.ts +42 -19
  66. package/src/utils/upload_files.ts +11 -6
  67. package/src/utils/view_api.ts +4 -7
  68. package/vite.config.js +7 -0
  69. package/src/utils/client.node-test.ts +0 -173
package/dist/index.js CHANGED
@@ -5,16 +5,23 @@ var __publicField = (obj, key, value) => {
5
5
  return value;
6
6
  };
7
7
  var fn = new Intl.Collator(0, { numeric: 1 }).compare;
8
- function semiver$1(a, b, bool) {
8
+ function semiver(a, b, bool) {
9
9
  a = a.split(".");
10
10
  b = b.split(".");
11
11
  return fn(a[0], b[0]) || fn(a[1], b[1]) || (b[2] = b.slice(2).join("."), bool = /[.-]/.test(a[2] = a.slice(2).join(".")), bool == /[.-]/.test(b[2]) ? fn(a[2], b[2]) : bool ? -1 : 1);
12
12
  }
13
+ const UPLOAD_URL = "upload";
13
14
  const CONFIG_URL = "config";
14
15
  const API_INFO_URL = "info";
16
+ const RUNTIME_URL = "runtime";
17
+ const SLEEPTIME_URL = "sleeptime";
15
18
  const SPACE_FETCHER_URL = "https://gradio-space-api-fetcher-v2.hf.space/api";
16
- const QUEUE_FULL_MSG = "This application is too busy. Keep trying!";
17
- const BROKEN_CONNECTION_MSG = "Connection errored out.";
19
+ const QUEUE_FULL_MSG = "This application is currently busy. Please try again. ";
20
+ const BROKEN_CONNECTION_MSG = "Connection errored out. ";
21
+ const CONFIG_ERROR_MSG = "Could not resolve app config. ";
22
+ const SPACE_STATUS_ERROR_MSG = "Could not get space status. ";
23
+ const API_INFO_ERROR_MSG = "Could not get API info. ";
24
+ const SPACE_METADATA_ERROR_MSG = "Space metadata could not be loaded. ";
18
25
  function resolve_root(base_url, root_path, prioritize_base) {
19
26
  if (root_path.startsWith("http://") || root_path.startsWith("https://")) {
20
27
  return prioritize_base ? base_url : root_path;
@@ -31,7 +38,6 @@ async function get_jwt(space, token) {
31
38
  const jwt = (await r.json()).token;
32
39
  return jwt || false;
33
40
  } catch (e) {
34
- console.error(e);
35
41
  return false;
36
42
  }
37
43
  }
@@ -53,21 +59,18 @@ async function resolve_config(endpoint) {
53
59
  config.root = config_root;
54
60
  return { ...config, path };
55
61
  } else if (endpoint) {
56
- const response = await this.fetch_implementation(
57
- `${endpoint}/${CONFIG_URL}`,
58
- {
59
- headers
60
- }
61
- );
62
+ const response = await this.fetch(`${endpoint}/${CONFIG_URL}`, {
63
+ headers
64
+ });
62
65
  if ((response == null ? void 0 : response.status) === 200) {
63
66
  let config = await response.json();
64
67
  config.path = config.path ?? "";
65
68
  config.root = endpoint;
66
69
  return config;
67
70
  }
68
- throw new Error("Could not get config.");
71
+ throw new Error(CONFIG_ERROR_MSG);
69
72
  }
70
- throw new Error("No config or app endpoint found");
73
+ throw new Error(CONFIG_ERROR_MSG);
71
74
  }
72
75
  function determine_protocol(endpoint) {
73
76
  if (endpoint.startsWith("http")) {
@@ -112,15 +115,15 @@ async function process_endpoint(app_reference, hf_token) {
112
115
  `https://huggingface.co/api/spaces/${_app_reference}/host`,
113
116
  { headers }
114
117
  );
115
- if (res.status !== 200)
116
- throw new Error("Space metadata could not be loaded.");
117
118
  const _host = (await res.json()).host;
118
119
  return {
119
120
  space_id: app_reference,
120
121
  ...determine_protocol(_host)
121
122
  };
122
123
  } catch (e) {
123
- throw new Error("Space metadata could not be loaded." + e.message);
124
+ throw new Error(
125
+ "Space metadata could not be loaded. " + e.message
126
+ );
124
127
  }
125
128
  }
126
129
  if (RE_SPACE_DOMAIN.test(_app_reference)) {
@@ -314,6 +317,45 @@ function handle_message(data, last_status) {
314
317
  }
315
318
  return { type: "none", status: { stage: "error", queue } };
316
319
  }
320
+ const map_data_to_params = (data, api_info) => {
321
+ const parameters = Object.values(api_info.named_endpoints).flatMap(
322
+ (values) => values.parameters
323
+ );
324
+ if (Array.isArray(data)) {
325
+ if (data.length > parameters.length) {
326
+ console.warn("Too many arguments provided for the endpoint.");
327
+ }
328
+ return data;
329
+ }
330
+ const resolved_data = [];
331
+ const provided_keys = Object.keys(data);
332
+ parameters.forEach((param, index) => {
333
+ if (data.hasOwnProperty(param.parameter_name)) {
334
+ resolved_data[index] = data[param.parameter_name];
335
+ } else if (param.parameter_has_default) {
336
+ resolved_data[index] = param.parameter_default;
337
+ } else {
338
+ throw new Error(
339
+ `No value provided for required parameter: ${param.parameter_name}`
340
+ );
341
+ }
342
+ });
343
+ provided_keys.forEach((key) => {
344
+ if (!parameters.some((param) => param.parameter_name === key)) {
345
+ throw new Error(
346
+ `Parameter \`${key}\` is not a valid keyword argument. Please refer to the API for usage.`
347
+ );
348
+ }
349
+ });
350
+ resolved_data.forEach((value, idx) => {
351
+ if (value === void 0 && !parameters[idx].parameter_has_default) {
352
+ throw new Error(
353
+ `No value provided for required parameter: ${parameters[idx].parameter_name}`
354
+ );
355
+ }
356
+ });
357
+ return resolved_data;
358
+ };
317
359
  async function view_api() {
318
360
  if (this.api_info)
319
361
  return this.api_info;
@@ -328,8 +370,8 @@ async function view_api() {
328
370
  }
329
371
  try {
330
372
  let response;
331
- if (semiver$1((config == null ? void 0 : config.version) || "2.0.0", "3.30") < 0) {
332
- response = await this.fetch_implementation(SPACE_FETCHER_URL, {
373
+ if (semiver((config == null ? void 0 : config.version) || "2.0.0", "3.30") < 0) {
374
+ response = await this.fetch(SPACE_FETCHER_URL, {
333
375
  method: "POST",
334
376
  body: JSON.stringify({
335
377
  serialize: false,
@@ -338,12 +380,9 @@ async function view_api() {
338
380
  headers
339
381
  });
340
382
  } else {
341
- response = await this.fetch_implementation(
342
- `${config == null ? void 0 : config.root}/${API_INFO_URL}`,
343
- {
344
- headers
345
- }
346
- );
383
+ response = await this.fetch(`${config == null ? void 0 : config.root}/${API_INFO_URL}`, {
384
+ headers
385
+ });
347
386
  }
348
387
  if (!response.ok) {
349
388
  throw new Error(BROKEN_CONNECTION_MSG);
@@ -361,12 +400,14 @@ async function view_api() {
361
400
  }
362
401
  }
363
402
  async function upload_files(root_url, files, upload_id) {
403
+ var _a;
364
404
  const headers = {};
365
- if (this.options.hf_token) {
405
+ if ((_a = this == null ? void 0 : this.options) == null ? void 0 : _a.hf_token) {
366
406
  headers.Authorization = `Bearer ${this.options.hf_token}`;
367
407
  }
368
408
  const chunkSize = 1e3;
369
409
  const uploadResponses = [];
410
+ let response;
370
411
  for (let i = 0; i < files.length; i += chunkSize) {
371
412
  const chunk = files.slice(i, i + chunkSize);
372
413
  const formData = new FormData();
@@ -374,17 +415,18 @@ async function upload_files(root_url, files, upload_id) {
374
415
  formData.append("files", file);
375
416
  });
376
417
  try {
377
- const upload_url = upload_id ? `${root_url}/upload?upload_id=${upload_id}` : `${root_url}/upload`;
378
- var response = await this.fetch_implementation(upload_url, {
418
+ const upload_url = upload_id ? `${root_url}/upload?upload_id=${upload_id}` : `${root_url}/${UPLOAD_URL}`;
419
+ response = await this.fetch(upload_url, {
379
420
  method: "POST",
380
421
  body: formData,
381
422
  headers
382
423
  });
383
424
  } catch (e) {
384
- return { error: BROKEN_CONNECTION_MSG };
425
+ throw new Error(BROKEN_CONNECTION_MSG + e.message);
385
426
  }
386
427
  if (!response.ok) {
387
- return { error: await response.text() };
428
+ const error_text = await response.text();
429
+ return { error: `HTTP ${response.status}: ${error_text}` };
388
430
  }
389
431
  const output = await response.json();
390
432
  if (output) {
@@ -393,87 +435,7 @@ async function upload_files(root_url, files, upload_id) {
393
435
  }
394
436
  return { files: uploadResponses };
395
437
  }
396
- function update_object(object, newValue, stack) {
397
- while (stack.length > 1) {
398
- const key2 = stack.shift();
399
- if (typeof key2 === "string" || typeof key2 === "number") {
400
- object = object[key2];
401
- } else {
402
- throw new Error("Invalid key type");
403
- }
404
- }
405
- const key = stack.shift();
406
- if (typeof key === "string" || typeof key === "number") {
407
- object[key] = newValue;
408
- } else {
409
- throw new Error("Invalid key type");
410
- }
411
- }
412
- async function walk_and_store_blobs(param, type = void 0, path = [], root = false, endpoint_info = void 0) {
413
- if (Array.isArray(param)) {
414
- let blob_refs = [];
415
- await Promise.all(
416
- param.map(async (item) => {
417
- var _a;
418
- let new_path = path.slice();
419
- new_path.push(item);
420
- const array_refs = await walk_and_store_blobs(
421
- param[item],
422
- root ? ((_a = endpoint_info == null ? void 0 : endpoint_info.parameters[item]) == null ? void 0 : _a.component) || void 0 : type,
423
- new_path,
424
- false,
425
- endpoint_info
426
- );
427
- blob_refs = blob_refs.concat(array_refs);
428
- })
429
- );
430
- return blob_refs;
431
- } else if (globalThis.Buffer && param instanceof globalThis.Buffer) {
432
- const is_image = type === "Image";
433
- return [
434
- {
435
- path,
436
- blob: is_image ? false : new NodeBlob([param]),
437
- type
438
- }
439
- ];
440
- } else if (typeof param === "object") {
441
- let blob_refs = [];
442
- for (let key in param) {
443
- if (param.hasOwnProperty(key)) {
444
- let new_path = path.slice();
445
- new_path.push(key);
446
- blob_refs = blob_refs.concat(
447
- await walk_and_store_blobs(
448
- // @ts-ignore
449
- param[key],
450
- void 0,
451
- new_path,
452
- false,
453
- endpoint_info
454
- )
455
- );
456
- }
457
- }
458
- return blob_refs;
459
- }
460
- return [];
461
- }
462
- function skip_queue(id, config) {
463
- var _a, _b, _c, _d;
464
- 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;
465
- }
466
- function post_message(message, origin) {
467
- return new Promise((res, _rej) => {
468
- const channel = new MessageChannel();
469
- channel.port1.onmessage = ({ data }) => {
470
- channel.port1.close();
471
- res(data);
472
- };
473
- window.parent.postMessage(message, origin, [channel.port2]);
474
- });
475
- }
476
- async function upload(file_data, root_url, upload_id, max_file_size, upload_fn = upload_files) {
438
+ async function upload(file_data, root_url, upload_id, max_file_size) {
477
439
  let files = (Array.isArray(file_data) ? file_data : [file_data]).map(
478
440
  (file_data2) => file_data2.blob
479
441
  );
@@ -486,7 +448,7 @@ async function upload(file_data, root_url, upload_id, max_file_size, upload_fn =
486
448
  );
487
449
  }
488
450
  return await Promise.all(
489
- await upload_fn(root_url, files, upload_id).then(
451
+ await this.upload_files(root_url, files, upload_id).then(
490
452
  async (response) => {
491
453
  if (response.error) {
492
454
  throw new Error(response.error);
@@ -549,6 +511,95 @@ class FileData {
549
511
  this.alt_text = alt_text;
550
512
  }
551
513
  }
514
+ function update_object(object, newValue, stack) {
515
+ while (stack.length > 1) {
516
+ const key2 = stack.shift();
517
+ if (typeof key2 === "string" || typeof key2 === "number") {
518
+ object = object[key2];
519
+ } else {
520
+ throw new Error("Invalid key type");
521
+ }
522
+ }
523
+ const key = stack.shift();
524
+ if (typeof key === "string" || typeof key === "number") {
525
+ object[key] = newValue;
526
+ } else {
527
+ throw new Error("Invalid key type");
528
+ }
529
+ }
530
+ async function walk_and_store_blobs(data, type = void 0, path = [], root = false, endpoint_info = void 0) {
531
+ if (Array.isArray(data)) {
532
+ let blob_refs = [];
533
+ await Promise.all(
534
+ data.map(async (item) => {
535
+ var _a;
536
+ let new_path = path.slice();
537
+ new_path.push(item);
538
+ const array_refs = await walk_and_store_blobs(
539
+ data[item],
540
+ root ? ((_a = endpoint_info == null ? void 0 : endpoint_info.parameters[item]) == null ? void 0 : _a.component) || void 0 : type,
541
+ new_path,
542
+ false,
543
+ endpoint_info
544
+ );
545
+ blob_refs = blob_refs.concat(array_refs);
546
+ })
547
+ );
548
+ return blob_refs;
549
+ } else if (globalThis.Buffer && data instanceof globalThis.Buffer || data instanceof Blob) {
550
+ const is_image = type === "Image";
551
+ return [
552
+ {
553
+ path,
554
+ blob: is_image ? false : new NodeBlob([data]),
555
+ type
556
+ }
557
+ ];
558
+ } else if (typeof data === "object" && data !== null) {
559
+ let blob_refs = [];
560
+ for (const key of Object.keys(data)) {
561
+ const new_path = [...path, key];
562
+ const value = data[key];
563
+ blob_refs = blob_refs.concat(
564
+ await walk_and_store_blobs(
565
+ value,
566
+ void 0,
567
+ new_path,
568
+ false,
569
+ endpoint_info
570
+ )
571
+ );
572
+ }
573
+ if (!blob_refs.length && !(data instanceof Blob || data instanceof ArrayBuffer || data instanceof Uint8Array)) {
574
+ return [
575
+ {
576
+ path,
577
+ blob: new NodeBlob([JSON.stringify(data)]),
578
+ type: typeof data
579
+ }
580
+ ];
581
+ }
582
+ return blob_refs;
583
+ }
584
+ return [];
585
+ }
586
+ function skip_queue(id, config) {
587
+ var _a, _b;
588
+ if (((_b = (_a = config == null ? void 0 : config.dependencies) == null ? void 0 : _a[id]) == null ? void 0 : _b.queue) !== null) {
589
+ return !config.dependencies[id].queue;
590
+ }
591
+ return !config.enable_queue;
592
+ }
593
+ function post_message(message, origin) {
594
+ return new Promise((res, _rej) => {
595
+ const channel = new MessageChannel();
596
+ channel.port1.onmessage = ({ data }) => {
597
+ channel.port1.close();
598
+ res(data);
599
+ };
600
+ window.parent.postMessage(message, origin, [channel.port2]);
601
+ });
602
+ }
552
603
  async function handle_blob(endpoint, data, api_info) {
553
604
  const self = this;
554
605
  const blobRefs = await walk_and_store_blobs(
@@ -568,7 +619,7 @@ async function handle_blob(endpoint, data, api_info) {
568
619
  path,
569
620
  file_url,
570
621
  type,
571
- name: blob == null ? void 0 : blob.name
622
+ name: blob instanceof File ? blob == null ? void 0 : blob.name : void 0
572
623
  };
573
624
  })
574
625
  );
@@ -588,7 +639,7 @@ async function post_data(url, body, additional_headers) {
588
639
  headers.Authorization = `Bearer ${this.options.hf_token}`;
589
640
  }
590
641
  try {
591
- var response = await this.fetch_implementation(url, {
642
+ var response = await this.fetch(url, {
592
643
  method: "POST",
593
644
  body: JSON.stringify(body),
594
645
  headers: { ...headers, ...additional_headers }
@@ -626,7 +677,7 @@ async function predict(endpoint, data) {
626
677
  );
627
678
  }
628
679
  return new Promise(async (resolve, reject) => {
629
- const app = this.submit(endpoint, data || []);
680
+ const app = this.submit(endpoint, data);
630
681
  let result;
631
682
  app.on("data", (d) => {
632
683
  if (status_complete) {
@@ -663,7 +714,7 @@ async function check_space_status(id, type, status_callback) {
663
714
  status_callback({
664
715
  status: "error",
665
716
  load_status: "error",
666
- message: "Could not get space status",
717
+ message: SPACE_STATUS_ERROR_MSG,
667
718
  detail: "NOT_FOUND"
668
719
  });
669
720
  return;
@@ -751,7 +802,7 @@ async function get_space_hardware(space_id, hf_token) {
751
802
  }
752
803
  try {
753
804
  const res = await fetch(
754
- `https://huggingface.co/api/spaces/${space_id}/runtime`,
805
+ `https://huggingface.co/api/spaces/${space_id}/${RUNTIME_URL}`,
755
806
  { headers }
756
807
  );
757
808
  if (res.status !== 200)
@@ -772,7 +823,7 @@ async function set_space_timeout(space_id, timeout, hf_token) {
772
823
  };
773
824
  try {
774
825
  const res = await fetch(
775
- `https://huggingface.co/api/spaces/${space_id}/sleeptime`,
826
+ `https://huggingface.co/api/spaces/${space_id}/${SLEEPTIME_URL}`,
776
827
  {
777
828
  method: "POST",
778
829
  headers: { "Content-Type": "application/json", ...headers },
@@ -827,8 +878,12 @@ async function duplicate(app_reference, options) {
827
878
  body.private = true;
828
879
  }
829
880
  let original_hardware;
830
- if (!hardware) {
831
- original_hardware = await get_space_hardware(app_reference, hf_token);
881
+ try {
882
+ if (!hardware) {
883
+ original_hardware = await get_space_hardware(app_reference, hf_token);
884
+ }
885
+ } catch (e) {
886
+ throw Error(SPACE_METADATA_ERROR_MSG + e.message);
832
887
  }
833
888
  const requested_hardware = hardware || original_hardware || "cpu-basic";
834
889
  body.hardware = requested_hardware;
@@ -854,58 +909,73 @@ async function duplicate(app_reference, options) {
854
909
  }
855
910
  const duplicated_space = await response.json();
856
911
  await set_space_timeout(`${user}/${space_name}`, timeout || 300, hf_token);
857
- return await Client.connect(duplicated_space.url, options);
912
+ return await Client.connect(
913
+ get_space_reference(duplicated_space.url),
914
+ options
915
+ );
858
916
  } catch (e) {
859
917
  throw new Error(e);
860
918
  }
861
919
  }
862
- function open_stream() {
920
+ function get_space_reference(url) {
921
+ const regex = /https:\/\/huggingface.co\/spaces\/([^/]+\/[^/]+)/;
922
+ const match = url.match(regex);
923
+ if (match) {
924
+ return match[1];
925
+ }
926
+ }
927
+ async function open_stream() {
863
928
  let {
864
929
  event_callbacks,
865
930
  unclosed_events,
866
931
  pending_stream_messages,
867
932
  stream_status,
868
- config
933
+ config,
934
+ jwt
869
935
  } = this;
870
936
  if (!config) {
871
937
  throw new Error("Could not resolve app config");
872
938
  }
873
939
  stream_status.open = true;
874
- let event_source = null;
940
+ let stream = null;
875
941
  let params = new URLSearchParams({
876
942
  session_hash: this.session_hash
877
943
  }).toString();
878
944
  let url = new URL(`${config.root}/queue/data?${params}`);
879
- event_source = this.eventSource_factory(url);
880
- if (!event_source) {
881
- throw new Error("Cannot connect to sse endpoint: " + url.toString());
945
+ if (jwt) {
946
+ url.searchParams.set("__sign", jwt);
947
+ }
948
+ stream = await this.stream(url);
949
+ if (!stream) {
950
+ console.warn("Cannot connect to SSE endpoint: " + url.toString());
951
+ return;
882
952
  }
883
- event_source.onmessage = async function(event) {
953
+ stream.onmessage = async function(event) {
884
954
  let _data = JSON.parse(event.data);
885
955
  if (_data.msg === "close_stream") {
886
- close_stream(stream_status, event_source);
956
+ close_stream(stream_status, stream);
887
957
  return;
888
958
  }
889
959
  const event_id = _data.event_id;
890
960
  if (!event_id) {
891
961
  await Promise.all(
892
962
  Object.keys(event_callbacks).map(
893
- (event_id2) => (
894
- // @ts-ignore
895
- event_callbacks[event_id2](_data)
896
- )
897
- // todo: check event_callbacks
963
+ (event_id2) => event_callbacks[event_id2](_data)
898
964
  )
899
965
  );
900
966
  } else if (event_callbacks[event_id] && config) {
901
967
  if (_data.msg === "process_completed" && ["sse", "sse_v1", "sse_v2", "sse_v2.1"].includes(config.protocol)) {
902
968
  unclosed_events.delete(event_id);
903
969
  if (unclosed_events.size === 0) {
904
- close_stream(stream_status, event_source);
970
+ close_stream(stream_status, stream);
905
971
  }
906
972
  }
907
973
  let fn2 = event_callbacks[event_id];
908
- window.setTimeout(fn2, 0, _data);
974
+ if (typeof window !== "undefined") {
975
+ window.setTimeout(fn2, 0, _data);
976
+ } else {
977
+ setImmediate(fn2, _data);
978
+ }
909
979
  } else {
910
980
  if (!pending_stream_messages[event_id]) {
911
981
  pending_stream_messages[event_id] = [];
@@ -913,25 +983,22 @@ function open_stream() {
913
983
  pending_stream_messages[event_id].push(_data);
914
984
  }
915
985
  };
916
- event_source.onerror = async function() {
986
+ stream.onerror = async function() {
917
987
  await Promise.all(
918
988
  Object.keys(event_callbacks).map(
919
- (event_id) => (
920
- // @ts-ignore
921
- event_callbacks[event_id]({
922
- msg: "unexpected_error",
923
- message: BROKEN_CONNECTION_MSG
924
- })
925
- )
989
+ (event_id) => event_callbacks[event_id]({
990
+ msg: "unexpected_error",
991
+ message: BROKEN_CONNECTION_MSG
992
+ })
926
993
  )
927
994
  );
928
- close_stream(stream_status, event_source);
995
+ close_stream(stream_status, stream);
929
996
  };
930
997
  }
931
- function close_stream(stream_status, event_source) {
932
- if (stream_status && event_source) {
998
+ function close_stream(stream_status, stream) {
999
+ if (stream_status && stream) {
933
1000
  stream_status.open = false;
934
- event_source == null ? void 0 : event_source.close();
1001
+ stream == null ? void 0 : stream.close();
935
1002
  }
936
1003
  }
937
1004
  function apply_diff_stream(pending_diff_streams, event_id, data) {
@@ -1023,7 +1090,7 @@ function submit(endpoint, data, event_data, trigger_id) {
1023
1090
  };
1024
1091
  const { hf_token } = this.options;
1025
1092
  const {
1026
- fetch_implementation,
1093
+ fetch: fetch2,
1027
1094
  app_reference,
1028
1095
  config,
1029
1096
  session_hash,
@@ -1046,8 +1113,9 @@ function submit(endpoint, data, event_data, trigger_id) {
1046
1113
  api_map,
1047
1114
  config
1048
1115
  );
1116
+ let resolved_data = map_data_to_params(data, api_info);
1049
1117
  let websocket;
1050
- let event_source;
1118
+ let stream;
1051
1119
  let protocol = config.protocol ?? "ws";
1052
1120
  const _endpoint = typeof endpoint === "number" ? "/predict" : endpoint;
1053
1121
  let payload;
@@ -1080,14 +1148,14 @@ function submit(endpoint, data, event_data, trigger_id) {
1080
1148
  }
1081
1149
  cancel_request = { fn_index, session_hash };
1082
1150
  } else {
1083
- event_source == null ? void 0 : event_source.close();
1151
+ stream == null ? void 0 : stream.close();
1084
1152
  cancel_request = { event_id };
1085
1153
  }
1086
1154
  try {
1087
1155
  if (!config) {
1088
1156
  throw new Error("Could not resolve app config");
1089
1157
  }
1090
- await fetch_implementation(`${config.root}/reset`, {
1158
+ await fetch2(`${config.root}/reset`, {
1091
1159
  headers: { "Content-Type": "application/json" },
1092
1160
  method: "POST",
1093
1161
  body: JSON.stringify(cancel_request)
@@ -1098,8 +1166,9 @@ function submit(endpoint, data, event_data, trigger_id) {
1098
1166
  );
1099
1167
  }
1100
1168
  }
1101
- this.handle_blob(`${config.root}`, data, endpoint_info).then(
1169
+ this.handle_blob(config.root, resolved_data, endpoint_info).then(
1102
1170
  async (_payload) => {
1171
+ var _a;
1103
1172
  payload = {
1104
1173
  data: _payload || [],
1105
1174
  event_data,
@@ -1291,13 +1360,16 @@ function submit(endpoint, data, event_data, trigger_id) {
1291
1360
  let url = new URL(
1292
1361
  `${config.root}/queue/join?${url_params ? url_params + "&" : ""}${params}`
1293
1362
  );
1294
- event_source = this.eventSource_factory(url);
1295
- if (!event_source) {
1296
- throw new Error(
1297
- "Cannot connect to sse endpoint: " + url.toString()
1363
+ if (this.jwt) {
1364
+ url.searchParams.set("__sign", this.jwt);
1365
+ }
1366
+ stream = await this.stream(url);
1367
+ if (!stream) {
1368
+ return Promise.reject(
1369
+ new Error("Cannot connect to SSE endpoint: " + url.toString())
1298
1370
  );
1299
1371
  }
1300
- event_source.onmessage = async function(event) {
1372
+ stream.onmessage = async function(event) {
1301
1373
  const _data = JSON.parse(event.data);
1302
1374
  const { type, status, data: data2 } = handle_message(
1303
1375
  _data,
@@ -1312,7 +1384,7 @@ function submit(endpoint, data, event_data, trigger_id) {
1312
1384
  ...status
1313
1385
  });
1314
1386
  if (status.stage === "error") {
1315
- event_source == null ? void 0 : event_source.close();
1387
+ stream == null ? void 0 : stream.close();
1316
1388
  }
1317
1389
  } else if (type === "data") {
1318
1390
  event_id = _data.event_id;
@@ -1331,7 +1403,7 @@ function submit(endpoint, data, event_data, trigger_id) {
1331
1403
  fn_index,
1332
1404
  time: /* @__PURE__ */ new Date()
1333
1405
  });
1334
- event_source == null ? void 0 : event_source.close();
1406
+ stream == null ? void 0 : stream.close();
1335
1407
  }
1336
1408
  } else if (type === "complete") {
1337
1409
  complete = status;
@@ -1374,7 +1446,7 @@ function submit(endpoint, data, event_data, trigger_id) {
1374
1446
  endpoint: _endpoint,
1375
1447
  fn_index
1376
1448
  });
1377
- event_source == null ? void 0 : event_source.close();
1449
+ stream == null ? void 0 : stream.close();
1378
1450
  }
1379
1451
  }
1380
1452
  };
@@ -1387,7 +1459,10 @@ function submit(endpoint, data, event_data, trigger_id) {
1387
1459
  fn_index,
1388
1460
  time: /* @__PURE__ */ new Date()
1389
1461
  });
1390
- let hostname = window.location.hostname;
1462
+ let hostname = "";
1463
+ if (typeof window !== "undefined") {
1464
+ hostname = (_a = window == null ? void 0 : window.location) == null ? void 0 : _a.hostname;
1465
+ }
1391
1466
  let hfhubdev = "dev.spaces.huggingface.tech";
1392
1467
  const origin = hostname.includes(".dev.") ? `https://moon-${hostname.split(".")[1]}.${hfhubdev}` : `https://huggingface.co`;
1393
1468
  const zerogpu_auth_promise = dependency.zerogpu && window.parent != window && config.space_id ? post_message("zerogpu-headers", origin) : Promise.resolve(null);
@@ -1401,7 +1476,7 @@ function submit(endpoint, data, event_data, trigger_id) {
1401
1476
  headers
1402
1477
  );
1403
1478
  });
1404
- post_data_promise.then(([response, status]) => {
1479
+ post_data_promise.then(async ([response, status]) => {
1405
1480
  if (status === 503) {
1406
1481
  fire_event({
1407
1482
  type: "status",
@@ -1485,6 +1560,14 @@ function submit(endpoint, data, event_data, trigger_id) {
1485
1560
  endpoint: _endpoint,
1486
1561
  fn_index
1487
1562
  });
1563
+ if (data2.render_config) {
1564
+ fire_event({
1565
+ type: "render",
1566
+ data: data2.render_config,
1567
+ endpoint: _endpoint,
1568
+ fn_index
1569
+ });
1570
+ }
1488
1571
  if (complete) {
1489
1572
  fire_event({
1490
1573
  type: "status",
@@ -1517,7 +1600,7 @@ function submit(endpoint, data, event_data, trigger_id) {
1517
1600
  time: /* @__PURE__ */ new Date()
1518
1601
  });
1519
1602
  if (["sse_v2", "sse_v2.1"].includes(protocol)) {
1520
- close_stream(stream_status, event_source);
1603
+ close_stream(stream_status, stream);
1521
1604
  stream_status.open = false;
1522
1605
  }
1523
1606
  }
@@ -1531,7 +1614,7 @@ function submit(endpoint, data, event_data, trigger_id) {
1531
1614
  event_callbacks[event_id] = callback;
1532
1615
  unclosed_events.add(event_id);
1533
1616
  if (!stream_status.open) {
1534
- this.open_stream();
1617
+ await this.open_stream();
1535
1618
  }
1536
1619
  }
1537
1620
  });
@@ -1589,6 +1672,7 @@ class Client {
1589
1672
  __publicField(this, "heartbeat_event", null);
1590
1673
  __publicField(this, "view_api");
1591
1674
  __publicField(this, "upload_files");
1675
+ __publicField(this, "upload");
1592
1676
  __publicField(this, "handle_blob");
1593
1677
  __publicField(this, "post_data");
1594
1678
  __publicField(this, "submit");
@@ -1605,15 +1689,23 @@ class Client {
1605
1689
  this.predict = predict.bind(this);
1606
1690
  this.open_stream = open_stream.bind(this);
1607
1691
  this.resolve_config = resolve_config.bind(this);
1692
+ this.upload = upload.bind(this);
1608
1693
  }
1609
- fetch_implementation(input, init) {
1694
+ fetch(input, init) {
1610
1695
  return fetch(input, init);
1611
1696
  }
1612
- eventSource_factory(url) {
1613
- if (typeof window !== void 0 && typeof EventSource !== "undefined") {
1697
+ async stream(url) {
1698
+ if (typeof window === "undefined" || typeof EventSource === "undefined") {
1699
+ try {
1700
+ const EventSourceModule = await import("eventsource");
1701
+ return new EventSourceModule.default(url.toString());
1702
+ } catch (error) {
1703
+ console.error("Failed to load EventSource module:", error);
1704
+ throw error;
1705
+ }
1706
+ } else {
1614
1707
  return new EventSource(url.toString());
1615
1708
  }
1616
- return null;
1617
1709
  }
1618
1710
  async init() {
1619
1711
  var _a;
@@ -1626,11 +1718,11 @@ class Client {
1626
1718
  await this._resolve_config().then(async ({ config }) => {
1627
1719
  if (config) {
1628
1720
  this.config = config;
1629
- if (this.config) {
1721
+ if (this.config && this.config.connect_heartbeat) {
1630
1722
  const heartbeat_url = new URL(
1631
1723
  `${this.config.root}/heartbeat/${this.session_hash}`
1632
1724
  );
1633
- this.heartbeat_event = this.eventSource_factory(heartbeat_url);
1725
+ this.heartbeat_event = await this.stream(heartbeat_url);
1634
1726
  if (this.config.space_id && this.options.hf_token) {
1635
1727
  this.jwt = await get_jwt(
1636
1728
  this.config.space_id,
@@ -1641,7 +1733,7 @@ class Client {
1641
1733
  }
1642
1734
  });
1643
1735
  } catch (e) {
1644
- throw Error(`Could not resolve config: ${e}`);
1736
+ throw Error(CONFIG_ERROR_MSG + e.message);
1645
1737
  }
1646
1738
  this.api_info = await this.view_api();
1647
1739
  this.api_map = map_names_to_ids(((_a = this.config) == null ? void 0 : _a.dependencies) || []);
@@ -1668,7 +1760,7 @@ class Client {
1668
1760
  try {
1669
1761
  config = await this.resolve_config(`${http_protocol}//${host}`);
1670
1762
  if (!config) {
1671
- throw new Error("Could not resolve app config");
1763
+ throw new Error(CONFIG_ERROR_MSG);
1672
1764
  }
1673
1765
  return this.config_success(config);
1674
1766
  } catch (e) {
@@ -1703,7 +1795,7 @@ class Client {
1703
1795
  try {
1704
1796
  this.api_info = await this.view_api();
1705
1797
  } catch (e) {
1706
- console.error(`Could not get API details: ${e.message}`);
1798
+ console.error(API_INFO_ERROR_MSG + e.message);
1707
1799
  }
1708
1800
  return this.prepare_return_obj();
1709
1801
  }
@@ -1715,7 +1807,7 @@ class Client {
1715
1807
  try {
1716
1808
  this.config = await this._resolve_config();
1717
1809
  if (!this.config) {
1718
- throw new Error("Could not resolve app config");
1810
+ throw new Error(CONFIG_ERROR_MSG);
1719
1811
  }
1720
1812
  const _config = await this.config_success(this.config);
1721
1813
  return _config;
@@ -1735,7 +1827,7 @@ class Client {
1735
1827
  async component_server(component_id, fn_name, data) {
1736
1828
  var _a;
1737
1829
  if (!this.config) {
1738
- throw new Error("Could not resolve app config");
1830
+ throw new Error(CONFIG_ERROR_MSG);
1739
1831
  }
1740
1832
  const headers = {};
1741
1833
  const { hf_token } = this.options;
@@ -1776,14 +1868,11 @@ class Client {
1776
1868
  headers.Authorization = `Bearer ${hf_token}`;
1777
1869
  }
1778
1870
  try {
1779
- const response = await this.fetch_implementation(
1780
- `${root_url}/component_server/`,
1781
- {
1782
- method: "POST",
1783
- body,
1784
- headers
1785
- }
1786
- );
1871
+ const response = await this.fetch(`${root_url}/component_server/`, {
1872
+ method: "POST",
1873
+ body,
1874
+ headers
1875
+ });
1787
1876
  if (!response.ok) {
1788
1877
  throw new Error(
1789
1878
  "Could not connect to component server: " + response.statusText
@@ -1808,11 +1897,14 @@ class Client {
1808
1897
  async function client(app_reference, options = {}) {
1809
1898
  return await Client.connect(app_reference, options);
1810
1899
  }
1900
+ async function duplicate_space(app_reference, options) {
1901
+ return await Client.duplicate(app_reference, options);
1902
+ }
1811
1903
  export {
1812
1904
  Client,
1813
1905
  FileData,
1814
1906
  client,
1815
- duplicate,
1907
+ duplicate_space as duplicate,
1816
1908
  predict,
1817
1909
  prepare_files,
1818
1910
  submit,