@gradio/client 2.3.0 → 2.4.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 (46) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +4 -2
  3. package/dist/__vite-browser-external-Cgmn0awE.js +7 -0
  4. package/dist/browser.js +1672 -1902
  5. package/dist/client.d.ts +5 -0
  6. package/dist/client.d.ts.map +1 -1
  7. package/dist/constants.d.ts +4 -0
  8. package/dist/constants.d.ts.map +1 -1
  9. package/dist/helpers/api_info.d.ts.map +1 -1
  10. package/dist/helpers/data.d.ts.map +1 -1
  11. package/dist/helpers/init_helpers.d.ts +12 -3
  12. package/dist/helpers/init_helpers.d.ts.map +1 -1
  13. package/dist/index.cjs +2274 -0
  14. package/dist/index.js +2155 -2449
  15. package/dist/index.min.js +1735 -0
  16. package/dist/types.d.ts +16 -0
  17. package/dist/types.d.ts.map +1 -1
  18. package/dist/utils/duplicate.d.ts.map +1 -1
  19. package/dist/utils/predict.d.ts.map +1 -1
  20. package/dist/utils/stream.d.ts.map +1 -1
  21. package/dist/utils/submit.d.ts.map +1 -1
  22. package/dist/utils/view_api.d.ts.map +1 -1
  23. package/package.json +11 -4
  24. package/scripts/verify_dist.mjs +46 -0
  25. package/src/client.ts +46 -7
  26. package/src/constants.ts +10 -0
  27. package/src/helpers/api_info.ts +47 -19
  28. package/src/helpers/data.ts +8 -3
  29. package/src/helpers/init_helpers.ts +61 -14
  30. package/src/test/api_info.test.ts +105 -12
  31. package/src/test/data.test.ts +26 -3
  32. package/src/test/init.test.ts +21 -3
  33. package/src/test/init_helpers.test.ts +94 -1
  34. package/src/test/post_data.test.ts +21 -0
  35. package/src/test/refresh.test.ts +31 -0
  36. package/src/test/submit.test.ts +14 -0
  37. package/src/types.ts +16 -0
  38. package/src/utils/duplicate.ts +5 -1
  39. package/src/utils/post_data.ts +1 -1
  40. package/src/utils/predict.ts +34 -19
  41. package/src/utils/stream.ts +17 -4
  42. package/src/utils/submit.ts +43 -10
  43. package/src/utils/upload_files.ts +1 -1
  44. package/src/utils/view_api.ts +2 -3
  45. package/vite.config.ts +20 -4
  46. package/dist/__vite-browser-external-DYxpcVy9.js +0 -4
package/dist/index.js CHANGED
@@ -1,2557 +1,2263 @@
1
- const HOST_URL = `host`;
2
- const SSE_URL = `queue/data`;
3
- const SSE_DATA_URL = `queue/join`;
4
- const UPLOAD_URL = `upload`;
5
- const LOGIN_URL = `login`;
6
- const CONFIG_URL = `config`;
7
- const API_INFO_URL = `info`;
8
- const RUNTIME_URL = `runtime`;
9
- const SLEEPTIME_URL = `sleeptime`;
10
- const HEARTBEAT_URL = `heartbeat`;
11
- const COMPONENT_SERVER_URL = `component_server`;
12
- const RESET_URL = `reset`;
13
- const CANCEL_URL = `cancel`;
14
- const APP_ID_URL = `app_id`;
15
- const QUEUE_FULL_MSG = "This application is currently busy. Please try again. ";
16
- const BROKEN_CONNECTION_MSG = "Connection errored out. ";
17
- const CONFIG_ERROR_MSG = "Could not resolve app config. ";
18
- const SPACE_STATUS_ERROR_MSG = "Could not get space status. ";
19
- const API_INFO_ERROR_MSG = "Could not get API info. ";
20
- const SPACE_METADATA_ERROR_MSG = "Space metadata could not be loaded. ";
21
- const INVALID_URL_MSG = "Invalid URL. A full URL path is required.";
22
- const UNAUTHORIZED_MSG = "Not authorized to access this space. ";
23
- const INVALID_CREDENTIALS_MSG = "Invalid credentials. Could not login. ";
24
- const MISSING_CREDENTIALS_MSG = "Login credentials are required to access this space.";
25
- const NODEJS_FS_ERROR_MSG = "File system access is only available in Node.js environments";
26
- const ROOT_URL_ERROR_MSG = "Root URL not found in client config";
27
- const FILE_PROCESSING_ERROR_MSG = "Error uploading file";
1
+ //#region src/constants.ts
2
+ var HOST_URL = `host`;
3
+ var SSE_URL = `queue/data`;
4
+ var SSE_DATA_URL = `queue/join`;
5
+ var UPLOAD_URL = `upload`;
6
+ var LOGIN_URL = `login`;
7
+ var CONFIG_URL = `config`;
8
+ var API_INFO_URL = `info`;
9
+ var RUNTIME_URL = `runtime`;
10
+ var SLEEPTIME_URL = `sleeptime`;
11
+ var HEARTBEAT_URL = `heartbeat`;
12
+ var COMPONENT_SERVER_URL = `component_server`;
13
+ var RESET_URL = `reset`;
14
+ var CANCEL_URL = `cancel`;
15
+ var APP_ID_URL = `app_id`;
16
+ var QUEUE_FULL_MSG = "This application is currently busy. Please try again. ";
17
+ var BROKEN_CONNECTION_MSG = "Connection errored out. ";
18
+ var CONFIG_ERROR_MSG = "Could not resolve app config. ";
19
+ var SPACE_STATUS_ERROR_MSG = "Could not get space status. ";
20
+ var API_INFO_ERROR_MSG = "Could not get API info. ";
21
+ var SPACE_METADATA_ERROR_MSG = "Space metadata could not be loaded. ";
22
+ var INVALID_URL_MSG = "Invalid URL. A full URL path is required.";
23
+ var UNAUTHORIZED_MSG = "Not authorized to access this space. ";
24
+ var INVALID_CREDENTIALS_MSG = "Invalid credentials. Could not login. ";
25
+ var MISSING_CREDENTIALS_MSG = "Login credentials are required to access this space.";
26
+ var PRIVATE_SPACE_MSG = "Could not access this app (received a 401 response). If it is a private Hugging Face Space, pass a valid Hugging Face token to the `token` option of `Client.connect`. You can generate a token at https://huggingface.co/settings/tokens.";
27
+ var SPACE_NOT_FOUND_MSG = (space, status) => `Space "${space}" could not be accessed (received a ${status} response from the Hugging Face API). Check that the Space name is spelled correctly and that the Space exists. If the Space is private, pass a valid Hugging Face token to the \`token\` option of \`Client.connect\`. You can generate a token at https://huggingface.co/settings/tokens.`;
28
+ var NO_API_INFO_MSG = "No API information is available for this app. This can happen when the app's `/info` endpoint cannot be reached, or when the app is running a legacy version of Gradio that is not supported by this client. ";
29
+ var WS_PROTOCOL_MSG = "This app appears to be running a legacy version of Gradio (3.x or earlier) that communicates over WebSockets, which is not supported by this version of @gradio/client. Please upgrade the app to a newer version of Gradio, or connect to it with @gradio/client version 0.x.";
30
+ var NODEJS_FS_ERROR_MSG = "File system access is only available in Node.js environments";
31
+ var ROOT_URL_ERROR_MSG = "Root URL not found in client config";
32
+ var FILE_PROCESSING_ERROR_MSG = "Error uploading file";
33
+ //#endregion
34
+ //#region src/helpers/init_helpers.ts
28
35
  async function get_jwt(space, token, cookies) {
29
- try {
30
- const r = await fetch(`https://huggingface.co/api/spaces/${space}/jwt`, {
31
- headers: {
32
- Authorization: `Bearer ${token}`,
33
- ...cookies ? { Cookie: cookies } : {}
34
- }
35
- });
36
- const jwt = (await r.json()).token;
37
- return jwt || false;
38
- } catch (e) {
39
- return false;
40
- }
36
+ try {
37
+ return (await (await fetch(`https://huggingface.co/api/spaces/${space}/jwt`, { headers: {
38
+ Authorization: `Bearer ${token}`,
39
+ ...cookies ? { Cookie: cookies } : {}
40
+ } })).json()).token || false;
41
+ } catch (e) {
42
+ return false;
43
+ }
44
+ }
45
+ /**
46
+ * The `hf_token` option was renamed to `token`, but a lot of existing code
47
+ * (and the Python client) still uses `hf_token`. Accept it as an alias so
48
+ * that authenticated requests are not silently sent without credentials,
49
+ * which previously surfaced as "Could not resolve app config" errors when
50
+ * connecting to private Spaces.
51
+ */
52
+ function normalise_token_option(options) {
53
+ if (options.hf_token && !options.token) {
54
+ options.token = options.hf_token;
55
+ console.warn("The `hf_token` option has been renamed to `token`. Support for `hf_token` will be removed in a future version of @gradio/client.");
56
+ }
41
57
  }
42
58
  function map_names_to_ids(fns) {
43
- let apis = {};
44
- fns.forEach(({ api_name, id }) => {
45
- if (api_name) apis[api_name] = id;
46
- });
47
- return apis;
59
+ let apis = {};
60
+ fns.forEach(({ api_name, id }) => {
61
+ if (api_name) apis[api_name] = id;
62
+ });
63
+ return apis;
64
+ }
65
+ function resolve_config_root(root, current_location) {
66
+ const root_url = new URL(root, current_location);
67
+ const current_url = new URL(current_location);
68
+ if (root_url.hostname !== current_url.hostname) return root;
69
+ root_url.protocol = current_url.protocol;
70
+ root_url.host = current_url.host;
71
+ return root_url.toString().replace(/\/$/, "");
48
72
  }
49
- async function resolve_config(endpoint) {
50
- const headers = this.options.token ? { Authorization: `Bearer ${this.options.token}` } : {};
51
- headers["Content-Type"] = "application/json";
52
- if (typeof window !== "undefined" && window.gradio_config && location.origin !== "http://localhost:9876") {
53
- if (window.gradio_config.current_page) {
54
- endpoint = endpoint.substring(0, endpoint.lastIndexOf("/"));
55
- }
56
- if (window.gradio_config.dev_mode || typeof window !== "undefined" && window?.BUILD_MODE === "dev") {
57
- let config_url = join_urls(
58
- endpoint,
59
- this.deep_link ? CONFIG_URL + "?deep_link=" + this.deep_link : CONFIG_URL
60
- );
61
- const response = await this.fetch(config_url, {
62
- headers,
63
- credentials: "include"
64
- });
65
- const config = await handleConfigResponse(response, !!this.options.auth);
66
- config.root = endpoint || config.root;
67
- window.gradio_config = {
68
- ...config,
69
- current_page: window.gradio_config.current_page
70
- };
71
- }
72
- return { ...window.gradio_config };
73
- } else if (endpoint) {
74
- let config_url = join_urls(
75
- endpoint,
76
- this.deep_link ? CONFIG_URL + "?deep_link=" + this.deep_link : CONFIG_URL
77
- );
78
- const response = await this.fetch(config_url, {
79
- headers,
80
- credentials: "include"
81
- });
82
- const config = await handleConfigResponse(response, !!this.options.auth);
83
- if (!config.root) {
84
- config.root = endpoint;
85
- }
86
- return config;
87
- }
88
- throw new Error(CONFIG_ERROR_MSG);
73
+ async function resolve_config(endpoint, strip_current_page = true) {
74
+ const headers = this.options.token ? { Authorization: `Bearer ${this.options.token}` } : {};
75
+ if (typeof window !== "undefined" && window.gradio_config && location.origin !== "http://localhost:9876") {
76
+ if (strip_current_page && window.gradio_config.current_page) endpoint = endpoint.substring(0, endpoint.lastIndexOf("/"));
77
+ if (window.gradio_config.dev_mode || typeof window !== "undefined" && window?.BUILD_MODE === "dev") {
78
+ let config_url = join_urls(endpoint, this.deep_link ? CONFIG_URL + "?deep_link=" + this.deep_link : CONFIG_URL);
79
+ const config = await handleConfigResponse(await this.fetch(config_url, {
80
+ headers,
81
+ credentials: this.options.credentials ?? "same-origin"
82
+ }), !!this.options.auth);
83
+ config.root = endpoint || config.root;
84
+ window.gradio_config = {
85
+ ...config,
86
+ current_page: window.gradio_config.current_page
87
+ };
88
+ }
89
+ const config = { ...window.gradio_config };
90
+ config.root = resolve_config_root(config.root, location.href);
91
+ return config;
92
+ } else if (endpoint) {
93
+ let config_url = join_urls(endpoint, this.deep_link ? CONFIG_URL + "?deep_link=" + this.deep_link : CONFIG_URL);
94
+ const config = await handleConfigResponse(await this.fetch(config_url, {
95
+ headers,
96
+ credentials: this.options.credentials ?? "same-origin"
97
+ }), !!this.options.auth);
98
+ if (!config.root) config.root = endpoint;
99
+ return config;
100
+ }
101
+ throw new Error(CONFIG_ERROR_MSG);
89
102
  }
90
103
  async function handleConfigResponse(response, authorized) {
91
- if (response?.status === 401 && !authorized) {
92
- const error_data = await response.json();
93
- const auth_message = error_data?.detail?.auth_message;
94
- throw new Error(auth_message || MISSING_CREDENTIALS_MSG);
95
- } else if (response?.status === 401 && authorized) {
96
- throw new Error(INVALID_CREDENTIALS_MSG);
97
- }
98
- if (response?.status === 200) {
99
- let config = await response.json();
100
- config.dependencies?.forEach((dep, i) => {
101
- if (dep.id === void 0) {
102
- dep.id = i;
103
- }
104
- });
105
- return config;
106
- } else if (response?.status === 401) {
107
- throw new Error(UNAUTHORIZED_MSG);
108
- }
109
- throw new Error(CONFIG_ERROR_MSG);
104
+ if (response?.status === 401 && !authorized) {
105
+ let error_data = null;
106
+ try {
107
+ error_data = await response.json();
108
+ } catch (e) {
109
+ throw new Error(PRIVATE_SPACE_MSG);
110
+ }
111
+ const auth_message = error_data?.detail?.auth_message;
112
+ throw new Error(auth_message || "Login credentials are required to access this space.");
113
+ } else if (response?.status === 401 && authorized) throw new Error(INVALID_CREDENTIALS_MSG);
114
+ if (response?.status === 200) {
115
+ let config = await response.json();
116
+ config.dependencies?.forEach((dep, i) => {
117
+ if (dep.id === void 0) dep.id = i;
118
+ });
119
+ return config;
120
+ } else if (response?.status === 401) throw new Error(UNAUTHORIZED_MSG);
121
+ throw new Error(`${CONFIG_ERROR_MSG}(received status ${response?.status} when fetching the app config)`);
110
122
  }
111
123
  async function resolve_cookies() {
112
- const { http_protocol, host } = await process_endpoint(
113
- this.app_reference,
114
- this.options.token
115
- );
116
- try {
117
- if (this.options.auth) {
118
- const cookie_header = await get_cookie_header(
119
- http_protocol,
120
- host,
121
- this.options.auth,
122
- this.fetch,
123
- this.options.token
124
- );
125
- if (cookie_header) this.set_cookies(cookie_header);
126
- }
127
- } catch (e) {
128
- throw Error(e.message);
129
- }
124
+ const { http_protocol, host } = await process_endpoint(this.app_reference, this.options.token);
125
+ try {
126
+ if (this.options.auth) {
127
+ const cookie_header = await get_cookie_header(http_protocol, host, this.options.auth, this.fetch, this.options.token, this.options.credentials);
128
+ if (cookie_header) this.set_cookies(cookie_header);
129
+ }
130
+ } catch (e) {
131
+ throw Error(e.message);
132
+ }
130
133
  }
131
- async function get_cookie_header(http_protocol, host, auth, _fetch, token) {
132
- const formData = new FormData();
133
- formData.append("username", auth?.[0]);
134
- formData.append("password", auth?.[1]);
135
- let headers = {};
136
- if (token) {
137
- headers.Authorization = `Bearer ${token}`;
138
- }
139
- const res = await _fetch(`${http_protocol}//${host}/${LOGIN_URL}`, {
140
- headers,
141
- method: "POST",
142
- body: formData,
143
- credentials: "include"
144
- });
145
- if (res.status === 200) {
146
- return res.headers.get("set-cookie");
147
- } else if (res.status === 401) {
148
- throw new Error(INVALID_CREDENTIALS_MSG);
149
- } else {
150
- throw new Error(SPACE_METADATA_ERROR_MSG);
151
- }
134
+ async function get_cookie_header(http_protocol, host, auth, _fetch, token, credentials) {
135
+ const formData = new FormData();
136
+ formData.append("username", auth?.[0]);
137
+ formData.append("password", auth?.[1]);
138
+ let headers = {};
139
+ if (token) headers.Authorization = `Bearer ${token}`;
140
+ const res = await _fetch(`${http_protocol}//${host}/${LOGIN_URL}`, {
141
+ headers,
142
+ method: "POST",
143
+ body: formData,
144
+ credentials: credentials ?? "same-origin"
145
+ });
146
+ if (res.status === 200) return res.headers.get("set-cookie");
147
+ else if (res.status === 401) throw new Error(INVALID_CREDENTIALS_MSG);
148
+ else throw new Error(SPACE_METADATA_ERROR_MSG);
152
149
  }
153
150
  function determine_protocol(endpoint) {
154
- if (endpoint.startsWith("http")) {
155
- const { protocol, host, pathname } = new URL(endpoint);
156
- return {
157
- ws_protocol: protocol === "https:" ? "wss" : "ws",
158
- http_protocol: protocol,
159
- host: host + (pathname !== "/" ? pathname : "")
160
- };
161
- }
162
- return {
163
- ws_protocol: "wss",
164
- http_protocol: "https:",
165
- host: new URL(endpoint).host
166
- };
151
+ if (endpoint.startsWith("http")) {
152
+ const { protocol, host, pathname } = new URL(endpoint);
153
+ return {
154
+ ws_protocol: protocol === "https:" ? "wss" : "ws",
155
+ http_protocol: protocol,
156
+ host: host + (pathname !== "/" ? pathname : "")
157
+ };
158
+ }
159
+ return {
160
+ ws_protocol: "wss",
161
+ http_protocol: "https:",
162
+ host: new URL(endpoint).host
163
+ };
167
164
  }
168
- const parse_and_set_cookies = (cookie_header) => {
169
- let cookies = [];
170
- const parts = cookie_header.split(/,(?=\s*[^\s=;]+=[^\s=;]+)/);
171
- parts.forEach((cookie) => {
172
- const [cookie_name, cookie_value] = cookie.split(";")[0].split("=");
173
- if (cookie_name && cookie_value) {
174
- cookies.push(`${cookie_name.trim()}=${cookie_value.trim()}`);
175
- }
176
- });
177
- return cookies;
165
+ var parse_and_set_cookies = (cookie_header) => {
166
+ let cookies = [];
167
+ cookie_header.split(/,(?=\s*[^\s=;]+=[^\s=;]+)/).forEach((cookie) => {
168
+ const [cookie_name, cookie_value] = cookie.split(";")[0].split("=");
169
+ if (cookie_name && cookie_value) cookies.push(`${cookie_name.trim()}=${cookie_value.trim()}`);
170
+ });
171
+ return cookies;
178
172
  };
179
- const RE_SPACE_NAME = /^[a-zA-Z0-9_\-\.]+\/[a-zA-Z0-9_\-\.]+$/;
180
- const RE_SPACE_DOMAIN = /.*hf\.space\/{0,1}.*$/;
173
+ //#endregion
174
+ //#region src/helpers/api_info.ts
175
+ var RE_SPACE_NAME = /^[a-zA-Z0-9_\-\.]+\/[a-zA-Z0-9_\-\.]+$/;
176
+ var RE_SPACE_DOMAIN = /.*hf\.space\/{0,1}.*$/;
181
177
  async function process_endpoint(app_reference, token) {
182
- const headers = {};
183
- if (token) {
184
- headers.Authorization = `Bearer ${token}`;
185
- }
186
- const _app_reference = app_reference.trim().replace(/\/$/, "");
187
- if (RE_SPACE_NAME.test(_app_reference)) {
188
- try {
189
- const res = await fetch(
190
- `https://huggingface.co/api/spaces/${_app_reference}/${HOST_URL}`,
191
- { headers }
192
- );
193
- const _host = (await res.json()).host;
194
- return {
195
- space_id: app_reference,
196
- ...determine_protocol(_host)
197
- };
198
- } catch (e) {
199
- throw new Error(SPACE_METADATA_ERROR_MSG);
200
- }
201
- }
202
- if (RE_SPACE_DOMAIN.test(_app_reference)) {
203
- const { ws_protocol, http_protocol, host } = determine_protocol(_app_reference);
204
- return {
205
- space_id: host.split("/")[0].replace(".hf.space", ""),
206
- ws_protocol,
207
- http_protocol,
208
- host
209
- };
210
- }
211
- return {
212
- space_id: false,
213
- ...determine_protocol(_app_reference)
214
- };
178
+ const headers = {};
179
+ if (token) headers.Authorization = `Bearer ${token}`;
180
+ const _app_reference = app_reference.trim().replace(/\/$/, "");
181
+ if (RE_SPACE_NAME.test(_app_reference)) {
182
+ let res;
183
+ try {
184
+ res = await fetch(`https://huggingface.co/api/spaces/${_app_reference}/${HOST_URL}`, { headers });
185
+ } catch (e) {
186
+ throw new Error(SPACE_METADATA_ERROR_MSG);
187
+ }
188
+ if (res.status === 401 || res.status === 404) throw new Error(SPACE_NOT_FOUND_MSG(_app_reference, res.status));
189
+ let _host;
190
+ try {
191
+ _host = (await res.json()).host;
192
+ } catch (e) {
193
+ throw new Error(SPACE_METADATA_ERROR_MSG);
194
+ }
195
+ if (!_host) throw new Error(SPACE_METADATA_ERROR_MSG);
196
+ return {
197
+ space_id: _app_reference,
198
+ ...determine_protocol(_host)
199
+ };
200
+ }
201
+ if (RE_SPACE_DOMAIN.test(_app_reference)) {
202
+ const { ws_protocol, http_protocol, host } = determine_protocol(_app_reference);
203
+ return {
204
+ space_id: host.split("/")[0].replace(".hf.space", ""),
205
+ ws_protocol,
206
+ http_protocol,
207
+ host
208
+ };
209
+ }
210
+ return {
211
+ space_id: false,
212
+ ...determine_protocol(_app_reference)
213
+ };
215
214
  }
216
- const join_urls = (...urls) => {
217
- try {
218
- return urls.reduce((base_url, part) => {
219
- base_url = base_url.replace(/\/+$/, "");
220
- part = part.replace(/^\/+/, "");
221
- return new URL(part, base_url + "/").toString();
222
- });
223
- } catch (e) {
224
- throw new Error(INVALID_URL_MSG);
225
- }
215
+ var join_urls = (...urls) => {
216
+ try {
217
+ return urls.reduce((base_url, part) => {
218
+ base_url = base_url.replace(/\/+$/, "");
219
+ part = part.replace(/^\/+/, "");
220
+ return new URL(part, base_url + "/").toString();
221
+ });
222
+ } catch (e) {
223
+ throw new Error(INVALID_URL_MSG);
224
+ }
226
225
  };
227
226
  function transform_api_info(api_info, config, api_map) {
228
- const transformed_info = {
229
- named_endpoints: {},
230
- unnamed_endpoints: {}
231
- };
232
- Object.keys(api_info).forEach((category) => {
233
- if (category === "named_endpoints" || category === "unnamed_endpoints") {
234
- transformed_info[category] = {};
235
- Object.entries(api_info[category]).forEach(
236
- ([endpoint, { parameters, returns }]) => {
237
- const dependencyIndex = config.dependencies.find(
238
- (dep) => dep.api_name === endpoint || dep.api_name === endpoint.replace("/", "")
239
- )?.id || api_map[endpoint.replace("/", "")] || -1;
240
- const dependencyTypes = dependencyIndex !== -1 ? config.dependencies.find((dep) => dep.id == dependencyIndex)?.types : { generator: false, cancel: false };
241
- if (dependencyIndex !== -1 && config.dependencies.find((dep) => dep.id == dependencyIndex)?.inputs?.length !== parameters.length) {
242
- const components = config.dependencies.find((dep) => dep.id == dependencyIndex).inputs.map(
243
- (input) => config.components.find((c) => c.id === input)?.type
244
- );
245
- try {
246
- components.forEach((comp, idx) => {
247
- if (comp === "state") {
248
- const new_param = {
249
- component: "state",
250
- example: null,
251
- parameter_default: null,
252
- parameter_has_default: true,
253
- parameter_name: null,
254
- hidden: true
255
- };
256
- parameters.splice(idx, 0, new_param);
257
- }
258
- });
259
- } catch (e) {
260
- console.error(e);
261
- }
262
- }
263
- const transform_type = (data, component, serializer, signature_type) => ({
264
- ...data,
265
- description: get_description(data?.type, serializer),
266
- type: get_type(data?.type, component, serializer, signature_type) || ""
267
- });
268
- transformed_info[category][endpoint] = {
269
- parameters: parameters.map(
270
- (p) => transform_type(p, p?.component, p?.serializer, "parameter")
271
- ),
272
- returns: returns.map(
273
- (r) => transform_type(r, r?.component, r?.serializer, "return")
274
- ),
275
- type: dependencyTypes
276
- };
277
- }
278
- );
279
- }
280
- });
281
- return transformed_info;
227
+ const transformed_info = {
228
+ named_endpoints: {},
229
+ unnamed_endpoints: {}
230
+ };
231
+ Object.keys(api_info).forEach((category) => {
232
+ if (category === "named_endpoints" || category === "unnamed_endpoints") {
233
+ transformed_info[category] = {};
234
+ Object.entries(api_info[category]).forEach(([endpoint, endpoint_info]) => {
235
+ const parameters = endpoint_info?.parameters ?? [];
236
+ const returns = endpoint_info?.returns ?? [];
237
+ const dependencyIndex = config.dependencies.find((dep) => dep.api_name === endpoint || dep.api_name === endpoint.replace("/", ""))?.id || api_map[endpoint.replace("/", "")] || -1;
238
+ const dependency = dependencyIndex !== -1 ? config.dependencies.find((dep) => dep.id == dependencyIndex) : void 0;
239
+ const dependencyTypes = dependencyIndex !== -1 ? dependency?.types : {
240
+ generator: false,
241
+ cancel: false
242
+ };
243
+ if (dependency && Array.isArray(dependency.inputs) && dependency.inputs.length !== parameters.length) {
244
+ const components = dependency.inputs.map((input) => config.components.find((c) => c.id === input)?.type);
245
+ try {
246
+ components.forEach((comp, idx) => {
247
+ if (comp === "state") parameters.splice(idx, 0, {
248
+ component: "state",
249
+ example: null,
250
+ parameter_default: null,
251
+ parameter_has_default: true,
252
+ parameter_name: null,
253
+ hidden: true
254
+ });
255
+ });
256
+ } catch (e) {
257
+ console.error(e);
258
+ }
259
+ }
260
+ const transform_type = (data, component, serializer, signature_type) => ({
261
+ ...data,
262
+ description: get_description(data?.type, serializer),
263
+ type: get_type(data?.type, component, serializer, signature_type) || ""
264
+ });
265
+ transformed_info[category][endpoint] = {
266
+ parameters: parameters.map((p) => transform_type(p, p?.component, p?.serializer, "parameter")),
267
+ returns: returns.map((r) => transform_type(r, r?.component, r?.serializer, "return")),
268
+ type: dependencyTypes,
269
+ ...endpoint_info?.oauth_token ? { oauth_token: endpoint_info.oauth_token } : {}
270
+ };
271
+ });
272
+ }
273
+ });
274
+ return transformed_info;
282
275
  }
283
276
  function get_type(type, component, serializer, signature_type) {
284
- if (component === "Api") return type.type;
285
- switch (type?.type) {
286
- case "string":
287
- return "string";
288
- case "boolean":
289
- return "boolean";
290
- case "number":
291
- return "number";
292
- }
293
- if (serializer === "JSONSerializable" || serializer === "StringSerializable") {
294
- return "any";
295
- } else if (serializer === "ListStringSerializable") {
296
- return "string[]";
297
- } else if (component === "Image") {
298
- return signature_type === "parameter" ? "Blob | File | Buffer" : "string";
299
- } else if (serializer === "FileSerializable") {
300
- if (type?.type === "array") {
301
- return signature_type === "parameter" ? "(Blob | File | Buffer)[]" : `{ name: string; data: string; size?: number; is_file?: boolean; orig_name?: string}[]`;
302
- }
303
- return signature_type === "parameter" ? "Blob | File | Buffer" : `{ name: string; data: string; size?: number; is_file?: boolean; orig_name?: string}`;
304
- } else if (serializer === "GallerySerializable") {
305
- return signature_type === "parameter" ? "[(Blob | File | Buffer), (string | null)][]" : `[{ name: string; data: string; size?: number; is_file?: boolean; orig_name?: string}, (string | null))][]`;
306
- }
277
+ if (component === "Api") return type.type;
278
+ switch (type?.type) {
279
+ case "string": return "string";
280
+ case "boolean": return "boolean";
281
+ case "number": return "number";
282
+ }
283
+ if (serializer === "JSONSerializable" || serializer === "StringSerializable") return "any";
284
+ else if (serializer === "ListStringSerializable") return "string[]";
285
+ else if (component === "Image") return signature_type === "parameter" ? "Blob | File | Buffer" : "string";
286
+ else if (serializer === "FileSerializable") {
287
+ if (type?.type === "array") return signature_type === "parameter" ? "(Blob | File | Buffer)[]" : `{ name: string; data: string; size?: number; is_file?: boolean; orig_name?: string}[]`;
288
+ return signature_type === "parameter" ? "Blob | File | Buffer" : `{ name: string; data: string; size?: number; is_file?: boolean; orig_name?: string}`;
289
+ } else if (serializer === "GallerySerializable") return signature_type === "parameter" ? "[(Blob | File | Buffer), (string | null)][]" : `[{ name: string; data: string; size?: number; is_file?: boolean; orig_name?: string}, (string | null))][]`;
307
290
  }
308
291
  function get_description(type, serializer) {
309
- if (serializer === "GallerySerializable") {
310
- return "array of [file, label] tuples";
311
- } else if (serializer === "ListStringSerializable") {
312
- return "array of strings";
313
- } else if (serializer === "FileSerializable") {
314
- return "array of files or single file";
315
- }
316
- return type?.description;
292
+ if (serializer === "GallerySerializable") return "array of [file, label] tuples";
293
+ else if (serializer === "ListStringSerializable") return "array of strings";
294
+ else if (serializer === "FileSerializable") return "array of files or single file";
295
+ return type?.description;
317
296
  }
318
297
  function handle_message(data, last_status) {
319
- const queue = true;
320
- switch (data.msg) {
321
- case "send_data":
322
- return { type: "data" };
323
- case "send_hash":
324
- return { type: "hash" };
325
- case "queue_full":
326
- return {
327
- type: "update",
328
- status: {
329
- queue,
330
- message: QUEUE_FULL_MSG,
331
- stage: "error",
332
- code: data.code,
333
- success: data.success
334
- }
335
- };
336
- case "heartbeat":
337
- return {
338
- type: "heartbeat"
339
- };
340
- case "unexpected_error":
341
- return {
342
- type: "unexpected_error",
343
- status: {
344
- queue,
345
- message: data.message,
346
- session_not_found: data.session_not_found,
347
- stage: "error",
348
- success: false
349
- }
350
- };
351
- case "broken_connection":
352
- return {
353
- type: "broken_connection",
354
- status: {
355
- queue,
356
- message: data.message,
357
- stage: "error",
358
- success: false
359
- }
360
- };
361
- case "estimation":
362
- return {
363
- type: "update",
364
- status: {
365
- queue,
366
- stage: last_status || "pending",
367
- code: data.code,
368
- size: data.queue_size,
369
- position: data.rank,
370
- eta: data.rank_eta,
371
- success: data.success
372
- }
373
- };
374
- case "progress":
375
- return {
376
- type: "update",
377
- status: {
378
- queue,
379
- stage: "pending",
380
- code: data.code,
381
- progress_data: data.progress_data,
382
- success: data.success
383
- }
384
- };
385
- case "log":
386
- return { type: "log", data };
387
- case "process_generating":
388
- return {
389
- type: "generating",
390
- status: {
391
- queue,
392
- message: !data.success ? data.output.error : null,
393
- stage: data.success ? "generating" : "error",
394
- code: data.code,
395
- progress_data: data.progress_data,
396
- eta: data.average_duration,
397
- changed_state_ids: data.success ? data.output.changed_state_ids : void 0
398
- },
399
- data: data.success ? data.output : null
400
- };
401
- case "process_streaming":
402
- return {
403
- type: "streaming",
404
- status: {
405
- queue,
406
- message: data.output.error,
407
- stage: "streaming",
408
- time_limit: data.time_limit,
409
- code: data.code,
410
- progress_data: data.progress_data,
411
- eta: data.eta
412
- },
413
- data: data.output
414
- };
415
- case "process_completed":
416
- if ("error" in data.output) {
417
- return {
418
- type: "update",
419
- status: {
420
- queue,
421
- title: data.output.title ?? "Error",
422
- message: data.output.error ?? "An error occurred",
423
- visible: data.output.visible,
424
- duration: data.output.duration,
425
- stage: "error",
426
- code: data.code,
427
- success: data.success
428
- }
429
- };
430
- }
431
- return {
432
- type: "complete",
433
- status: {
434
- queue,
435
- message: !data.success ? data.output.error : void 0,
436
- stage: data.success ? "complete" : "error",
437
- code: data.code,
438
- progress_data: data.progress_data,
439
- changed_state_ids: data.success ? data.output.changed_state_ids : void 0,
440
- used_cache: data.used_cache,
441
- cache_duration: data.cache_duration,
442
- avg_time: data.avg_time
443
- },
444
- data: data.success ? data.output : null
445
- };
446
- case "process_starts":
447
- return {
448
- type: "update",
449
- status: {
450
- queue,
451
- stage: "pending",
452
- code: data.code,
453
- size: data.rank,
454
- position: 0,
455
- success: data.success,
456
- eta: data.eta
457
- },
458
- original_msg: "process_starts"
459
- };
460
- }
461
- return { type: "none", status: { stage: "error", queue } };
298
+ const queue = true;
299
+ switch (data.msg) {
300
+ case "send_data": return { type: "data" };
301
+ case "send_hash": return { type: "hash" };
302
+ case "queue_full": return {
303
+ type: "update",
304
+ status: {
305
+ queue,
306
+ message: QUEUE_FULL_MSG,
307
+ stage: "error",
308
+ code: data.code,
309
+ success: data.success
310
+ }
311
+ };
312
+ case "heartbeat": return { type: "heartbeat" };
313
+ case "unexpected_error": return {
314
+ type: "unexpected_error",
315
+ status: {
316
+ queue,
317
+ message: data.message,
318
+ session_not_found: data.session_not_found,
319
+ stage: "error",
320
+ success: false
321
+ }
322
+ };
323
+ case "broken_connection": return {
324
+ type: "broken_connection",
325
+ status: {
326
+ queue,
327
+ message: data.message,
328
+ stage: "error",
329
+ success: false
330
+ }
331
+ };
332
+ case "estimation": return {
333
+ type: "update",
334
+ status: {
335
+ queue,
336
+ stage: last_status || "pending",
337
+ code: data.code,
338
+ size: data.queue_size,
339
+ position: data.rank,
340
+ eta: data.rank_eta,
341
+ success: data.success
342
+ }
343
+ };
344
+ case "progress": return {
345
+ type: "update",
346
+ status: {
347
+ queue,
348
+ stage: "pending",
349
+ code: data.code,
350
+ progress_data: data.progress_data,
351
+ success: data.success
352
+ }
353
+ };
354
+ case "log": return {
355
+ type: "log",
356
+ data
357
+ };
358
+ case "process_generating": return {
359
+ type: "generating",
360
+ status: {
361
+ queue,
362
+ message: !data.success ? data.output.error : null,
363
+ stage: data.success ? "generating" : "error",
364
+ code: data.code,
365
+ progress_data: data.progress_data,
366
+ eta: data.average_duration,
367
+ changed_state_ids: data.success ? data.output.changed_state_ids : void 0
368
+ },
369
+ data: data.success ? data.output : null
370
+ };
371
+ case "process_streaming": return {
372
+ type: "streaming",
373
+ status: {
374
+ queue,
375
+ message: data.output.error,
376
+ stage: "streaming",
377
+ time_limit: data.time_limit,
378
+ code: data.code,
379
+ progress_data: data.progress_data,
380
+ changed_state_ids: data.output.changed_state_ids,
381
+ eta: data.eta
382
+ },
383
+ data: data.output
384
+ };
385
+ case "process_completed":
386
+ if ("error" in data.output) return {
387
+ type: "update",
388
+ status: {
389
+ queue,
390
+ title: data.output.title ?? "Error",
391
+ message: data.output.error ?? "An error occurred",
392
+ visible: data.output.visible,
393
+ duration: data.output.duration,
394
+ stage: "error",
395
+ code: data.code,
396
+ success: data.success
397
+ }
398
+ };
399
+ return {
400
+ type: "complete",
401
+ status: {
402
+ queue,
403
+ message: !data.success ? data.output.error : void 0,
404
+ stage: data.success ? "complete" : "error",
405
+ code: data.code,
406
+ progress_data: data.progress_data,
407
+ changed_state_ids: data.success ? data.output.changed_state_ids : void 0,
408
+ used_cache: data.used_cache,
409
+ cache_duration: data.cache_duration,
410
+ avg_time: data.avg_time
411
+ },
412
+ data: data.success ? data.output : null
413
+ };
414
+ case "process_starts": return {
415
+ type: "update",
416
+ status: {
417
+ queue,
418
+ stage: "pending",
419
+ code: data.code,
420
+ size: data.rank,
421
+ position: 0,
422
+ success: data.success,
423
+ eta: data.eta
424
+ },
425
+ original_msg: "process_starts"
426
+ };
427
+ }
428
+ return {
429
+ type: "none",
430
+ status: {
431
+ stage: "error",
432
+ queue
433
+ }
434
+ };
462
435
  }
463
- const map_data_to_params = (data = [], endpoint_info) => {
464
- const parameters = endpoint_info ? endpoint_info.parameters : [];
465
- if (Array.isArray(data)) {
466
- if (endpoint_info && parameters.length > 0 && data.length > parameters.length) {
467
- console.warn("Too many arguments provided for the endpoint.");
468
- }
469
- return data;
470
- }
471
- const resolved_data = [];
472
- const provided_keys = Object.keys(data);
473
- parameters.forEach((param, index) => {
474
- if (data.hasOwnProperty(param.parameter_name)) {
475
- resolved_data[index] = data[param.parameter_name];
476
- } else if (param.parameter_has_default) {
477
- resolved_data[index] = param.parameter_default;
478
- } else {
479
- throw new Error(
480
- `No value provided for required parameter: ${param.parameter_name}`
481
- );
482
- }
483
- });
484
- provided_keys.forEach((key) => {
485
- if (!parameters.some((param) => param.parameter_name === key)) {
486
- throw new Error(
487
- `Parameter \`${key}\` is not a valid keyword argument. Please refer to the API for usage.`
488
- );
489
- }
490
- });
491
- resolved_data.forEach((value, idx) => {
492
- if (value === void 0 && !parameters[idx].parameter_has_default) {
493
- throw new Error(
494
- `No value provided for required parameter: ${parameters[idx].parameter_name}`
495
- );
496
- }
497
- });
498
- return resolved_data;
436
+ /**
437
+ * Maps the provided `data` to the parameters defined by the `/info` endpoint response.
438
+ * This allows us to support both positional and keyword arguments passed to the client
439
+ * and ensures that all parameters are either directly provided or have default values assigned.
440
+ *
441
+ * @param {unknown[] | Record<string, unknown>} data - The input data for the function,
442
+ * which can be either an array of values for positional arguments or an object
443
+ * with key-value pairs for keyword arguments.
444
+ * @param {JsApiData[]} parameters - Array of parameter descriptions retrieved from the
445
+ * `/info` endpoint.
446
+ *
447
+ * @returns {unknown[]} - Returns an array of resolved data where each element corresponds
448
+ * to the expected parameter from the API. The `parameter_default` value is used where
449
+ * a value is not provided for a parameter, and optional parameters without defaults are
450
+ * set to `undefined`.
451
+ *
452
+ * @throws {Error} - Throws an error:
453
+ * - If more arguments are provided than are defined in the parameters.
454
+ * * - If no parameter value is provided for a required parameter and no default value is defined.
455
+ * - If an argument is provided that does not match any defined parameter.
456
+ */
457
+ var map_data_to_params = (data = [], endpoint_info) => {
458
+ const parameters = endpoint_info ? endpoint_info.parameters : [];
459
+ if (Array.isArray(data)) {
460
+ if (endpoint_info && parameters.length > 0 && data.length > parameters.length) console.warn("Too many arguments provided for the endpoint.");
461
+ return data;
462
+ }
463
+ const resolved_data = [];
464
+ const provided_keys = Object.keys(data);
465
+ parameters.forEach((param, index) => {
466
+ if (data.hasOwnProperty(param.parameter_name)) resolved_data[index] = data[param.parameter_name];
467
+ else if (param.parameter_has_default) resolved_data[index] = param.parameter_default;
468
+ else throw new Error(`No value provided for required parameter: ${param.parameter_name}`);
469
+ });
470
+ provided_keys.forEach((key) => {
471
+ if (!parameters.some((param) => param.parameter_name === key)) throw new Error(`Parameter \`${key}\` is not a valid keyword argument. Please refer to the API for usage.`);
472
+ });
473
+ resolved_data.forEach((value, idx) => {
474
+ if (value === void 0 && !parameters[idx].parameter_has_default) throw new Error(`No value provided for required parameter: ${parameters[idx].parameter_name}`);
475
+ });
476
+ return resolved_data;
499
477
  };
478
+ //#endregion
479
+ //#region src/utils/view_api.ts
500
480
  async function view_api() {
501
- if (this.api_info) return this.api_info;
502
- const { token } = this.options;
503
- const { config } = this;
504
- const headers = { "Content-Type": "application/json" };
505
- if (token) {
506
- headers.Authorization = `Bearer ${token}`;
507
- }
508
- if (!config) {
509
- return;
510
- }
511
- try {
512
- let response;
513
- let api_info;
514
- if (typeof window !== "undefined" && window.gradio_api_info) {
515
- api_info = window.gradio_api_info;
516
- } else {
517
- const url = join_urls(config.root, this.api_prefix, API_INFO_URL);
518
- response = await this.fetch(url, {
519
- headers,
520
- credentials: "include"
521
- });
522
- if (!response.ok) {
523
- throw new Error(BROKEN_CONNECTION_MSG);
524
- }
525
- api_info = await response.json();
526
- }
527
- if ("api" in api_info) {
528
- api_info = api_info.api;
529
- }
530
- if (api_info.named_endpoints["/predict"] && !api_info.unnamed_endpoints["0"]) {
531
- api_info.unnamed_endpoints[0] = api_info.named_endpoints["/predict"];
532
- }
533
- return transform_api_info(api_info, config, this.api_map);
534
- } catch (e) {
535
- throw new Error("Could not get API info. " + e.message);
536
- }
481
+ if (this.api_info) return this.api_info;
482
+ const { token } = this.options;
483
+ const { config } = this;
484
+ const headers = {};
485
+ if (token) headers.Authorization = `Bearer ${token}`;
486
+ if (!config) return;
487
+ try {
488
+ let response;
489
+ let api_info;
490
+ if (typeof window !== "undefined" && window.gradio_api_info) api_info = window.gradio_api_info;
491
+ else {
492
+ const url = join_urls(config.root, this.api_prefix, API_INFO_URL);
493
+ response = await this.fetch(url, {
494
+ headers,
495
+ credentials: this.options.credentials ?? "same-origin"
496
+ });
497
+ if (!response.ok) throw new Error(BROKEN_CONNECTION_MSG);
498
+ api_info = await response.json();
499
+ }
500
+ if ("api" in api_info) api_info = api_info.api;
501
+ if (api_info.named_endpoints["/predict"] && !api_info.unnamed_endpoints["0"]) api_info.unnamed_endpoints[0] = api_info.named_endpoints["/predict"];
502
+ return transform_api_info(api_info, config, this.api_map);
503
+ } catch (e) {
504
+ throw new Error("Could not get API info. " + e.message);
505
+ }
537
506
  }
507
+ //#endregion
508
+ //#region src/utils/upload_files.ts
538
509
  async function upload_files(root_url, files, upload_id) {
539
- const headers = {};
540
- if (this?.options?.token) {
541
- headers.Authorization = `Bearer ${this.options.token}`;
542
- }
543
- const chunkSize = 1e3;
544
- const uploadResponses = [];
545
- let response;
546
- for (let i = 0; i < files.length; i += chunkSize) {
547
- const chunk = files.slice(i, i + chunkSize);
548
- const formData = new FormData();
549
- chunk.forEach((file) => {
550
- formData.append("files", file);
551
- });
552
- try {
553
- const upload_url = upload_id ? `${root_url}${this.api_prefix}/${UPLOAD_URL}?upload_id=${upload_id}` : `${root_url}${this.api_prefix}/${UPLOAD_URL}`;
554
- response = await this.fetch(upload_url, {
555
- method: "POST",
556
- body: formData,
557
- headers,
558
- credentials: "include"
559
- });
560
- } catch (e) {
561
- throw new Error(BROKEN_CONNECTION_MSG + e.message);
562
- }
563
- if (!response.ok) {
564
- const error_text = await response.text();
565
- return { error: `HTTP ${response.status}: ${error_text}` };
566
- }
567
- const output = await response.json();
568
- if (output) {
569
- uploadResponses.push(...output);
570
- }
571
- }
572
- return { files: uploadResponses };
510
+ const headers = {};
511
+ if (this?.options?.token) headers.Authorization = `Bearer ${this.options.token}`;
512
+ const chunkSize = 1e3;
513
+ const uploadResponses = [];
514
+ let response;
515
+ for (let i = 0; i < files.length; i += chunkSize) {
516
+ const chunk = files.slice(i, i + chunkSize);
517
+ const formData = new FormData();
518
+ chunk.forEach((file) => {
519
+ formData.append("files", file);
520
+ });
521
+ try {
522
+ const upload_url = upload_id ? `${root_url}${this.api_prefix}/${UPLOAD_URL}?upload_id=${upload_id}` : `${root_url}${this.api_prefix}/${UPLOAD_URL}`;
523
+ response = await this.fetch(upload_url, {
524
+ method: "POST",
525
+ body: formData,
526
+ headers,
527
+ credentials: this.options.credentials ?? "same-origin"
528
+ });
529
+ } catch (e) {
530
+ throw new Error(BROKEN_CONNECTION_MSG + e.message);
531
+ }
532
+ if (!response.ok) {
533
+ const error_text = await response.text();
534
+ return { error: `HTTP ${response.status}: ${error_text}` };
535
+ }
536
+ const output = await response.json();
537
+ if (output) uploadResponses.push(...output);
538
+ }
539
+ return { files: uploadResponses };
573
540
  }
574
- const si = {
575
- radix: 1e3,
576
- unit: ["b", "kb", "Mb", "Gb", "Tb", "Pb", "Eb", "Zb", "Yb"]
577
- };
578
- const iec = {
579
- radix: 1024,
580
- unit: ["b", "Kib", "Mib", "Gib", "Tib", "Pib", "Eib", "Zib", "Yib"]
581
- };
582
- const jedec = {
583
- radix: 1024,
584
- unit: ["b", "Kb", "Mb", "Gb", "Tb", "Pb", "Eb", "Zb", "Yb"]
585
- };
586
- const SPECS = {
587
- si,
588
- iec,
589
- jedec
541
+ var SPECS = {
542
+ si: {
543
+ radix: 1e3,
544
+ unit: [
545
+ "b",
546
+ "kb",
547
+ "Mb",
548
+ "Gb",
549
+ "Tb",
550
+ "Pb",
551
+ "Eb",
552
+ "Zb",
553
+ "Yb"
554
+ ]
555
+ },
556
+ iec: {
557
+ radix: 1024,
558
+ unit: [
559
+ "b",
560
+ "Kib",
561
+ "Mib",
562
+ "Gib",
563
+ "Tib",
564
+ "Pib",
565
+ "Eib",
566
+ "Zib",
567
+ "Yib"
568
+ ]
569
+ },
570
+ jedec: {
571
+ radix: 1024,
572
+ unit: [
573
+ "b",
574
+ "Kb",
575
+ "Mb",
576
+ "Gb",
577
+ "Tb",
578
+ "Pb",
579
+ "Eb",
580
+ "Zb",
581
+ "Yb"
582
+ ]
583
+ }
590
584
  };
585
+ /**
586
+ * file size from https://github.com/hustcc/filesize.js
587
+ * @param bytes - The number of bytes to convert to human-readable format
588
+ * @param fixed - Number of decimal places to display (default: 1)
589
+ * @param spec - Size specification to use: "si", "iec", or "jedec" (default: "jedec")
590
+ * @returns Human-readable file size string
591
+ */
591
592
  function filesize(bytes, fixed = 1, spec = "jedec") {
592
- bytes = Math.abs(bytes);
593
- const { radix, unit } = SPECS[spec] || SPECS.jedec;
594
- let loop = 0;
595
- while (bytes >= radix) {
596
- bytes /= radix;
597
- ++loop;
598
- }
599
- return `${bytes.toFixed(fixed)} ${unit[loop]}`;
593
+ bytes = Math.abs(bytes);
594
+ const { radix, unit } = SPECS[spec] || SPECS.jedec;
595
+ let loop = 0;
596
+ while (bytes >= radix) {
597
+ bytes /= radix;
598
+ ++loop;
599
+ }
600
+ return `${bytes.toFixed(fixed)} ${unit[loop]}`;
600
601
  }
602
+ //#endregion
603
+ //#region src/upload.ts
601
604
  async function upload(file_data, root_url, upload_id, max_file_size) {
602
- let files = (Array.isArray(file_data) ? file_data : [file_data]).map(
603
- (file_data2) => file_data2.blob
604
- );
605
- const oversized_files = files.filter(
606
- (f) => f.size > (max_file_size ?? Infinity)
607
- );
608
- if (oversized_files.length) {
609
- throw new Error(
610
- `File(s) exceed the maximum allowed size of ${filesize(max_file_size || Infinity)}: ${oversized_files.map((f) => `"${f.name}"`).join(", ")}`
611
- );
612
- }
613
- return await Promise.all(
614
- await this.upload_files(root_url, files, upload_id).then(
615
- async (response) => {
616
- if (response.error) {
617
- throw new Error(response.error);
618
- } else {
619
- if (response.files) {
620
- return response.files.map((f, i) => {
621
- const file = new FileData({
622
- ...file_data[i],
623
- path: f,
624
- url: `${root_url}${this.api_prefix}/file=${f}`
625
- });
626
- return file;
627
- });
628
- }
629
- return [];
630
- }
631
- }
632
- )
633
- );
605
+ let files = (Array.isArray(file_data) ? file_data : [file_data]).map((file_data) => file_data.blob);
606
+ const oversized_files = files.filter((f) => f.size > (max_file_size ?? Infinity));
607
+ if (oversized_files.length) throw new Error(`File(s) exceed the maximum allowed size of ${filesize(max_file_size || Infinity)}: ${oversized_files.map((f) => `"${f.name}"`).join(", ")}`);
608
+ return await Promise.all(await this.upload_files(root_url, files, upload_id).then(async (response) => {
609
+ if (response.error) throw new Error(response.error);
610
+ else {
611
+ if (response.files) return response.files.map((f, i) => {
612
+ return new FileData({
613
+ ...file_data[i],
614
+ path: f,
615
+ url: `${root_url}${this.api_prefix}/file=${f}`
616
+ });
617
+ });
618
+ return [];
619
+ }
620
+ }));
634
621
  }
635
622
  async function prepare_files(files, is_stream) {
636
- return files.map(
637
- (f) => new FileData({
638
- path: f.name,
639
- orig_name: f.name,
640
- blob: f,
641
- size: f.size,
642
- mime_type: f.type,
643
- is_stream
644
- })
645
- );
646
- }
647
- class FileData {
648
- path;
649
- url;
650
- orig_name;
651
- size;
652
- blob;
653
- is_stream;
654
- mime_type;
655
- alt_text;
656
- b64;
657
- meta = { _type: "gradio.FileData" };
658
- constructor({
659
- path,
660
- url,
661
- orig_name,
662
- size,
663
- blob,
664
- is_stream,
665
- mime_type,
666
- alt_text,
667
- b64
668
- }) {
669
- this.path = path;
670
- this.url = url;
671
- this.orig_name = orig_name;
672
- this.size = size;
673
- this.blob = url ? void 0 : blob;
674
- this.is_stream = is_stream;
675
- this.mime_type = mime_type;
676
- this.alt_text = alt_text;
677
- this.b64 = b64;
678
- }
679
- }
680
- class Command {
681
- type;
682
- command;
683
- meta;
684
- fileData;
685
- constructor(command, meta) {
686
- this.type = "command";
687
- this.command = command;
688
- this.meta = meta;
689
- }
623
+ return files.map((f) => new FileData({
624
+ path: f.name,
625
+ orig_name: f.name,
626
+ blob: f,
627
+ size: f.size,
628
+ mime_type: f.type,
629
+ is_stream
630
+ }));
690
631
  }
691
- const is_node = typeof process !== "undefined" && process.versions && process.versions.node;
632
+ var FileData = class {
633
+ path;
634
+ url;
635
+ orig_name;
636
+ size;
637
+ blob;
638
+ is_stream;
639
+ mime_type;
640
+ alt_text;
641
+ b64;
642
+ meta = { _type: "gradio.FileData" };
643
+ constructor({ path, url, orig_name, size, blob, is_stream, mime_type, alt_text, b64 }) {
644
+ this.path = path;
645
+ this.url = url;
646
+ this.orig_name = orig_name;
647
+ this.size = size;
648
+ this.blob = url ? void 0 : blob;
649
+ this.is_stream = is_stream;
650
+ this.mime_type = mime_type;
651
+ this.alt_text = alt_text;
652
+ this.b64 = b64;
653
+ }
654
+ };
655
+ //#endregion
656
+ //#region src/types.ts
657
+ var Command = class {
658
+ type;
659
+ command;
660
+ meta;
661
+ fileData;
662
+ constructor(command, meta) {
663
+ this.type = "command";
664
+ this.command = command;
665
+ this.meta = meta;
666
+ }
667
+ };
668
+ //#endregion
669
+ //#region src/helpers/data.ts
670
+ var is_node = typeof process !== "undefined" && process.versions && process.versions.node;
692
671
  function update_object(object, newValue, stack) {
693
- while (stack.length > 1) {
694
- const key2 = stack.shift();
695
- if (typeof key2 === "string" || typeof key2 === "number") {
696
- object = object[key2];
697
- } else {
698
- throw new Error("Invalid key type");
699
- }
700
- }
701
- const key = stack.shift();
702
- if (typeof key === "string" || typeof key === "number") {
703
- object[key] = newValue;
704
- } else {
705
- throw new Error("Invalid key type");
706
- }
672
+ while (stack.length > 1) {
673
+ const key = stack.shift();
674
+ if (typeof key === "string" || typeof key === "number") object = object[key];
675
+ else throw new Error("Invalid key type");
676
+ }
677
+ const key = stack.shift();
678
+ if (typeof key === "string" || typeof key === "number") object[key] = newValue;
679
+ else throw new Error("Invalid key type");
707
680
  }
708
681
  async function walk_and_store_blobs(data, type = void 0, path = [], root = false, endpoint_info = void 0) {
709
- if (Array.isArray(data)) {
710
- let blob_refs = [];
711
- await Promise.all(
712
- data.map(async (_, index) => {
713
- let new_path = path.slice();
714
- new_path.push(String(index));
715
- const array_refs = await walk_and_store_blobs(
716
- data[index],
717
- root ? endpoint_info?.parameters[index]?.component || void 0 : type,
718
- new_path,
719
- false,
720
- endpoint_info
721
- );
722
- blob_refs = blob_refs.concat(array_refs);
723
- })
724
- );
725
- return blob_refs;
726
- } else if (globalThis.Buffer && data instanceof globalThis.Buffer || data instanceof Blob) {
727
- return [
728
- {
729
- path,
730
- blob: new Blob([data]),
731
- type
732
- }
733
- ];
734
- } else if (typeof data === "object" && data !== null) {
735
- let blob_refs = [];
736
- for (const key of Object.keys(data)) {
737
- const new_path = [...path, key];
738
- const value = data[key];
739
- blob_refs = blob_refs.concat(
740
- await walk_and_store_blobs(
741
- value,
742
- void 0,
743
- new_path,
744
- false,
745
- endpoint_info
746
- )
747
- );
748
- }
749
- return blob_refs;
750
- }
751
- return [];
682
+ if (Array.isArray(data)) {
683
+ let blob_refs = [];
684
+ await Promise.all(data.map(async (_, index) => {
685
+ let new_path = path.slice();
686
+ new_path.push(String(index));
687
+ const array_refs = await walk_and_store_blobs(data[index], root ? endpoint_info?.parameters[index]?.component || void 0 : type, new_path, false, endpoint_info);
688
+ blob_refs = blob_refs.concat(array_refs);
689
+ }));
690
+ return blob_refs;
691
+ } else if (globalThis.Buffer && data instanceof globalThis.Buffer || data instanceof Blob) return [{
692
+ path,
693
+ blob: data instanceof Blob ? data : new Blob([data]),
694
+ type
695
+ }];
696
+ else if (typeof data === "object" && data !== null) {
697
+ let blob_refs = [];
698
+ for (const key of Object.keys(data)) {
699
+ const new_path = [...path, key];
700
+ const value = data[key];
701
+ blob_refs = blob_refs.concat(await walk_and_store_blobs(value, void 0, new_path, false, endpoint_info));
702
+ }
703
+ return blob_refs;
704
+ }
705
+ return [];
752
706
  }
753
707
  function skip_queue(id, config) {
754
- let fn_queue = config?.dependencies?.find((dep) => dep.id == id)?.queue;
755
- if (fn_queue != null) {
756
- return !fn_queue;
757
- }
758
- return !config.enable_queue;
708
+ let fn_queue = config?.dependencies?.find((dep) => dep.id == id)?.queue;
709
+ if (fn_queue != null) return !fn_queue;
710
+ return !config.enable_queue;
759
711
  }
760
712
  function post_message(message, origin) {
761
- return new Promise((res, _rej) => {
762
- const channel = new MessageChannel();
763
- channel.port1.onmessage = (({ data }) => {
764
- channel.port1.close();
765
- res(data);
766
- });
767
- window.parent.postMessage(message, origin, [channel.port2]);
768
- });
713
+ return new Promise((res, _rej) => {
714
+ const channel = new MessageChannel();
715
+ channel.port1.onmessage = (({ data }) => {
716
+ channel.port1.close();
717
+ res(data);
718
+ });
719
+ window.parent.postMessage(message, origin, [channel.port2]);
720
+ });
769
721
  }
770
722
  function handle_file(file_or_url) {
771
- if (typeof file_or_url === "string") {
772
- if (file_or_url.startsWith("http://") || file_or_url.startsWith("https://")) {
773
- return {
774
- path: file_or_url,
775
- url: file_or_url,
776
- orig_name: file_or_url.split("/").pop() ?? "unknown",
777
- meta: { _type: "gradio.FileData" }
778
- };
779
- }
780
- if (is_node) {
781
- return new Command("upload_file", {
782
- path: file_or_url,
783
- name: file_or_url,
784
- orig_path: file_or_url
785
- });
786
- }
787
- } else if (typeof File !== "undefined" && file_or_url instanceof File) {
788
- return new Blob([file_or_url]);
789
- } else if (file_or_url instanceof Buffer) {
790
- return new Blob([file_or_url]);
791
- } else if (file_or_url instanceof Blob) {
792
- return file_or_url;
793
- }
794
- throw new Error(
795
- "Invalid input: must be a URL, File, Blob, or Buffer object."
796
- );
723
+ if (typeof file_or_url === "string") {
724
+ if (file_or_url.startsWith("http://") || file_or_url.startsWith("https://")) return {
725
+ path: file_or_url,
726
+ url: file_or_url,
727
+ orig_name: file_or_url.split("/").pop() ?? "unknown",
728
+ meta: { _type: "gradio.FileData" }
729
+ };
730
+ if (is_node) return new Command("upload_file", {
731
+ path: file_or_url,
732
+ name: file_or_url,
733
+ orig_path: file_or_url
734
+ });
735
+ } else if (typeof File !== "undefined" && file_or_url instanceof File) return file_or_url;
736
+ else if (globalThis.Buffer && file_or_url instanceof globalThis.Buffer) return new Blob([file_or_url]);
737
+ else if (file_or_url instanceof Blob) return file_or_url;
738
+ throw new Error("Invalid input: must be a URL, File, Blob, or Buffer object.");
797
739
  }
740
+ /**
741
+ * Handles the payload by filtering out state inputs and returning an array of resolved payload values.
742
+ * We send null values for state inputs to the server, but we don't want to include them in the resolved payload.
743
+ *
744
+ * @param resolved_payload - The resolved payload values received from the client or the server
745
+ * @param dependency - The dependency object.
746
+ * @param components - The array of component metadata.
747
+ * @param with_null_state - Optional. Specifies whether to include null values for state inputs. Default is false.
748
+ * @returns An array of resolved payload values, filtered based on the dependency and component metadata.
749
+ */
798
750
  function handle_payload(resolved_payload, dependency, components, type, with_null_state = false) {
799
- if (type === "input" && !with_null_state) {
800
- throw new Error("Invalid code path. Cannot skip state inputs for input.");
801
- }
802
- if (type === "output" && with_null_state) {
803
- return resolved_payload;
804
- }
805
- let updated_payload = [];
806
- let payload_index = 0;
807
- const deps = type === "input" ? dependency.inputs : dependency.outputs;
808
- for (let i = 0; i < deps.length; i++) {
809
- const input_id = deps[i];
810
- const component = components.find((c) => c.id === input_id);
811
- if (component?.type === "state") {
812
- if (with_null_state) {
813
- if (resolved_payload.length === deps.length) {
814
- const value = resolved_payload[payload_index];
815
- updated_payload.push(value);
816
- payload_index++;
817
- } else {
818
- updated_payload.push(null);
819
- }
820
- } else {
821
- payload_index++;
822
- continue;
823
- }
824
- continue;
825
- } else {
826
- const value = resolved_payload[payload_index];
827
- updated_payload.push(value);
828
- payload_index++;
829
- }
830
- }
831
- return updated_payload;
751
+ if (type === "input" && !with_null_state) throw new Error("Invalid code path. Cannot skip state inputs for input.");
752
+ if (type === "output" && with_null_state) return resolved_payload;
753
+ let updated_payload = [];
754
+ let payload_index = 0;
755
+ const deps = type === "input" ? dependency.inputs : dependency.outputs;
756
+ for (let i = 0; i < deps.length; i++) {
757
+ const input_id = deps[i];
758
+ if (components.find((c) => c.id === input_id)?.type === "state") {
759
+ if (with_null_state) if (resolved_payload.length === deps.length) {
760
+ const value = resolved_payload[payload_index];
761
+ updated_payload.push(value);
762
+ payload_index++;
763
+ } else updated_payload.push(null);
764
+ else {
765
+ payload_index++;
766
+ continue;
767
+ }
768
+ continue;
769
+ } else {
770
+ const value = resolved_payload[payload_index];
771
+ updated_payload.push(value);
772
+ payload_index++;
773
+ }
774
+ }
775
+ return updated_payload;
832
776
  }
777
+ //#endregion
778
+ //#region src/utils/handle_blob.ts
833
779
  async function handle_blob(endpoint, data, api_info) {
834
- const self = this;
835
- await process_local_file_commands(self, data);
836
- const blobRefs = await walk_and_store_blobs(
837
- data,
838
- void 0,
839
- [],
840
- true,
841
- api_info
842
- );
843
- const results = await Promise.all(
844
- blobRefs.map(async ({ path, blob, type }) => {
845
- if (!blob) return { path, type };
846
- const response = await self.upload_files(endpoint, [blob]);
847
- const file_url = response.files && response.files[0];
848
- return {
849
- path,
850
- file_url,
851
- type,
852
- name: typeof File !== "undefined" && blob instanceof File ? blob?.name : void 0
853
- };
854
- })
855
- );
856
- results.forEach(({ path, file_url, type, name }) => {
857
- if (type === "Gallery") {
858
- update_object(data, file_url, path);
859
- } else if (file_url) {
860
- const file = new FileData({ path: file_url, orig_name: name });
861
- update_object(data, file, path);
862
- }
863
- });
864
- return data;
780
+ const self = this;
781
+ await process_local_file_commands(self, data);
782
+ const blobRefs = await walk_and_store_blobs(data, void 0, [], true, api_info);
783
+ (await Promise.all(blobRefs.map(async ({ path, blob, type }) => {
784
+ if (!blob) return {
785
+ path,
786
+ type
787
+ };
788
+ const response = await self.upload_files(endpoint, [blob]);
789
+ return {
790
+ path,
791
+ file_url: response.files && response.files[0],
792
+ type,
793
+ name: typeof File !== "undefined" && blob instanceof File ? blob?.name : void 0
794
+ };
795
+ }))).forEach(({ path, file_url, type, name }) => {
796
+ if (type === "Gallery") update_object(data, file_url, path);
797
+ else if (file_url) update_object(data, new FileData({
798
+ path: file_url,
799
+ orig_name: name
800
+ }), path);
801
+ });
802
+ return data;
865
803
  }
866
- async function process_local_file_commands(client2, data) {
867
- const root = client2.config?.root || client2.config?.root_url;
868
- if (!root) {
869
- throw new Error(ROOT_URL_ERROR_MSG);
870
- }
871
- await recursively_process_commands(client2, data);
804
+ async function process_local_file_commands(client, data) {
805
+ if (!(client.config?.root || client.config?.root_url)) throw new Error(ROOT_URL_ERROR_MSG);
806
+ await recursively_process_commands(client, data);
872
807
  }
873
- async function recursively_process_commands(client2, data, path = []) {
874
- for (const key in data) {
875
- if (data[key] instanceof Command) {
876
- await process_single_command(client2, data, key);
877
- } else if (typeof data[key] === "object" && data[key] !== null) {
878
- await recursively_process_commands(client2, data[key], [...path, key]);
879
- }
880
- }
808
+ async function recursively_process_commands(client, data, path = []) {
809
+ for (const key in data) if (data[key] instanceof Command) await process_single_command(client, data, key);
810
+ else if (typeof data[key] === "object" && data[key] !== null) await recursively_process_commands(client, data[key], [...path, key]);
881
811
  }
882
- async function process_single_command(client2, data, key) {
883
- let cmd_item = data[key];
884
- const root = client2.config?.root || client2.config?.root_url;
885
- if (!root) {
886
- throw new Error(ROOT_URL_ERROR_MSG);
887
- }
888
- try {
889
- let fileBuffer;
890
- let fullPath;
891
- if (typeof process !== "undefined" && process.versions && process.versions.node) {
892
- const fs = await import("fs/promises");
893
- const path = await import("path");
894
- fullPath = path.resolve(process.cwd(), cmd_item.meta.path);
895
- fileBuffer = await fs.readFile(fullPath);
896
- } else {
897
- throw new Error(NODEJS_FS_ERROR_MSG);
898
- }
899
- const file = new Blob([fileBuffer], {
900
- type: "application/octet-stream"
901
- });
902
- const response = await client2.upload_files(root, [file]);
903
- const file_url = response.files && response.files[0];
904
- if (file_url) {
905
- const fileData = new FileData({
906
- path: file_url,
907
- orig_name: cmd_item.meta.name || ""
908
- });
909
- data[key] = fileData;
910
- }
911
- } catch (error) {
912
- console.error(FILE_PROCESSING_ERROR_MSG, error);
913
- }
812
+ async function process_single_command(client, data, key) {
813
+ let cmd_item = data[key];
814
+ const root = client.config?.root || client.config?.root_url;
815
+ if (!root) throw new Error(ROOT_URL_ERROR_MSG);
816
+ try {
817
+ let fileBuffer;
818
+ let fullPath;
819
+ if (typeof process !== "undefined" && process.versions && process.versions.node) {
820
+ const fs = await import("fs/promises");
821
+ fullPath = (await import("path")).resolve(process.cwd(), cmd_item.meta.path);
822
+ fileBuffer = await fs.readFile(fullPath);
823
+ } else throw new Error(NODEJS_FS_ERROR_MSG);
824
+ const file = new Blob([fileBuffer], { type: "application/octet-stream" });
825
+ const response = await client.upload_files(root, [file]);
826
+ const file_url = response.files && response.files[0];
827
+ if (file_url) data[key] = new FileData({
828
+ path: file_url,
829
+ orig_name: cmd_item.meta.name || ""
830
+ });
831
+ } catch (error) {
832
+ console.error(FILE_PROCESSING_ERROR_MSG, error);
833
+ }
914
834
  }
835
+ //#endregion
836
+ //#region src/utils/post_data.ts
915
837
  async function post_data(url, body, additional_headers) {
916
- const headers = { "Content-Type": "application/json" };
917
- if (this.options.token) {
918
- headers.Authorization = `Bearer ${this.options.token}`;
919
- }
920
- try {
921
- var response = await this.fetch(url, {
922
- method: "POST",
923
- body: JSON.stringify(body),
924
- headers: { ...headers, ...additional_headers },
925
- credentials: "include"
926
- });
927
- } catch (e) {
928
- return [{ error: BROKEN_CONNECTION_MSG }, 500];
929
- }
930
- let output;
931
- let status;
932
- try {
933
- output = await response.json();
934
- status = response.status;
935
- } catch (e) {
936
- output = { error: `Could not parse server response: ${e}` };
937
- status = 500;
938
- }
939
- return [output, status];
838
+ const headers = { "Content-Type": "application/json" };
839
+ if (this.options.token) headers.Authorization = `Bearer ${this.options.token}`;
840
+ try {
841
+ var response = await this.fetch(url, {
842
+ method: "POST",
843
+ body: JSON.stringify(body),
844
+ headers: {
845
+ ...headers,
846
+ ...additional_headers
847
+ },
848
+ credentials: this.options.credentials ?? "same-origin"
849
+ });
850
+ } catch (e) {
851
+ return [{ error: BROKEN_CONNECTION_MSG }, 500];
852
+ }
853
+ let output;
854
+ let status;
855
+ try {
856
+ output = await response.json();
857
+ status = response.status;
858
+ } catch (e) {
859
+ output = { error: `Could not parse server response: ${e}` };
860
+ status = 500;
861
+ }
862
+ return [output, status];
940
863
  }
864
+ //#endregion
865
+ //#region src/utils/predict.ts
941
866
  async function predict(endpoint, data = {}) {
942
- let data_returned = false;
943
- let status_complete = false;
944
- if (!this.config) {
945
- throw new Error("Could not resolve app config");
946
- }
947
- if (typeof endpoint === "number") {
948
- this.config.dependencies.find((dep) => dep.id == endpoint);
949
- } else {
950
- const trimmed_endpoint = endpoint.replace(/^\//, "");
951
- this.config.dependencies.find(
952
- (dep) => dep.id == this.api_map[trimmed_endpoint]
953
- );
954
- }
955
- return new Promise(async (resolve, reject) => {
956
- const app = this.submit(endpoint, data, null, null, true);
957
- let result;
958
- for await (const message of app) {
959
- if (message.type === "data") {
960
- if (status_complete) {
961
- resolve(result);
962
- }
963
- data_returned = true;
964
- result = message;
965
- }
966
- if (message.type === "status") {
967
- if (message.stage === "error") reject(message);
968
- if (message.stage === "complete") {
969
- status_complete = true;
970
- if (data_returned) {
971
- resolve(result);
972
- }
973
- }
974
- }
975
- }
976
- });
867
+ let data_returned = false;
868
+ let status_complete = false;
869
+ if (!this.config) throw new Error("Could not resolve app config");
870
+ if (typeof endpoint === "number") this.config.dependencies.find((dep) => dep.id == endpoint);
871
+ else {
872
+ const trimmed_endpoint = endpoint.replace(/^\//, "");
873
+ this.config.dependencies.find((dep) => dep.id == this.api_map[trimmed_endpoint]);
874
+ }
875
+ const app = this.submit(endpoint, data, null, null, true);
876
+ let result;
877
+ for await (const message of app) {
878
+ if (message.type === "data") {
879
+ data_returned = true;
880
+ result = message;
881
+ if (status_complete) return result;
882
+ }
883
+ if (message.type === "status") {
884
+ if (message.stage === "error") {
885
+ const { message: error_message, ...status } = message;
886
+ const error = new Error((typeof error_message === "string" ? error_message : error_message && JSON.stringify(error_message)) || "An unknown error occurred while making a prediction.");
887
+ Object.assign(error, status);
888
+ throw error;
889
+ }
890
+ if (message.stage === "complete") {
891
+ status_complete = true;
892
+ if (data_returned) return result;
893
+ }
894
+ }
895
+ }
896
+ return result;
977
897
  }
898
+ //#endregion
899
+ //#region src/helpers/spaces.ts
978
900
  async function check_space_status(id, type, status_callback) {
979
- let endpoint = type === "subdomain" ? `https://huggingface.co/api/spaces/by-subdomain/${id}` : `https://huggingface.co/api/spaces/${id}`;
980
- let response;
981
- let _status;
982
- try {
983
- response = await fetch(endpoint);
984
- _status = response.status;
985
- if (_status !== 200) {
986
- throw new Error();
987
- }
988
- response = await response.json();
989
- } catch (e) {
990
- status_callback({
991
- status: "error",
992
- load_status: "error",
993
- message: SPACE_STATUS_ERROR_MSG,
994
- detail: "NOT_FOUND"
995
- });
996
- return;
997
- }
998
- if (!response || _status !== 200) return;
999
- const {
1000
- runtime: { stage },
1001
- id: space_name
1002
- } = response;
1003
- switch (stage) {
1004
- case "STOPPED":
1005
- case "SLEEPING":
1006
- status_callback({
1007
- status: "sleeping",
1008
- load_status: "pending",
1009
- message: "Space is asleep. Waking it up...",
1010
- detail: stage
1011
- });
1012
- setTimeout(() => {
1013
- check_space_status(id, type, status_callback);
1014
- }, 1e3);
1015
- break;
1016
- case "PAUSED":
1017
- status_callback({
1018
- status: "paused",
1019
- load_status: "error",
1020
- message: "This space has been paused by the author. If you would like to try this demo, consider duplicating the space.",
1021
- detail: stage,
1022
- discussions_enabled: await discussions_enabled(space_name)
1023
- });
1024
- break;
1025
- case "RUNNING":
1026
- case "RUNNING_BUILDING":
1027
- status_callback({
1028
- status: "running",
1029
- load_status: "complete",
1030
- message: "Space is running.",
1031
- detail: stage
1032
- });
1033
- break;
1034
- case "BUILDING":
1035
- status_callback({
1036
- status: "building",
1037
- load_status: "pending",
1038
- message: "Space is building...",
1039
- detail: stage
1040
- });
1041
- setTimeout(() => {
1042
- check_space_status(id, type, status_callback);
1043
- }, 1e3);
1044
- break;
1045
- case "APP_STARTING":
1046
- status_callback({
1047
- status: "starting",
1048
- load_status: "pending",
1049
- message: "Space is starting...",
1050
- detail: stage
1051
- });
1052
- setTimeout(() => {
1053
- check_space_status(id, type, status_callback);
1054
- }, 1e3);
1055
- break;
1056
- default:
1057
- status_callback({
1058
- status: "space_error",
1059
- load_status: "error",
1060
- message: "This space is experiencing an issue.",
1061
- detail: stage,
1062
- discussions_enabled: await discussions_enabled(space_name)
1063
- });
1064
- break;
1065
- }
901
+ let endpoint = type === "subdomain" ? `https://huggingface.co/api/spaces/by-subdomain/${id}` : `https://huggingface.co/api/spaces/${id}`;
902
+ let response;
903
+ let _status;
904
+ try {
905
+ response = await fetch(endpoint);
906
+ _status = response.status;
907
+ if (_status !== 200) throw new Error();
908
+ response = await response.json();
909
+ } catch (e) {
910
+ status_callback({
911
+ status: "error",
912
+ load_status: "error",
913
+ message: SPACE_STATUS_ERROR_MSG,
914
+ detail: "NOT_FOUND"
915
+ });
916
+ return;
917
+ }
918
+ if (!response || _status !== 200) return;
919
+ const { runtime: { stage }, id: space_name } = response;
920
+ switch (stage) {
921
+ case "STOPPED":
922
+ case "SLEEPING":
923
+ status_callback({
924
+ status: "sleeping",
925
+ load_status: "pending",
926
+ message: "Space is asleep. Waking it up...",
927
+ detail: stage
928
+ });
929
+ setTimeout(() => {
930
+ check_space_status(id, type, status_callback);
931
+ }, 1e3);
932
+ break;
933
+ case "PAUSED":
934
+ status_callback({
935
+ status: "paused",
936
+ load_status: "error",
937
+ message: "This space has been paused by the author. If you would like to try this demo, consider duplicating the space.",
938
+ detail: stage,
939
+ discussions_enabled: await discussions_enabled(space_name)
940
+ });
941
+ break;
942
+ case "RUNNING":
943
+ case "RUNNING_BUILDING":
944
+ status_callback({
945
+ status: "running",
946
+ load_status: "complete",
947
+ message: "Space is running.",
948
+ detail: stage
949
+ });
950
+ break;
951
+ case "BUILDING":
952
+ status_callback({
953
+ status: "building",
954
+ load_status: "pending",
955
+ message: "Space is building...",
956
+ detail: stage
957
+ });
958
+ setTimeout(() => {
959
+ check_space_status(id, type, status_callback);
960
+ }, 1e3);
961
+ break;
962
+ case "APP_STARTING":
963
+ status_callback({
964
+ status: "starting",
965
+ load_status: "pending",
966
+ message: "Space is starting...",
967
+ detail: stage
968
+ });
969
+ setTimeout(() => {
970
+ check_space_status(id, type, status_callback);
971
+ }, 1e3);
972
+ break;
973
+ default:
974
+ status_callback({
975
+ status: "space_error",
976
+ load_status: "error",
977
+ message: "This space is experiencing an issue.",
978
+ detail: stage,
979
+ discussions_enabled: await discussions_enabled(space_name)
980
+ });
981
+ break;
982
+ }
1066
983
  }
1067
- const check_and_wake_space = async (space_id, status_callback) => {
1068
- let retries = 0;
1069
- const max_retries = 12;
1070
- const check_interval = 5e3;
1071
- return new Promise((resolve) => {
1072
- check_space_status(
1073
- space_id,
1074
- RE_SPACE_NAME.test(space_id) ? "space_name" : "subdomain",
1075
- (status) => {
1076
- status_callback(status);
1077
- if (status.status === "running") {
1078
- resolve();
1079
- } else if (status.status === "error" || status.status === "paused" || status.status === "space_error") {
1080
- resolve();
1081
- } else if (status.status === "sleeping" || status.status === "building") {
1082
- if (retries < max_retries) {
1083
- retries++;
1084
- setTimeout(() => {
1085
- check_and_wake_space(space_id, status_callback).then(resolve);
1086
- }, check_interval);
1087
- } else {
1088
- resolve();
1089
- }
1090
- }
1091
- }
1092
- );
1093
- });
984
+ var check_and_wake_space = async (space_id, status_callback) => {
985
+ let retries = 0;
986
+ const max_retries = 12;
987
+ const check_interval = 5e3;
988
+ return new Promise((resolve) => {
989
+ check_space_status(space_id, RE_SPACE_NAME.test(space_id) ? "space_name" : "subdomain", (status) => {
990
+ status_callback(status);
991
+ if (status.status === "running") resolve();
992
+ else if (status.status === "error" || status.status === "paused" || status.status === "space_error") resolve();
993
+ else if (status.status === "sleeping" || status.status === "building") if (retries < max_retries) {
994
+ retries++;
995
+ setTimeout(() => {
996
+ check_and_wake_space(space_id, status_callback).then(resolve);
997
+ }, check_interval);
998
+ } else resolve();
999
+ });
1000
+ });
1094
1001
  };
1095
- const RE_DISABLED_DISCUSSION = /^(?=[^]*\b[dD]iscussions{0,1}\b)(?=[^]*\b[dD]isabled\b)[^]*$/;
1002
+ var RE_DISABLED_DISCUSSION = /^(?=[^]*\b[dD]iscussions{0,1}\b)(?=[^]*\b[dD]isabled\b)[^]*$/;
1096
1003
  async function discussions_enabled(space_id) {
1097
- try {
1098
- const r = await fetch(
1099
- `https://huggingface.co/api/spaces/${space_id}/discussions`,
1100
- {
1101
- method: "HEAD"
1102
- }
1103
- );
1104
- const error = r.headers.get("x-error-message");
1105
- if (!r.ok || error && RE_DISABLED_DISCUSSION.test(error)) return false;
1106
- return true;
1107
- } catch (e) {
1108
- return false;
1109
- }
1004
+ try {
1005
+ const r = await fetch(`https://huggingface.co/api/spaces/${space_id}/discussions`, { method: "HEAD" });
1006
+ const error = r.headers.get("x-error-message");
1007
+ if (!r.ok || error && RE_DISABLED_DISCUSSION.test(error)) return false;
1008
+ return true;
1009
+ } catch (e) {
1010
+ return false;
1011
+ }
1110
1012
  }
1111
1013
  async function get_space_hardware(space_id, token) {
1112
- const headers = {};
1113
- if (token) {
1114
- headers.Authorization = `Bearer ${token}`;
1115
- }
1116
- try {
1117
- const res = await fetch(
1118
- `https://huggingface.co/api/spaces/${space_id}/${RUNTIME_URL}`,
1119
- { headers }
1120
- );
1121
- if (res.status !== 200)
1122
- throw new Error("Space hardware could not be obtained.");
1123
- const { hardware } = await res.json();
1124
- return hardware.current;
1125
- } catch (e) {
1126
- throw new Error(e.message);
1127
- }
1014
+ const headers = {};
1015
+ if (token) headers.Authorization = `Bearer ${token}`;
1016
+ try {
1017
+ const res = await fetch(`https://huggingface.co/api/spaces/${space_id}/${RUNTIME_URL}`, { headers });
1018
+ if (res.status !== 200) throw new Error("Space hardware could not be obtained.");
1019
+ const { hardware } = await res.json();
1020
+ return hardware.current;
1021
+ } catch (e) {
1022
+ throw new Error(e.message);
1023
+ }
1128
1024
  }
1129
1025
  async function set_space_timeout(space_id, timeout, token) {
1130
- const headers = {};
1131
- if (token) {
1132
- headers.Authorization = `Bearer ${token}`;
1133
- }
1134
- const body = {
1135
- seconds: timeout
1136
- };
1137
- try {
1138
- const res = await fetch(
1139
- `https://huggingface.co/api/spaces/${space_id}/${SLEEPTIME_URL}`,
1140
- {
1141
- method: "POST",
1142
- headers: { "Content-Type": "application/json", ...headers },
1143
- body: JSON.stringify(body)
1144
- }
1145
- );
1146
- if (res.status !== 200) {
1147
- throw new Error(
1148
- "Could not set sleep timeout on duplicated Space. Please visit *ADD HF LINK TO SETTINGS* to set a timeout manually to reduce billing charges."
1149
- );
1150
- }
1151
- const response = await res.json();
1152
- return response;
1153
- } catch (e) {
1154
- throw new Error(e.message);
1155
- }
1026
+ const headers = {};
1027
+ if (token) headers.Authorization = `Bearer ${token}`;
1028
+ const body = { seconds: timeout };
1029
+ try {
1030
+ const res = await fetch(`https://huggingface.co/api/spaces/${space_id}/${SLEEPTIME_URL}`, {
1031
+ method: "POST",
1032
+ headers: {
1033
+ "Content-Type": "application/json",
1034
+ ...headers
1035
+ },
1036
+ body: JSON.stringify(body)
1037
+ });
1038
+ if (res.status !== 200) throw new Error("Could not set sleep timeout on duplicated Space. Please visit *ADD HF LINK TO SETTINGS* to set a timeout manually to reduce billing charges.");
1039
+ return await res.json();
1040
+ } catch (e) {
1041
+ throw new Error(e.message);
1042
+ }
1156
1043
  }
1157
- const hardware_types = [
1158
- "cpu-basic",
1159
- "cpu-upgrade",
1160
- "cpu-xl",
1161
- "t4-small",
1162
- "t4-medium",
1163
- "a10g-small",
1164
- "a10g-large",
1165
- "a10g-largex2",
1166
- "a10g-largex4",
1167
- "a100-large",
1168
- "zero-a10g",
1169
- "h100",
1170
- "h100x8"
1044
+ var hardware_types = [
1045
+ "cpu-basic",
1046
+ "cpu-upgrade",
1047
+ "cpu-xl",
1048
+ "t4-small",
1049
+ "t4-medium",
1050
+ "a10g-small",
1051
+ "a10g-large",
1052
+ "a10g-largex2",
1053
+ "a10g-largex4",
1054
+ "a100-large",
1055
+ "zero-a10g",
1056
+ "h100",
1057
+ "h100x8"
1171
1058
  ];
1059
+ //#endregion
1060
+ //#region src/utils/duplicate.ts
1172
1061
  async function duplicate(app_reference, options) {
1173
- const { token, private: _private, hardware, timeout, auth } = options;
1174
- if (hardware && !hardware_types.includes(hardware)) {
1175
- throw new Error(
1176
- `Invalid hardware type provided. Valid types are: ${hardware_types.map((v) => `"${v}"`).join(",")}.`
1177
- );
1178
- }
1179
- const { http_protocol, host } = await process_endpoint(app_reference, token);
1180
- let cookies = null;
1181
- if (auth) {
1182
- const cookie_header = await get_cookie_header(
1183
- http_protocol,
1184
- host,
1185
- auth,
1186
- fetch
1187
- );
1188
- if (cookie_header) cookies = parse_and_set_cookies(cookie_header);
1189
- }
1190
- const headers = {
1191
- Authorization: `Bearer ${token}`,
1192
- "Content-Type": "application/json",
1193
- ...cookies ? { Cookie: cookies.join("; ") } : {}
1194
- };
1195
- const user = (await (await fetch(`https://huggingface.co/api/whoami-v2`, {
1196
- headers
1197
- })).json()).name;
1198
- const space_name = app_reference.split("/")[1];
1199
- const body = {
1200
- repository: `${user}/${space_name}`
1201
- };
1202
- if (_private) {
1203
- body.private = true;
1204
- }
1205
- let original_hardware;
1206
- try {
1207
- if (!hardware) {
1208
- original_hardware = await get_space_hardware(app_reference, token);
1209
- }
1210
- } catch (e) {
1211
- throw Error(SPACE_METADATA_ERROR_MSG + e.message);
1212
- }
1213
- const requested_hardware = hardware || original_hardware || "cpu-basic";
1214
- body.hardware = requested_hardware;
1215
- try {
1216
- const response = await fetch(
1217
- `https://huggingface.co/api/spaces/${app_reference}/duplicate`,
1218
- {
1219
- method: "POST",
1220
- headers,
1221
- body: JSON.stringify(body)
1222
- }
1223
- );
1224
- if (response.status === 409) {
1225
- try {
1226
- const client2 = await Client.connect(`${user}/${space_name}`, options);
1227
- return client2;
1228
- } catch (error) {
1229
- console.error("Failed to connect Client instance:", error);
1230
- throw error;
1231
- }
1232
- } else if (response.status !== 200) {
1233
- throw new Error(response.statusText);
1234
- }
1235
- const duplicated_space = await response.json();
1236
- await set_space_timeout(`${user}/${space_name}`, timeout || 300, token);
1237
- return await Client.connect(
1238
- get_space_reference(duplicated_space.url),
1239
- options
1240
- );
1241
- } catch (e) {
1242
- throw new Error(e);
1243
- }
1062
+ normalise_token_option(options);
1063
+ const { token, private: _private, hardware, timeout, auth } = options;
1064
+ if (hardware && !hardware_types.includes(hardware)) throw new Error(`Invalid hardware type provided. Valid types are: ${hardware_types.map((v) => `"${v}"`).join(",")}.`);
1065
+ const { http_protocol, host } = await process_endpoint(app_reference, token);
1066
+ let cookies = null;
1067
+ if (auth) {
1068
+ const cookie_header = await get_cookie_header(http_protocol, host, auth, fetch, void 0, options.credentials);
1069
+ if (cookie_header) cookies = parse_and_set_cookies(cookie_header);
1070
+ }
1071
+ const headers = {
1072
+ Authorization: `Bearer ${token}`,
1073
+ "Content-Type": "application/json",
1074
+ ...cookies ? { Cookie: cookies.join("; ") } : {}
1075
+ };
1076
+ const user = (await (await fetch(`https://huggingface.co/api/whoami-v2`, { headers })).json()).name;
1077
+ const space_name = app_reference.split("/")[1];
1078
+ const body = { repository: `${user}/${space_name}` };
1079
+ if (_private) body.private = true;
1080
+ let original_hardware;
1081
+ try {
1082
+ if (!hardware) original_hardware = await get_space_hardware(app_reference, token);
1083
+ } catch (e) {
1084
+ throw Error(SPACE_METADATA_ERROR_MSG + e.message);
1085
+ }
1086
+ body.hardware = hardware || original_hardware || "cpu-basic";
1087
+ try {
1088
+ const response = await fetch(`https://huggingface.co/api/spaces/${app_reference}/duplicate`, {
1089
+ method: "POST",
1090
+ headers,
1091
+ body: JSON.stringify(body)
1092
+ });
1093
+ if (response.status === 409) try {
1094
+ return await Client.connect(`${user}/${space_name}`, options);
1095
+ } catch (error) {
1096
+ console.error("Failed to connect Client instance:", error);
1097
+ throw error;
1098
+ }
1099
+ else if (response.status !== 200) throw new Error(response.statusText);
1100
+ const duplicated_space = await response.json();
1101
+ await set_space_timeout(`${user}/${space_name}`, timeout || 300, token);
1102
+ return await Client.connect(get_space_reference(duplicated_space.url), options);
1103
+ } catch (e) {
1104
+ throw new Error(e);
1105
+ }
1244
1106
  }
1245
1107
  function get_space_reference(url) {
1246
- const regex = /https:\/\/huggingface.co\/spaces\/([^/]+\/[^/]+)/;
1247
- const match = url.match(regex);
1248
- if (match) {
1249
- return match[1];
1250
- }
1108
+ const match = url.match(/https:\/\/huggingface.co\/spaces\/([^/]+\/[^/]+)/);
1109
+ if (match) return match[1];
1251
1110
  }
1252
- const ZEROGPU_HEADERS_MESSAGE = "supports-zerogpu-headers";
1253
- let zerogpu_handshake_initialized = false;
1111
+ //#endregion
1112
+ //#region src/helpers/zerogpu.ts
1113
+ var ZEROGPU_HEADERS_MESSAGE = "supports-zerogpu-headers";
1114
+ var zerogpu_handshake_initialized = false;
1254
1115
  function supports_browser_handshake() {
1255
- return typeof window !== "undefined" && typeof document !== "undefined" && typeof window.addEventListener === "function";
1116
+ return typeof window !== "undefined" && typeof document !== "undefined" && typeof window.addEventListener === "function";
1256
1117
  }
1257
1118
  function get_zerogpu_origin(hostname) {
1258
- if (hostname.includes(".dev.")) {
1259
- return `https://moon-${hostname.split(".")[1]}.dev.spaces.huggingface.tech`;
1260
- }
1261
- if (hostname.endsWith(".hf.space")) {
1262
- return "https://huggingface.co";
1263
- }
1264
- return null;
1119
+ if (hostname.includes(".dev.")) return `https://moon-${hostname.split(".")[1]}.dev.spaces.huggingface.tech`;
1120
+ if (hostname.endsWith(".hf.space")) return "https://huggingface.co";
1121
+ return null;
1265
1122
  }
1266
1123
  function initialize_zerogpu_handshake() {
1267
- if (!supports_browser_handshake() || zerogpu_handshake_initialized) {
1268
- return;
1269
- }
1270
- window.addEventListener("message", (event) => {
1271
- if (event.data === ZEROGPU_HEADERS_MESSAGE) {
1272
- window.supports_zerogpu_headers = true;
1273
- }
1274
- });
1275
- zerogpu_handshake_initialized = true;
1276
- const origin = get_zerogpu_origin(window.location.hostname);
1277
- if (origin && window.parent !== window) {
1278
- window.parent.postMessage(ZEROGPU_HEADERS_MESSAGE, origin);
1279
- }
1280
- }
1281
- class TextLineStream extends TransformStream {
1282
- #currentLine = "";
1283
- /** Constructs a new instance. */
1284
- constructor(options = { allowCR: false }) {
1285
- super({
1286
- transform: (chars, controller) => {
1287
- chars = this.#currentLine + chars;
1288
- while (true) {
1289
- const lfIndex = chars.indexOf("\n");
1290
- const crIndex = options.allowCR ? chars.indexOf("\r") : -1;
1291
- if (crIndex !== -1 && crIndex !== chars.length - 1 && (lfIndex === -1 || lfIndex - 1 > crIndex)) {
1292
- controller.enqueue(chars.slice(0, crIndex));
1293
- chars = chars.slice(crIndex + 1);
1294
- continue;
1295
- }
1296
- if (lfIndex === -1)
1297
- break;
1298
- const endIndex = chars[lfIndex - 1] === "\r" ? lfIndex - 1 : lfIndex;
1299
- controller.enqueue(chars.slice(0, endIndex));
1300
- chars = chars.slice(lfIndex + 1);
1301
- }
1302
- this.#currentLine = chars;
1303
- },
1304
- flush: (controller) => {
1305
- if (this.#currentLine === "")
1306
- return;
1307
- const currentLine = options.allowCR && this.#currentLine.endsWith("\r") ? this.#currentLine.slice(0, -1) : this.#currentLine;
1308
- controller.enqueue(currentLine);
1309
- }
1310
- });
1311
- }
1124
+ if (!supports_browser_handshake() || zerogpu_handshake_initialized) return;
1125
+ window.addEventListener("message", (event) => {
1126
+ if (event.data === ZEROGPU_HEADERS_MESSAGE) window.supports_zerogpu_headers = true;
1127
+ });
1128
+ zerogpu_handshake_initialized = true;
1129
+ const origin = get_zerogpu_origin(window.location.hostname);
1130
+ if (origin && window.parent !== window) window.parent.postMessage(ZEROGPU_HEADERS_MESSAGE, origin);
1312
1131
  }
1132
+ //#endregion
1133
+ //#region ../../node_modules/.pnpm/fetch-event-stream@0.1.6/node_modules/fetch-event-stream/esm/deps/jsr.io/@std/streams/0.221.0/text_line_stream.js
1134
+ /**
1135
+ * Transform a stream into a stream where each chunk is divided by a newline,
1136
+ * be it `\n` or `\r\n`. `\r` can be enabled via the `allowCR` option.
1137
+ *
1138
+ * @example
1139
+ * ```ts
1140
+ * import { TextLineStream } from "@std/streams/text-line-stream";
1141
+ *
1142
+ * const res = await fetch("https://example.com");
1143
+ * const lines = res.body!
1144
+ * .pipeThrough(new TextDecoderStream())
1145
+ * .pipeThrough(new TextLineStream());
1146
+ * ```
1147
+ */
1148
+ var TextLineStream = class extends TransformStream {
1149
+ #currentLine = "";
1150
+ /** Constructs a new instance. */
1151
+ constructor(options = { allowCR: false }) {
1152
+ super({
1153
+ transform: (chars, controller) => {
1154
+ chars = this.#currentLine + chars;
1155
+ while (true) {
1156
+ const lfIndex = chars.indexOf("\n");
1157
+ const crIndex = options.allowCR ? chars.indexOf("\r") : -1;
1158
+ if (crIndex !== -1 && crIndex !== chars.length - 1 && (lfIndex === -1 || lfIndex - 1 > crIndex)) {
1159
+ controller.enqueue(chars.slice(0, crIndex));
1160
+ chars = chars.slice(crIndex + 1);
1161
+ continue;
1162
+ }
1163
+ if (lfIndex === -1) break;
1164
+ const endIndex = chars[lfIndex - 1] === "\r" ? lfIndex - 1 : lfIndex;
1165
+ controller.enqueue(chars.slice(0, endIndex));
1166
+ chars = chars.slice(lfIndex + 1);
1167
+ }
1168
+ this.#currentLine = chars;
1169
+ },
1170
+ flush: (controller) => {
1171
+ if (this.#currentLine === "") return;
1172
+ const currentLine = options.allowCR && this.#currentLine.endsWith("\r") ? this.#currentLine.slice(0, -1) : this.#currentLine;
1173
+ controller.enqueue(currentLine);
1174
+ }
1175
+ });
1176
+ }
1177
+ };
1178
+ //#endregion
1179
+ //#region ../../node_modules/.pnpm/fetch-event-stream@0.1.6/node_modules/fetch-event-stream/esm/utils.js
1313
1180
  function stream$1(input) {
1314
- let decoder = new TextDecoderStream();
1315
- let split2 = new TextLineStream({ allowCR: true });
1316
- return input.pipeThrough(decoder).pipeThrough(split2);
1181
+ let decoder = new TextDecoderStream();
1182
+ let split = new TextLineStream({ allowCR: true });
1183
+ return input.pipeThrough(decoder).pipeThrough(split);
1317
1184
  }
1318
1185
  function split(input) {
1319
- let rgx = /[:]\s*/;
1320
- let match = rgx.exec(input);
1321
- let idx = match && match.index;
1322
- if (idx) {
1323
- return [
1324
- input.substring(0, idx),
1325
- input.substring(idx + match[0].length)
1326
- ];
1327
- }
1186
+ let match = /[:]\s*/.exec(input);
1187
+ let idx = match && match.index;
1188
+ if (idx) return [input.substring(0, idx), input.substring(idx + match[0].length)];
1328
1189
  }
1329
1190
  function fallback(headers, key, value) {
1330
- let tmp = headers.get(key);
1331
- if (!tmp)
1332
- headers.set(key, value);
1191
+ if (!headers.get(key)) headers.set(key, value);
1333
1192
  }
1193
+ //#endregion
1194
+ //#region ../../node_modules/.pnpm/fetch-event-stream@0.1.6/node_modules/fetch-event-stream/esm/mod.js
1195
+ /**
1196
+ * Convert a `Response` body containing Server Sent Events (SSE) into an Async Iterator that yields {@linkcode ServerSentEventMessage} objects.
1197
+ *
1198
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events}
1199
+ *
1200
+ * @example
1201
+ * ```js
1202
+ * // Optional
1203
+ * let abort = new AbortController;
1204
+ *
1205
+ * // Manually fetch a Response
1206
+ * let res = await fetch('https://...', {
1207
+ * method: 'POST',
1208
+ * signal: abort.signal,
1209
+ * headers: {
1210
+ * 'api-key': 'token <value>',
1211
+ * 'content-type': 'application/json',
1212
+ * },
1213
+ * body: JSON.stringify({
1214
+ * stream: true, // <- hypothetical
1215
+ * // ...
1216
+ * })
1217
+ * });
1218
+ *
1219
+ * if (res.ok) {
1220
+ * let stream = events(res, abort.signal);
1221
+ * for await (let event of stream) {
1222
+ * console.log('<<', event.data);
1223
+ * }
1224
+ * }
1225
+ * ```
1226
+ */
1334
1227
  async function* events(res, signal) {
1335
- if (!res.body)
1336
- return;
1337
- let iter = stream$1(res.body);
1338
- let line, reader = iter.getReader();
1339
- let event;
1340
- for (; ; ) {
1341
- if (signal && signal.aborted) {
1342
- return reader.cancel();
1343
- }
1344
- line = await reader.read();
1345
- if (line.done)
1346
- return;
1347
- if (!line.value) {
1348
- if (event)
1349
- yield event;
1350
- event = void 0;
1351
- continue;
1352
- }
1353
- let [field, value] = split(line.value) || [];
1354
- if (field === "data") {
1355
- event ||= {};
1356
- event[field] = event[field] ? event[field] + "\n" + value : value;
1357
- } else if (field === "event") {
1358
- event ||= {};
1359
- event[field] = value;
1360
- } else if (field === "id") {
1361
- event ||= {};
1362
- event[field] = String(+value) === value ? +value : value;
1363
- } else if (field === "retry") {
1364
- event ||= {};
1365
- event[field] = +value || void 0;
1366
- }
1367
- }
1228
+ if (!res.body) return;
1229
+ let iter = stream$1(res.body);
1230
+ let line, reader = iter.getReader();
1231
+ let event;
1232
+ for (;;) {
1233
+ if (signal && signal.aborted) return reader.cancel();
1234
+ line = await reader.read();
1235
+ if (line.done) return;
1236
+ if (!line.value) {
1237
+ if (event) yield event;
1238
+ event = void 0;
1239
+ continue;
1240
+ }
1241
+ let [field, value] = split(line.value) || [];
1242
+ if (field === "data") {
1243
+ event ||= {};
1244
+ event[field] = event[field] ? event[field] + "\n" + value : value;
1245
+ } else if (field === "event") {
1246
+ event ||= {};
1247
+ event[field] = value;
1248
+ } else if (field === "id") {
1249
+ event ||= {};
1250
+ event[field] = String(+value) === value ? +value : value;
1251
+ } else if (field === "retry") {
1252
+ event ||= {};
1253
+ event[field] = +value || void 0;
1254
+ }
1255
+ }
1368
1256
  }
1257
+ /**
1258
+ * Convenience function that will `fetch` with the given arguments and, if ok, will return the {@linkcode events} async iterator.
1259
+ *
1260
+ * If the response is not ok (status 200-299), the `Response` is thrown.
1261
+ *
1262
+ * @example
1263
+ * ```js
1264
+ * // NOTE: throws `Response` if not 2xx status
1265
+ * let events = await stream('https://api.openai.com/...', {
1266
+ * method: 'POST',
1267
+ * headers: {
1268
+ * 'Authorization': 'Bearer <token>',
1269
+ * 'Content-Type': 'application/json',
1270
+ * },
1271
+ * body: JSON.stringify({
1272
+ * stream: true,
1273
+ * // ...
1274
+ * })
1275
+ * });
1276
+ *
1277
+ * for await (let event of events) {
1278
+ * console.log('<<', JSON.parse(event.data));
1279
+ * }
1280
+ * ```
1281
+ */
1369
1282
  async function stream(input, init) {
1370
- let req = new Request(input, init);
1371
- fallback(req.headers, "Accept", "text/event-stream");
1372
- fallback(req.headers, "Content-Type", "application/json");
1373
- let r = await fetch(req);
1374
- if (!r.ok)
1375
- throw r;
1376
- return events(r, req.signal);
1283
+ let req = new Request(input, init);
1284
+ fallback(req.headers, "Accept", "text/event-stream");
1285
+ fallback(req.headers, "Content-Type", "application/json");
1286
+ let r = await fetch(req);
1287
+ if (!r.ok) throw r;
1288
+ return events(r, req.signal);
1377
1289
  }
1290
+ //#endregion
1291
+ //#region src/utils/stream.ts
1378
1292
  async function open_stream() {
1379
- let {
1380
- event_callbacks,
1381
- unclosed_events,
1382
- pending_stream_messages,
1383
- stream_status,
1384
- config,
1385
- jwt
1386
- } = this;
1387
- const that = this;
1388
- if (!config) {
1389
- throw new Error("Could not resolve app config");
1390
- }
1391
- stream_status.open = true;
1392
- let stream2 = null;
1393
- let params = new URLSearchParams({
1394
- session_hash: this.session_hash
1395
- }).toString();
1396
- let url = new URL(`${config.root}${this.api_prefix}/${SSE_URL}?${params}`);
1397
- if (jwt) {
1398
- url.searchParams.set("__sign", jwt);
1399
- }
1400
- stream2 = this.stream(url);
1401
- if (!stream2) {
1402
- console.warn("Cannot connect to SSE endpoint: " + url.toString());
1403
- return;
1404
- }
1405
- stream2.onmessage = async function(event) {
1406
- let _data = JSON.parse(event.data);
1407
- if (_data.msg === "close_stream") {
1408
- close_stream(stream_status, that.abort_controller);
1409
- return;
1410
- }
1411
- const event_id = _data.event_id;
1412
- if (!event_id) {
1413
- await Promise.all(
1414
- Object.keys(event_callbacks).map(
1415
- (event_id2) => event_callbacks[event_id2](_data)
1416
- )
1417
- );
1418
- } else if (event_callbacks[event_id] && config) {
1419
- if (_data.msg === "process_completed" && ["sse", "sse_v1", "sse_v2", "sse_v2.1", "sse_v3"].includes(
1420
- config.protocol
1421
- )) {
1422
- unclosed_events.delete(event_id);
1423
- }
1424
- let fn = event_callbacks[event_id];
1425
- if (typeof window !== "undefined" && typeof document !== "undefined") {
1426
- setTimeout(fn, 0, _data);
1427
- } else {
1428
- fn(_data);
1429
- }
1430
- } else {
1431
- if (!pending_stream_messages[event_id]) {
1432
- pending_stream_messages[event_id] = [];
1433
- }
1434
- pending_stream_messages[event_id].push(_data);
1435
- }
1436
- };
1437
- stream2.onerror = async function(e) {
1438
- console.error(e);
1439
- await Promise.all(
1440
- Object.keys(event_callbacks).map(
1441
- (event_id) => event_callbacks[event_id]({
1442
- msg: "broken_connection",
1443
- message: BROKEN_CONNECTION_MSG
1444
- })
1445
- )
1446
- );
1447
- };
1293
+ let { event_callbacks, unclosed_events, pending_stream_messages, stream_status, config, jwt } = this;
1294
+ const that = this;
1295
+ if (!config) throw new Error("Could not resolve app config");
1296
+ stream_status.open = true;
1297
+ let stream = null;
1298
+ let params = new URLSearchParams({ session_hash: this.session_hash }).toString();
1299
+ let url = new URL(`${config.root}${this.api_prefix}/${SSE_URL}?${params}`);
1300
+ if (jwt) url.searchParams.set("__sign", jwt);
1301
+ stream = this.stream(url);
1302
+ if (!stream) {
1303
+ console.warn("Cannot connect to SSE endpoint: " + url.toString());
1304
+ return;
1305
+ }
1306
+ stream.onmessage = async function(event) {
1307
+ let _data = JSON.parse(event.data);
1308
+ if (_data.msg === "close_stream") {
1309
+ close_stream(stream_status, that.abort_controller);
1310
+ return;
1311
+ }
1312
+ const event_id = _data.event_id;
1313
+ if (!event_id) await Promise.all(Object.keys(event_callbacks).map((event_id) => event_callbacks[event_id](_data)));
1314
+ else if (event_callbacks[event_id] && config) {
1315
+ if (_data.msg === "process_completed" && [
1316
+ "sse",
1317
+ "sse_v1",
1318
+ "sse_v2",
1319
+ "sse_v2.1",
1320
+ "sse_v3"
1321
+ ].includes(config.protocol)) unclosed_events.delete(event_id);
1322
+ let fn = event_callbacks[event_id];
1323
+ if (typeof window !== "undefined" && typeof document !== "undefined" && document.visibilityState !== "hidden") setTimeout(fn, 0, _data);
1324
+ else fn(_data);
1325
+ } else {
1326
+ if (!pending_stream_messages[event_id]) pending_stream_messages[event_id] = [];
1327
+ pending_stream_messages[event_id].push(_data);
1328
+ }
1329
+ };
1330
+ stream.onerror = async function(e) {
1331
+ console.error(e);
1332
+ await Promise.all(Object.keys(event_callbacks).map((event_id) => event_callbacks[event_id]({
1333
+ msg: "broken_connection",
1334
+ message: BROKEN_CONNECTION_MSG
1335
+ })));
1336
+ };
1448
1337
  }
1449
1338
  function close_stream(stream_status, abort_controller) {
1450
- if (stream_status) {
1451
- stream_status.open = false;
1452
- abort_controller?.abort();
1453
- }
1339
+ if (stream_status) {
1340
+ stream_status.open = false;
1341
+ abort_controller?.abort();
1342
+ }
1454
1343
  }
1455
1344
  function apply_diff_stream(pending_diff_streams, event_id, data) {
1456
- let is_first_generation = !pending_diff_streams[event_id];
1457
- if (is_first_generation) {
1458
- pending_diff_streams[event_id] = [];
1459
- data.data.forEach((value, i) => {
1460
- pending_diff_streams[event_id][i] = value;
1461
- });
1462
- } else {
1463
- data.data.forEach((value, i) => {
1464
- let new_data = apply_diff(pending_diff_streams[event_id][i], value);
1465
- pending_diff_streams[event_id][i] = new_data;
1466
- data.data[i] = new_data;
1467
- });
1468
- }
1345
+ if (!pending_diff_streams[event_id]) {
1346
+ pending_diff_streams[event_id] = [];
1347
+ data.data.forEach((value, i) => {
1348
+ pending_diff_streams[event_id][i] = value;
1349
+ });
1350
+ } else data.data.forEach((value, i) => {
1351
+ let new_data = apply_diff(i < pending_diff_streams[event_id].length ? pending_diff_streams[event_id][i] : null, value);
1352
+ pending_diff_streams[event_id][i] = new_data;
1353
+ data.data[i] = new_data;
1354
+ });
1469
1355
  }
1470
1356
  function apply_diff(obj, diff) {
1471
- diff.forEach(([action, path, value]) => {
1472
- obj = apply_edit(obj, path, action, value);
1473
- });
1474
- return obj;
1357
+ diff.forEach(([action, path, value]) => {
1358
+ obj = apply_edit(obj, path, action, value);
1359
+ });
1360
+ return obj;
1475
1361
  }
1476
1362
  function apply_edit(target, path, action, value) {
1477
- if (path.length === 0) {
1478
- if (action === "replace") {
1479
- return value;
1480
- } else if (action === "append") {
1481
- return target + value;
1482
- }
1483
- throw new Error(`Unsupported action: ${action}`);
1484
- }
1485
- let current = target;
1486
- for (let i = 0; i < path.length - 1; i++) {
1487
- current = current[path[i]];
1488
- }
1489
- const last_path = path[path.length - 1];
1490
- switch (action) {
1491
- case "replace":
1492
- current[last_path] = value;
1493
- break;
1494
- case "append":
1495
- current[last_path] += value;
1496
- break;
1497
- case "add":
1498
- if (Array.isArray(current)) {
1499
- current.splice(Number(last_path), 0, value);
1500
- } else {
1501
- current[last_path] = value;
1502
- }
1503
- break;
1504
- case "delete":
1505
- if (Array.isArray(current)) {
1506
- current.splice(Number(last_path), 1);
1507
- } else {
1508
- delete current[last_path];
1509
- }
1510
- break;
1511
- default:
1512
- throw new Error(`Unknown action: ${action}`);
1513
- }
1514
- return target;
1363
+ if (path.length === 0) {
1364
+ if (action === "replace") return value;
1365
+ else if (action === "append") return target + value;
1366
+ throw new Error(`Unsupported action: ${action}`);
1367
+ }
1368
+ let current = target;
1369
+ for (let i = 0; i < path.length - 1; i++) current = current[path[i]];
1370
+ const last_path = path[path.length - 1];
1371
+ switch (action) {
1372
+ case "replace":
1373
+ current[last_path] = value;
1374
+ break;
1375
+ case "append":
1376
+ current[last_path] += value;
1377
+ break;
1378
+ case "add":
1379
+ if (Array.isArray(current)) current.splice(Number(last_path), 0, value);
1380
+ else current[last_path] = value;
1381
+ break;
1382
+ case "delete":
1383
+ if (Array.isArray(current)) current.splice(Number(last_path), 1);
1384
+ else delete current[last_path];
1385
+ break;
1386
+ default: throw new Error(`Unknown action: ${action}`);
1387
+ }
1388
+ return target;
1515
1389
  }
1516
1390
  function readable_stream(input, init = {}) {
1517
- const instance = {
1518
- close: () => {
1519
- console.warn("Method not implemented.");
1520
- },
1521
- onerror: null,
1522
- onmessage: null,
1523
- onopen: null,
1524
- readyState: 0,
1525
- url: input.toString(),
1526
- withCredentials: false,
1527
- CONNECTING: 0,
1528
- OPEN: 1,
1529
- CLOSED: 2,
1530
- addEventListener: () => {
1531
- throw new Error("Method not implemented.");
1532
- },
1533
- dispatchEvent: () => {
1534
- throw new Error("Method not implemented.");
1535
- },
1536
- removeEventListener: () => {
1537
- throw new Error("Method not implemented.");
1538
- }
1539
- };
1540
- stream(input, init).then(async (res) => {
1541
- instance.readyState = instance.OPEN;
1542
- try {
1543
- for await (const chunk of res) {
1544
- instance.onmessage && instance.onmessage(chunk);
1545
- }
1546
- instance.readyState = instance.CLOSED;
1547
- } catch (e) {
1548
- instance.onerror && instance.onerror(e);
1549
- instance.readyState = instance.CLOSED;
1550
- }
1551
- }).catch((e) => {
1552
- console.error(e);
1553
- instance.onerror && instance.onerror(e);
1554
- instance.readyState = instance.CLOSED;
1555
- });
1556
- return instance;
1391
+ const instance = {
1392
+ close: () => {
1393
+ console.warn("Method not implemented.");
1394
+ },
1395
+ onerror: null,
1396
+ onmessage: null,
1397
+ onopen: null,
1398
+ readyState: 0,
1399
+ url: input.toString(),
1400
+ withCredentials: false,
1401
+ CONNECTING: 0,
1402
+ OPEN: 1,
1403
+ CLOSED: 2,
1404
+ addEventListener: () => {
1405
+ throw new Error("Method not implemented.");
1406
+ },
1407
+ dispatchEvent: () => {
1408
+ throw new Error("Method not implemented.");
1409
+ },
1410
+ removeEventListener: () => {
1411
+ throw new Error("Method not implemented.");
1412
+ }
1413
+ };
1414
+ stream(input, init).then(async (res) => {
1415
+ instance.readyState = instance.OPEN;
1416
+ try {
1417
+ for await (const chunk of res) instance.onmessage && instance.onmessage(chunk);
1418
+ instance.readyState = instance.CLOSED;
1419
+ } catch (e) {
1420
+ instance.onerror && instance.onerror(e);
1421
+ instance.readyState = instance.CLOSED;
1422
+ }
1423
+ }).catch((e) => {
1424
+ console.error(e);
1425
+ instance.onerror && instance.onerror(e);
1426
+ instance.readyState = instance.CLOSED;
1427
+ });
1428
+ return instance;
1557
1429
  }
1430
+ //#endregion
1431
+ //#region src/utils/submit.ts
1558
1432
  function submit(endpoint, data = {}, event_data, trigger_id, all_events, additional_headers) {
1559
- try {
1560
- let fire_event = function(event) {
1561
- if (all_events || events_to_publish[event.type]) {
1562
- push_event(event);
1563
- }
1564
- }, close = function() {
1565
- done = true;
1566
- while (resolvers.length > 0)
1567
- resolvers.shift()({
1568
- value: void 0,
1569
- done: true
1570
- });
1571
- }, push = function(data2) {
1572
- if (resolvers.length > 0) {
1573
- resolvers.shift()(data2);
1574
- } else {
1575
- values.push(data2);
1576
- }
1577
- }, push_error = function(error) {
1578
- push(thenable_reject(error));
1579
- close();
1580
- }, push_event = function(event) {
1581
- push({ value: event, done: false });
1582
- }, next = function() {
1583
- if (values.length > 0) {
1584
- return Promise.resolve(values.shift());
1585
- }
1586
- if (done) {
1587
- return Promise.resolve({ value: void 0, done: true });
1588
- }
1589
- return new Promise((resolve) => resolvers.push(resolve));
1590
- };
1591
- const { token } = this.options;
1592
- const {
1593
- fetch: fetch2,
1594
- app_reference,
1595
- config,
1596
- session_hash,
1597
- api_info,
1598
- api_map,
1599
- stream_status,
1600
- pending_stream_messages,
1601
- pending_diff_streams,
1602
- event_callbacks,
1603
- unclosed_events,
1604
- post_data: post_data2,
1605
- options,
1606
- api_prefix
1607
- } = this;
1608
- const addt_headers = additional_headers || { "x-gradio-user": "api" };
1609
- const that = this;
1610
- if (!api_info) throw new Error("No API found");
1611
- if (!config) throw new Error("Could not resolve app config");
1612
- let { fn_index, endpoint_info, dependency } = get_endpoint_info(
1613
- api_info,
1614
- endpoint,
1615
- api_map,
1616
- config
1617
- );
1618
- let resolved_data = map_data_to_params(data, endpoint_info);
1619
- let stream2;
1620
- let protocol = config.protocol ?? "ws";
1621
- if (protocol === "ws") {
1622
- throw new Error("WebSocket protocol is not supported in this version");
1623
- }
1624
- let event_id_final = "";
1625
- let event_id_cb = () => event_id_final;
1626
- const _endpoint = typeof endpoint === "number" ? "/predict" : endpoint;
1627
- let payload;
1628
- let event_id = null;
1629
- let complete = false;
1630
- let last_status = {};
1631
- let url_params = typeof window !== "undefined" && typeof document !== "undefined" ? new URLSearchParams(window.location.search).toString() : "";
1632
- const events_to_publish = options?.events?.reduce(
1633
- (acc, event) => {
1634
- acc[event] = true;
1635
- return acc;
1636
- },
1637
- {}
1638
- ) || {};
1639
- async function cancel() {
1640
- let reset_request = {};
1641
- let cancel_request = {};
1642
- reset_request = { event_id };
1643
- cancel_request = { event_id, session_hash, fn_index };
1644
- try {
1645
- if (!config) {
1646
- throw new Error("Could not resolve app config");
1647
- }
1648
- if ("event_id" in cancel_request) {
1649
- await fetch2(`${config.root}${api_prefix}/${CANCEL_URL}`, {
1650
- headers: { "Content-Type": "application/json" },
1651
- method: "POST",
1652
- body: JSON.stringify(cancel_request)
1653
- });
1654
- }
1655
- await fetch2(`${config.root}${api_prefix}/${RESET_URL}`, {
1656
- headers: { "Content-Type": "application/json" },
1657
- method: "POST",
1658
- body: JSON.stringify(reset_request)
1659
- });
1660
- } catch (e) {
1661
- console.warn(
1662
- "The `/reset` endpoint could not be called. Subsequent endpoint results may be unreliable."
1663
- );
1664
- }
1665
- }
1666
- const resolve_heartbeat = async (config2) => {
1667
- await this._resolve_heartbeat(config2);
1668
- };
1669
- async function handle_render_config(render_config) {
1670
- if (!config) return;
1671
- let render_id = render_config.render_id;
1672
- config.components = [
1673
- ...config.components.filter((c) => c.props.rendered_in !== render_id),
1674
- ...render_config.components
1675
- ];
1676
- config.dependencies = [
1677
- ...config.dependencies.filter((d) => d.rendered_in !== render_id),
1678
- ...render_config.dependencies
1679
- ];
1680
- const any_state = config.components.some((c) => c.type === "state");
1681
- const any_unload = config.dependencies.some(
1682
- (d) => d.targets.some((t) => t[1] === "unload")
1683
- );
1684
- config.connect_heartbeat = any_state || any_unload;
1685
- await resolve_heartbeat(config);
1686
- fire_event({
1687
- type: "render",
1688
- data: render_config,
1689
- endpoint: _endpoint,
1690
- fn_index
1691
- });
1692
- }
1693
- const job = this.handle_blob(
1694
- config.root,
1695
- resolved_data,
1696
- endpoint_info
1697
- ).then(async (_payload) => {
1698
- let input_data = handle_payload(
1699
- _payload,
1700
- dependency,
1701
- config.components,
1702
- "input",
1703
- true
1704
- );
1705
- payload = {
1706
- data: input_data || [],
1707
- event_data,
1708
- fn_index,
1709
- trigger_id
1710
- };
1711
- if (skip_queue(fn_index, config)) {
1712
- fire_event({
1713
- type: "status",
1714
- endpoint: _endpoint,
1715
- stage: "pending",
1716
- queue: false,
1717
- fn_index,
1718
- time: /* @__PURE__ */ new Date()
1719
- });
1720
- post_data2(
1721
- `${config.root}${api_prefix}/run${_endpoint.startsWith("/") ? _endpoint : `/${_endpoint}`}${url_params ? "?" + url_params : ""}`,
1722
- {
1723
- ...payload,
1724
- session_hash
1725
- },
1726
- addt_headers
1727
- ).then(async ([output, status_code]) => {
1728
- const data2 = output.data;
1729
- if (status_code == 200) {
1730
- fire_event({
1731
- type: "data",
1732
- endpoint: _endpoint,
1733
- fn_index,
1734
- data: handle_payload(
1735
- data2,
1736
- dependency,
1737
- config.components,
1738
- "output",
1739
- options.with_null_state
1740
- ),
1741
- time: /* @__PURE__ */ new Date(),
1742
- event_data,
1743
- trigger_id
1744
- });
1745
- if (output.render_config) {
1746
- await handle_render_config(output.render_config);
1747
- }
1748
- fire_event({
1749
- type: "status",
1750
- endpoint: _endpoint,
1751
- fn_index,
1752
- stage: "complete",
1753
- eta: output.average_duration,
1754
- queue: false,
1755
- time: /* @__PURE__ */ new Date()
1756
- });
1757
- } else {
1758
- const is_connection_error = output?.error === BROKEN_CONNECTION_MSG;
1759
- fire_event({
1760
- type: "status",
1761
- stage: "error",
1762
- endpoint: _endpoint,
1763
- fn_index,
1764
- message: output.error,
1765
- broken: is_connection_error,
1766
- queue: false,
1767
- time: /* @__PURE__ */ new Date()
1768
- });
1769
- }
1770
- }).catch((e) => {
1771
- fire_event({
1772
- type: "status",
1773
- stage: "error",
1774
- message: e.message,
1775
- endpoint: _endpoint,
1776
- fn_index,
1777
- queue: false,
1778
- time: /* @__PURE__ */ new Date()
1779
- });
1780
- });
1781
- } else if (protocol == "sse") {
1782
- fire_event({
1783
- type: "status",
1784
- stage: "pending",
1785
- queue: true,
1786
- endpoint: _endpoint,
1787
- fn_index,
1788
- time: /* @__PURE__ */ new Date()
1789
- });
1790
- var params = new URLSearchParams({
1791
- fn_index: fn_index.toString(),
1792
- session_hash
1793
- }).toString();
1794
- let url = new URL(
1795
- `${config.root}${api_prefix}/${SSE_URL}?${url_params ? url_params + "&" : ""}${params}`
1796
- );
1797
- if (this.jwt) {
1798
- url.searchParams.set("__sign", this.jwt);
1799
- }
1800
- stream2 = this.stream(url);
1801
- if (!stream2) {
1802
- return Promise.reject(
1803
- new Error("Cannot connect to SSE endpoint: " + url.toString())
1804
- );
1805
- }
1806
- stream2.onmessage = async function(event) {
1807
- const _data = JSON.parse(event.data);
1808
- const { type, status, data: data2 } = handle_message(
1809
- _data,
1810
- last_status[fn_index]
1811
- );
1812
- if (type === "update" && status && !complete) {
1813
- fire_event({
1814
- type: "status",
1815
- endpoint: _endpoint,
1816
- fn_index,
1817
- time: /* @__PURE__ */ new Date(),
1818
- ...status
1819
- });
1820
- if (status.stage === "error") {
1821
- stream2?.close();
1822
- close();
1823
- }
1824
- } else if (type === "data") {
1825
- let [_, status2] = await post_data2(
1826
- `${config.root}${api_prefix}/queue/data`,
1827
- {
1828
- ...payload,
1829
- session_hash,
1830
- event_id
1831
- }
1832
- );
1833
- if (status2 !== 200) {
1834
- fire_event({
1835
- type: "status",
1836
- stage: "error",
1837
- message: BROKEN_CONNECTION_MSG,
1838
- queue: true,
1839
- endpoint: _endpoint,
1840
- fn_index,
1841
- time: /* @__PURE__ */ new Date()
1842
- });
1843
- stream2?.close();
1844
- close();
1845
- }
1846
- } else if (type === "complete") {
1847
- complete = status;
1848
- } else if (type === "log") {
1849
- fire_event({
1850
- type: "log",
1851
- title: data2.title,
1852
- log: data2.log,
1853
- level: data2.level,
1854
- endpoint: _endpoint,
1855
- duration: data2.duration,
1856
- visible: data2.visible,
1857
- fn_index
1858
- });
1859
- } else if (type === "generating" || type === "streaming") {
1860
- fire_event({
1861
- type: "status",
1862
- time: /* @__PURE__ */ new Date(),
1863
- ...status,
1864
- stage: status?.stage,
1865
- queue: true,
1866
- endpoint: _endpoint,
1867
- fn_index
1868
- });
1869
- }
1870
- if (data2) {
1871
- fire_event({
1872
- type: "data",
1873
- time: /* @__PURE__ */ new Date(),
1874
- data: handle_payload(
1875
- data2.data,
1876
- dependency,
1877
- config.components,
1878
- "output",
1879
- options.with_null_state
1880
- ),
1881
- endpoint: _endpoint,
1882
- fn_index,
1883
- event_data,
1884
- trigger_id
1885
- });
1886
- if (complete) {
1887
- fire_event({
1888
- type: "status",
1889
- time: /* @__PURE__ */ new Date(),
1890
- ...complete,
1891
- stage: status?.stage,
1892
- queue: true,
1893
- endpoint: _endpoint,
1894
- fn_index
1895
- });
1896
- stream2?.close();
1897
- close();
1898
- }
1899
- }
1900
- };
1901
- } else if (protocol == "sse_v1" || protocol == "sse_v2" || protocol == "sse_v2.1" || protocol == "sse_v3") {
1902
- fire_event({
1903
- type: "status",
1904
- stage: "pending",
1905
- queue: true,
1906
- endpoint: _endpoint,
1907
- fn_index,
1908
- time: /* @__PURE__ */ new Date()
1909
- });
1910
- let hostname = "";
1911
- if (typeof window !== "undefined" && typeof document !== "undefined") {
1912
- hostname = window?.location?.hostname;
1913
- }
1914
- const origin = get_zerogpu_origin(hostname);
1915
- const is_zerogpu_iframe = typeof window !== "undefined" && typeof document !== "undefined" && window.parent != window && !!origin && window.supports_zerogpu_headers;
1916
- const zerogpu_auth_promise = is_zerogpu_iframe ? post_message("zerogpu-headers", origin) : Promise.resolve(null);
1917
- const post_data_promise = zerogpu_auth_promise.then((headers) => {
1918
- const combined_headers = { ...addt_headers, ...headers || {} };
1919
- return post_data2(
1920
- `${config.root}${api_prefix}/${SSE_DATA_URL}?${url_params}`,
1921
- {
1922
- ...payload,
1923
- session_hash
1924
- },
1925
- combined_headers
1926
- );
1927
- });
1928
- return post_data_promise.then(async ([response, status]) => {
1929
- if (response.event_id) {
1930
- event_id_final = response.event_id;
1931
- }
1932
- if (status === 503) {
1933
- fire_event({
1934
- type: "status",
1935
- stage: "error",
1936
- message: QUEUE_FULL_MSG,
1937
- queue: true,
1938
- endpoint: _endpoint,
1939
- fn_index,
1940
- time: /* @__PURE__ */ new Date(),
1941
- visible: true
1942
- });
1943
- close();
1944
- } else if (status === 422) {
1945
- fire_event({
1946
- type: "status",
1947
- stage: "error",
1948
- message: response.detail,
1949
- queue: true,
1950
- endpoint: _endpoint,
1951
- fn_index,
1952
- code: "validation_error",
1953
- time: /* @__PURE__ */ new Date(),
1954
- visible: true
1955
- });
1956
- close();
1957
- } else if (status !== 200) {
1958
- const is_connection_error = response?.error === BROKEN_CONNECTION_MSG;
1959
- fire_event({
1960
- type: "status",
1961
- stage: "error",
1962
- broken: is_connection_error,
1963
- message: is_connection_error ? BROKEN_CONNECTION_MSG : response.detail || response.error,
1964
- queue: true,
1965
- endpoint: _endpoint,
1966
- fn_index,
1967
- time: /* @__PURE__ */ new Date(),
1968
- visible: true
1969
- });
1970
- close();
1971
- } else {
1972
- event_id = response.event_id;
1973
- event_id_final = event_id;
1974
- let callback = async function(_data) {
1975
- try {
1976
- const { type, status: status2, data: data2, original_msg } = handle_message(
1977
- _data,
1978
- last_status[fn_index]
1979
- );
1980
- if (type == "heartbeat") {
1981
- return;
1982
- }
1983
- if (type === "update" && status2 && !complete) {
1984
- fire_event({
1985
- type: "status",
1986
- endpoint: _endpoint,
1987
- fn_index,
1988
- time: /* @__PURE__ */ new Date(),
1989
- original_msg,
1990
- ...status2
1991
- });
1992
- } else if (type === "complete") {
1993
- complete = status2;
1994
- } else if (type == "unexpected_error" || type == "broken_connection") {
1995
- console.error("Unexpected error", status2?.message);
1996
- const broken = type === "broken_connection";
1997
- fire_event({
1998
- type: "status",
1999
- stage: "error",
2000
- message: status2?.message || "An Unexpected Error Occurred!",
2001
- queue: true,
2002
- endpoint: _endpoint,
2003
- broken,
2004
- session_not_found: status2?.session_not_found,
2005
- fn_index,
2006
- time: /* @__PURE__ */ new Date()
2007
- });
2008
- } else if (type === "log") {
2009
- fire_event({
2010
- type: "log",
2011
- title: data2.title,
2012
- log: data2.log,
2013
- level: data2.level,
2014
- endpoint: _endpoint,
2015
- duration: data2.duration,
2016
- visible: data2.visible,
2017
- fn_index
2018
- });
2019
- return;
2020
- } else if (type === "generating" || type === "streaming") {
2021
- fire_event({
2022
- type: "status",
2023
- time: /* @__PURE__ */ new Date(),
2024
- ...status2,
2025
- stage: status2?.stage,
2026
- queue: true,
2027
- endpoint: _endpoint,
2028
- fn_index
2029
- });
2030
- if (data2 && dependency.connection !== "stream" && ["sse_v2", "sse_v2.1", "sse_v3"].includes(protocol)) {
2031
- apply_diff_stream(pending_diff_streams, event_id, data2);
2032
- }
2033
- }
2034
- if (data2) {
2035
- fire_event({
2036
- type: "data",
2037
- time: /* @__PURE__ */ new Date(),
2038
- data: handle_payload(
2039
- data2.data,
2040
- dependency,
2041
- config.components,
2042
- "output",
2043
- options.with_null_state
2044
- ),
2045
- endpoint: _endpoint,
2046
- fn_index
2047
- });
2048
- if (data2.render_config) {
2049
- await handle_render_config(data2.render_config);
2050
- }
2051
- if (complete) {
2052
- fire_event({
2053
- type: "status",
2054
- time: /* @__PURE__ */ new Date(),
2055
- ...complete,
2056
- stage: status2?.stage,
2057
- queue: true,
2058
- endpoint: _endpoint,
2059
- fn_index
2060
- });
2061
- close();
2062
- }
2063
- }
2064
- if (status2?.stage === "complete" || status2?.stage === "error") {
2065
- if (event_callbacks[event_id]) {
2066
- delete event_callbacks[event_id];
2067
- }
2068
- if (event_id in pending_diff_streams) {
2069
- delete pending_diff_streams[event_id];
2070
- }
2071
- close();
2072
- }
2073
- } catch (e) {
2074
- console.error("Unexpected client exception", e);
2075
- fire_event({
2076
- type: "status",
2077
- stage: "error",
2078
- message: "An Unexpected Error Occurred!",
2079
- queue: true,
2080
- endpoint: _endpoint,
2081
- fn_index,
2082
- time: /* @__PURE__ */ new Date()
2083
- });
2084
- if (["sse_v2", "sse_v2.1", "sse_v3"].includes(protocol)) {
2085
- close_stream(stream_status, that.abort_controller);
2086
- stream_status.open = false;
2087
- close();
2088
- }
2089
- }
2090
- };
2091
- if (event_id in pending_stream_messages) {
2092
- pending_stream_messages[event_id].forEach((msg) => callback(msg));
2093
- delete pending_stream_messages[event_id];
2094
- }
2095
- event_callbacks[event_id] = callback;
2096
- unclosed_events.add(event_id);
2097
- if (!stream_status.open) {
2098
- await this.open_stream();
2099
- }
2100
- }
2101
- });
2102
- }
2103
- });
2104
- let done = false;
2105
- const values = [];
2106
- const resolvers = [];
2107
- const iterator = {
2108
- [Symbol.asyncIterator]: () => iterator,
2109
- next,
2110
- throw: async (value) => {
2111
- push_error(value);
2112
- return next();
2113
- },
2114
- return: async () => {
2115
- close();
2116
- return { value: void 0, done: true };
2117
- },
2118
- cancel,
2119
- send_chunk: (payload2) => {
2120
- this.post_data(`${config.root}${api_prefix}/stream/${event_id_final}`, {
2121
- ...payload2,
2122
- session_hash: this.session_hash
2123
- });
2124
- },
2125
- close_stream: () => {
2126
- this.post_data(
2127
- `${config.root}${api_prefix}/stream/${event_id_final}/close`,
2128
- {}
2129
- );
2130
- close();
2131
- },
2132
- event_id: () => event_id_final,
2133
- wait_for_id: async () => {
2134
- await job;
2135
- return event_id;
2136
- }
2137
- };
2138
- return iterator;
2139
- } catch (error) {
2140
- console.error("Submit function encountered an error:", error);
2141
- throw error;
2142
- }
1433
+ try {
1434
+ const { token } = this.options;
1435
+ const { fetch, app_reference, config, session_hash, api_info, api_map, stream_status, pending_stream_messages, pending_diff_streams, event_callbacks, unclosed_events, post_data, options, api_prefix } = this;
1436
+ const addt_headers = additional_headers || { "x-gradio-user": "api" };
1437
+ const that = this;
1438
+ if (!api_info) throw new Error(NO_API_INFO_MSG);
1439
+ if (!config) throw new Error("Could not resolve app config");
1440
+ let { fn_index, endpoint_info, dependency } = get_endpoint_info(api_info, endpoint, api_map, config);
1441
+ let resolved_data = map_data_to_params(data, endpoint_info);
1442
+ let stream;
1443
+ let protocol = config.protocol ?? "ws";
1444
+ if (protocol === "ws") throw new Error(WS_PROTOCOL_MSG);
1445
+ let event_id_final = "";
1446
+ const _endpoint = typeof endpoint === "number" ? "/predict" : endpoint;
1447
+ let payload;
1448
+ let event_id = null;
1449
+ let complete = false;
1450
+ let last_status = {};
1451
+ let url_params = typeof window !== "undefined" && typeof document !== "undefined" ? new URLSearchParams(window.location.search).toString() : "";
1452
+ const events_to_publish = options?.events?.reduce((acc, event) => {
1453
+ acc[event] = true;
1454
+ return acc;
1455
+ }, {}) || {};
1456
+ function fire_event(event) {
1457
+ if (all_events || events_to_publish[event.type]) push_event(event);
1458
+ }
1459
+ async function cancel() {
1460
+ let reset_request = {};
1461
+ let cancel_request = {};
1462
+ reset_request = { event_id };
1463
+ cancel_request = {
1464
+ event_id,
1465
+ session_hash,
1466
+ fn_index
1467
+ };
1468
+ try {
1469
+ if (!config) throw new Error("Could not resolve app config");
1470
+ if ("event_id" in cancel_request) await fetch(`${config.root}${api_prefix}/${CANCEL_URL}`, {
1471
+ headers: { "Content-Type": "application/json" },
1472
+ method: "POST",
1473
+ body: JSON.stringify(cancel_request)
1474
+ });
1475
+ await fetch(`${config.root}${api_prefix}/${RESET_URL}`, {
1476
+ headers: { "Content-Type": "application/json" },
1477
+ method: "POST",
1478
+ body: JSON.stringify(reset_request)
1479
+ });
1480
+ } catch (e) {
1481
+ console.warn("The `/reset` endpoint could not be called. Subsequent endpoint results may be unreliable.");
1482
+ }
1483
+ }
1484
+ const resolve_heartbeat = async (config) => {
1485
+ await this._resolve_heartbeat(config);
1486
+ };
1487
+ async function handle_render_config(render_config) {
1488
+ if (!config) return;
1489
+ let render_id = render_config.render_id;
1490
+ config.components = [...config.components.filter((c) => c.props.rendered_in !== render_id), ...render_config.components];
1491
+ config.dependencies = [...config.dependencies.filter((d) => d.rendered_in !== render_id), ...render_config.dependencies];
1492
+ const any_state = config.components.some((c) => c.type === "state");
1493
+ const any_unload = config.dependencies.some((d) => d.targets.some((t) => t[1] === "unload"));
1494
+ config.connect_heartbeat = any_state || any_unload;
1495
+ await resolve_heartbeat(config);
1496
+ fire_event({
1497
+ type: "render",
1498
+ data: render_config,
1499
+ endpoint: _endpoint,
1500
+ fn_index
1501
+ });
1502
+ }
1503
+ const job = this.handle_blob(config.root, resolved_data, endpoint_info).then(async (_payload) => {
1504
+ payload = {
1505
+ data: handle_payload(_payload, dependency, config.components, "input", true) || [],
1506
+ event_data,
1507
+ fn_index,
1508
+ trigger_id,
1509
+ ...options.oauth_token && endpoint_info?.oauth_token ? { oauth_token: options.oauth_token } : {}
1510
+ };
1511
+ if (skip_queue(fn_index, config)) {
1512
+ fire_event({
1513
+ type: "status",
1514
+ endpoint: _endpoint,
1515
+ stage: "pending",
1516
+ queue: false,
1517
+ fn_index,
1518
+ time: /* @__PURE__ */ new Date()
1519
+ });
1520
+ post_data(`${config.root}${api_prefix}/run${_endpoint.startsWith("/") ? _endpoint : `/${_endpoint}`}${url_params ? "?" + url_params : ""}`, {
1521
+ ...payload,
1522
+ session_hash
1523
+ }, addt_headers).then(async ([output, status_code]) => {
1524
+ const data = output.data;
1525
+ if (status_code == 200) {
1526
+ fire_event({
1527
+ type: "data",
1528
+ endpoint: _endpoint,
1529
+ fn_index,
1530
+ data: handle_payload(data, dependency, config.components, "output", options.with_null_state),
1531
+ time: /* @__PURE__ */ new Date(),
1532
+ event_data,
1533
+ trigger_id
1534
+ });
1535
+ if (output.render_config) await handle_render_config(output.render_config);
1536
+ fire_event({
1537
+ type: "status",
1538
+ endpoint: _endpoint,
1539
+ fn_index,
1540
+ stage: "complete",
1541
+ eta: output.average_duration,
1542
+ queue: false,
1543
+ time: /* @__PURE__ */ new Date()
1544
+ });
1545
+ } else {
1546
+ const is_connection_error = output?.error === BROKEN_CONNECTION_MSG;
1547
+ fire_event({
1548
+ type: "status",
1549
+ stage: "error",
1550
+ endpoint: _endpoint,
1551
+ fn_index,
1552
+ message: output.error,
1553
+ broken: is_connection_error,
1554
+ queue: false,
1555
+ time: /* @__PURE__ */ new Date()
1556
+ });
1557
+ }
1558
+ }).catch((e) => {
1559
+ fire_event({
1560
+ type: "status",
1561
+ stage: "error",
1562
+ message: e.message,
1563
+ endpoint: _endpoint,
1564
+ fn_index,
1565
+ queue: false,
1566
+ time: /* @__PURE__ */ new Date()
1567
+ });
1568
+ });
1569
+ } else if (protocol == "sse") {
1570
+ fire_event({
1571
+ type: "status",
1572
+ stage: "pending",
1573
+ queue: true,
1574
+ endpoint: _endpoint,
1575
+ fn_index,
1576
+ time: /* @__PURE__ */ new Date()
1577
+ });
1578
+ var params = new URLSearchParams({
1579
+ fn_index: fn_index.toString(),
1580
+ session_hash
1581
+ }).toString();
1582
+ let url = new URL(`${config.root}${api_prefix}/${SSE_URL}?${url_params ? url_params + "&" : ""}${params}`);
1583
+ if (this.jwt) url.searchParams.set("__sign", this.jwt);
1584
+ stream = this.stream(url);
1585
+ if (!stream) return Promise.reject(/* @__PURE__ */ new Error("Cannot connect to SSE endpoint: " + url.toString()));
1586
+ stream.onmessage = async function(event) {
1587
+ const { type, status, data } = handle_message(JSON.parse(event.data), last_status[fn_index]);
1588
+ if (type === "update" && status && !complete) {
1589
+ fire_event({
1590
+ type: "status",
1591
+ endpoint: _endpoint,
1592
+ fn_index,
1593
+ time: /* @__PURE__ */ new Date(),
1594
+ ...status
1595
+ });
1596
+ if (status.stage === "error") {
1597
+ stream?.close();
1598
+ close();
1599
+ }
1600
+ } else if (type === "data") {
1601
+ let [_, status] = await post_data(`${config.root}${api_prefix}/queue/data`, {
1602
+ ...payload,
1603
+ session_hash,
1604
+ event_id
1605
+ });
1606
+ if (status !== 200) {
1607
+ fire_event({
1608
+ type: "status",
1609
+ stage: "error",
1610
+ message: BROKEN_CONNECTION_MSG,
1611
+ queue: true,
1612
+ endpoint: _endpoint,
1613
+ fn_index,
1614
+ time: /* @__PURE__ */ new Date()
1615
+ });
1616
+ stream?.close();
1617
+ close();
1618
+ }
1619
+ } else if (type === "complete") complete = status;
1620
+ else if (type === "log") fire_event({
1621
+ type: "log",
1622
+ title: data.title,
1623
+ log: data.log,
1624
+ level: data.level,
1625
+ endpoint: _endpoint,
1626
+ duration: data.duration,
1627
+ visible: data.visible,
1628
+ fn_index
1629
+ });
1630
+ else if (type === "generating" || type === "streaming") fire_event({
1631
+ type: "status",
1632
+ time: /* @__PURE__ */ new Date(),
1633
+ ...status,
1634
+ stage: status?.stage,
1635
+ queue: true,
1636
+ endpoint: _endpoint,
1637
+ fn_index
1638
+ });
1639
+ if (data) {
1640
+ fire_event({
1641
+ type: "data",
1642
+ time: /* @__PURE__ */ new Date(),
1643
+ data: handle_payload(data.data, dependency, config.components, "output", options.with_null_state),
1644
+ endpoint: _endpoint,
1645
+ fn_index,
1646
+ event_data,
1647
+ trigger_id
1648
+ });
1649
+ if (complete) {
1650
+ fire_event({
1651
+ type: "status",
1652
+ time: /* @__PURE__ */ new Date(),
1653
+ ...complete,
1654
+ stage: status?.stage,
1655
+ queue: true,
1656
+ endpoint: _endpoint,
1657
+ fn_index
1658
+ });
1659
+ stream?.close();
1660
+ close();
1661
+ }
1662
+ }
1663
+ };
1664
+ } else if (protocol == "sse_v1" || protocol == "sse_v2" || protocol == "sse_v2.1" || protocol == "sse_v3") {
1665
+ fire_event({
1666
+ type: "status",
1667
+ stage: "pending",
1668
+ queue: true,
1669
+ endpoint: _endpoint,
1670
+ fn_index,
1671
+ time: /* @__PURE__ */ new Date()
1672
+ });
1673
+ let hostname = "";
1674
+ if (typeof window !== "undefined" && typeof document !== "undefined") hostname = window?.location?.hostname;
1675
+ const origin = get_zerogpu_origin(hostname);
1676
+ return (typeof window !== "undefined" && typeof document !== "undefined" && window.parent != window && !!origin && window.supports_zerogpu_headers ? post_message("zerogpu-headers", origin) : Promise.resolve(null)).then((headers) => {
1677
+ const combined_headers = {
1678
+ ...addt_headers,
1679
+ ...headers || {}
1680
+ };
1681
+ return post_data(`${config.root}${api_prefix}/${SSE_DATA_URL}?${url_params}`, {
1682
+ ...payload,
1683
+ session_hash
1684
+ }, combined_headers);
1685
+ }).then(async ([response, status]) => {
1686
+ if (response.event_id) event_id_final = response.event_id;
1687
+ if (status === 503) {
1688
+ fire_event({
1689
+ type: "status",
1690
+ stage: "error",
1691
+ message: QUEUE_FULL_MSG,
1692
+ queue: true,
1693
+ endpoint: _endpoint,
1694
+ fn_index,
1695
+ time: /* @__PURE__ */ new Date(),
1696
+ visible: true
1697
+ });
1698
+ close();
1699
+ } else if (status === 422) {
1700
+ fire_event({
1701
+ type: "status",
1702
+ stage: "error",
1703
+ message: response.detail,
1704
+ queue: true,
1705
+ endpoint: _endpoint,
1706
+ fn_index,
1707
+ code: "validation_error",
1708
+ time: /* @__PURE__ */ new Date(),
1709
+ visible: true
1710
+ });
1711
+ close();
1712
+ } else if (status !== 200) {
1713
+ const is_connection_error = response?.error === BROKEN_CONNECTION_MSG;
1714
+ fire_event({
1715
+ type: "status",
1716
+ stage: "error",
1717
+ broken: is_connection_error,
1718
+ message: is_connection_error ? BROKEN_CONNECTION_MSG : response.detail || response.error,
1719
+ queue: true,
1720
+ endpoint: _endpoint,
1721
+ fn_index,
1722
+ time: /* @__PURE__ */ new Date(),
1723
+ visible: true
1724
+ });
1725
+ close();
1726
+ } else {
1727
+ event_id = response.event_id;
1728
+ event_id_final = event_id;
1729
+ let callback = async function(_data) {
1730
+ try {
1731
+ const { type, status, data, original_msg } = handle_message(_data, last_status[fn_index]);
1732
+ if (type == "heartbeat") return;
1733
+ if (type === "update" && status && !complete) fire_event({
1734
+ type: "status",
1735
+ endpoint: _endpoint,
1736
+ fn_index,
1737
+ time: /* @__PURE__ */ new Date(),
1738
+ original_msg,
1739
+ ...status
1740
+ });
1741
+ else if (type === "complete") complete = status;
1742
+ else if (type == "unexpected_error" || type == "broken_connection") {
1743
+ console.error("Unexpected error", status?.message);
1744
+ const broken = type === "broken_connection";
1745
+ fire_event({
1746
+ type: "status",
1747
+ stage: "error",
1748
+ message: status?.message || "An Unexpected Error Occurred!",
1749
+ queue: true,
1750
+ endpoint: _endpoint,
1751
+ broken,
1752
+ session_not_found: status?.session_not_found,
1753
+ fn_index,
1754
+ time: /* @__PURE__ */ new Date()
1755
+ });
1756
+ } else if (type === "log") {
1757
+ fire_event({
1758
+ type: "log",
1759
+ title: data.title,
1760
+ log: data.log,
1761
+ level: data.level,
1762
+ endpoint: _endpoint,
1763
+ duration: data.duration,
1764
+ visible: data.visible,
1765
+ fn_index
1766
+ });
1767
+ return;
1768
+ } else if (type === "generating" || type === "streaming") {
1769
+ fire_event({
1770
+ type: "status",
1771
+ time: /* @__PURE__ */ new Date(),
1772
+ ...status,
1773
+ stage: status?.stage,
1774
+ queue: true,
1775
+ endpoint: _endpoint,
1776
+ fn_index
1777
+ });
1778
+ if (data && dependency.connection !== "stream" && [
1779
+ "sse_v2",
1780
+ "sse_v2.1",
1781
+ "sse_v3"
1782
+ ].includes(protocol)) apply_diff_stream(pending_diff_streams, event_id, data);
1783
+ }
1784
+ if (data) {
1785
+ fire_event({
1786
+ type: "data",
1787
+ time: /* @__PURE__ */ new Date(),
1788
+ data: handle_payload(data.data, dependency, config.components, "output", options.with_null_state),
1789
+ endpoint: _endpoint,
1790
+ fn_index
1791
+ });
1792
+ if (data.render_config) await handle_render_config(data.render_config);
1793
+ if (complete) {
1794
+ fire_event({
1795
+ type: "status",
1796
+ time: /* @__PURE__ */ new Date(),
1797
+ ...complete,
1798
+ stage: status?.stage,
1799
+ queue: true,
1800
+ endpoint: _endpoint,
1801
+ fn_index
1802
+ });
1803
+ close();
1804
+ }
1805
+ }
1806
+ if (status?.stage === "complete" || status?.stage === "error") {
1807
+ if (event_callbacks[event_id]) delete event_callbacks[event_id];
1808
+ if (event_id in pending_diff_streams) delete pending_diff_streams[event_id];
1809
+ close();
1810
+ }
1811
+ } catch (e) {
1812
+ console.error("Unexpected client exception", e);
1813
+ fire_event({
1814
+ type: "status",
1815
+ stage: "error",
1816
+ message: "An Unexpected Error Occurred!",
1817
+ queue: true,
1818
+ endpoint: _endpoint,
1819
+ fn_index,
1820
+ time: /* @__PURE__ */ new Date()
1821
+ });
1822
+ if ([
1823
+ "sse_v2",
1824
+ "sse_v2.1",
1825
+ "sse_v3"
1826
+ ].includes(protocol)) {
1827
+ close_stream(stream_status, that.abort_controller);
1828
+ stream_status.open = false;
1829
+ close();
1830
+ }
1831
+ }
1832
+ };
1833
+ if (event_id in pending_stream_messages) {
1834
+ pending_stream_messages[event_id].forEach((msg) => callback(msg));
1835
+ delete pending_stream_messages[event_id];
1836
+ }
1837
+ event_callbacks[event_id] = callback;
1838
+ unclosed_events.add(event_id);
1839
+ if (!stream_status.open) await this.open_stream();
1840
+ }
1841
+ });
1842
+ }
1843
+ });
1844
+ job.catch((e) => {
1845
+ fire_event({
1846
+ type: "status",
1847
+ stage: "error",
1848
+ message: e instanceof Error ? e.message : String(e),
1849
+ queue: !skip_queue(fn_index, config),
1850
+ endpoint: _endpoint,
1851
+ fn_index,
1852
+ time: /* @__PURE__ */ new Date()
1853
+ });
1854
+ close();
1855
+ });
1856
+ let done = false;
1857
+ const values = [];
1858
+ const resolvers = [];
1859
+ function close() {
1860
+ done = true;
1861
+ while (resolvers.length > 0) resolvers.shift()({
1862
+ value: void 0,
1863
+ done: true
1864
+ });
1865
+ }
1866
+ function push(data) {
1867
+ if (resolvers.length > 0) resolvers.shift()(data);
1868
+ else values.push(data);
1869
+ }
1870
+ function push_error(error) {
1871
+ push(thenable_reject(error));
1872
+ close();
1873
+ }
1874
+ function push_event(event) {
1875
+ push({
1876
+ value: event,
1877
+ done: false
1878
+ });
1879
+ }
1880
+ function next() {
1881
+ if (values.length > 0) return Promise.resolve(values.shift());
1882
+ if (done) return Promise.resolve({
1883
+ value: void 0,
1884
+ done: true
1885
+ });
1886
+ return new Promise((resolve) => resolvers.push(resolve));
1887
+ }
1888
+ const iterator = {
1889
+ [Symbol.asyncIterator]: () => iterator,
1890
+ next,
1891
+ throw: async (value) => {
1892
+ push_error(value);
1893
+ return next();
1894
+ },
1895
+ return: async () => {
1896
+ close();
1897
+ return {
1898
+ value: void 0,
1899
+ done: true
1900
+ };
1901
+ },
1902
+ cancel,
1903
+ send_chunk: (payload) => {
1904
+ this.post_data(`${config.root}${api_prefix}/stream/${event_id_final}`, {
1905
+ ...payload,
1906
+ session_hash: this.session_hash
1907
+ });
1908
+ },
1909
+ close_stream: () => {
1910
+ this.post_data(`${config.root}${api_prefix}/stream/${event_id_final}/close`, {});
1911
+ close();
1912
+ },
1913
+ event_id: () => event_id_final,
1914
+ wait_for_id: async () => {
1915
+ await job;
1916
+ return event_id;
1917
+ }
1918
+ };
1919
+ return iterator;
1920
+ } catch (error) {
1921
+ console.error("Submit function encountered an error:", error);
1922
+ throw error;
1923
+ }
2143
1924
  }
2144
1925
  function thenable_reject(error) {
2145
- return {
2146
- then: (resolve, reject) => reject(error)
2147
- };
1926
+ return { then: (resolve, reject) => reject(error) };
2148
1927
  }
2149
1928
  function get_endpoint_info(api_info, endpoint, api_map, config) {
2150
- let fn_index;
2151
- let endpoint_info;
2152
- let dependency;
2153
- if (typeof endpoint === "number") {
2154
- fn_index = endpoint;
2155
- endpoint_info = api_info.unnamed_endpoints[fn_index];
2156
- dependency = config.dependencies.find((dep) => dep.id == endpoint);
2157
- } else {
2158
- const trimmed_endpoint = endpoint.replace(/^\//, "");
2159
- fn_index = api_map[trimmed_endpoint];
2160
- endpoint_info = api_info.named_endpoints[endpoint.trim()];
2161
- dependency = config.dependencies.find(
2162
- (dep) => dep.id == api_map[trimmed_endpoint]
2163
- );
2164
- }
2165
- if (typeof fn_index !== "number") {
2166
- throw new Error(
2167
- "There is no endpoint matching that name of fn_index matching that number."
2168
- );
2169
- }
2170
- return { fn_index, endpoint_info, dependency };
1929
+ let fn_index;
1930
+ let endpoint_info;
1931
+ let dependency;
1932
+ if (typeof endpoint === "number") {
1933
+ fn_index = endpoint;
1934
+ endpoint_info = api_info.unnamed_endpoints[fn_index];
1935
+ dependency = config.dependencies.find((dep) => dep.id == endpoint);
1936
+ } else {
1937
+ const trimmed_endpoint = endpoint.replace(/^\//, "");
1938
+ fn_index = api_map[trimmed_endpoint];
1939
+ endpoint_info = api_info.named_endpoints[endpoint.trim()] ?? api_info.named_endpoints[`/${trimmed_endpoint}`];
1940
+ dependency = config.dependencies.find((dep) => dep.id == api_map[trimmed_endpoint]);
1941
+ }
1942
+ if (typeof fn_index !== "number" || !dependency) {
1943
+ const valid_endpoints = config.dependencies.filter((dep) => dep.api_name).map((dep) => `"/${dep.api_name}"`).join(", ");
1944
+ throw new Error(`No endpoint matching ${JSON.stringify(endpoint)} was found. ` + (valid_endpoints ? `Valid named endpoints are: ${valid_endpoints}. ` : "This app exposes no named endpoints. ") + "An fn_index (number) of an existing dependency can also be used.");
1945
+ }
1946
+ return {
1947
+ fn_index,
1948
+ endpoint_info,
1949
+ dependency
1950
+ };
2171
1951
  }
2172
- class Client {
2173
- app_reference;
2174
- options;
2175
- deep_link = null;
2176
- config;
2177
- api_prefix = "";
2178
- api_info;
2179
- api_map = {};
2180
- session_hash = Math.random().toString(36).substring(2);
2181
- jwt = false;
2182
- last_status = {};
2183
- cookies = null;
2184
- // streaming
2185
- stream_status = { open: false };
2186
- closed = false;
2187
- pending_stream_messages = {};
2188
- pending_diff_streams = {};
2189
- event_callbacks = {};
2190
- unclosed_events = /* @__PURE__ */ new Set();
2191
- heartbeat_event = null;
2192
- abort_controller = null;
2193
- stream_instance = null;
2194
- current_payload;
2195
- get_url_config(url = null) {
2196
- if (!this.config) {
2197
- throw new Error(CONFIG_ERROR_MSG);
2198
- }
2199
- if (url === null) {
2200
- url = window.location.href;
2201
- }
2202
- const stripSlashes = (str) => str.replace(/^\/+|\/+$/g, "");
2203
- let root_path = stripSlashes(new URL(this.config.root).pathname);
2204
- let url_path = stripSlashes(new URL(url).pathname);
2205
- let page;
2206
- if (!url_path.startsWith(root_path)) {
2207
- page = "";
2208
- } else {
2209
- page = stripSlashes(url_path.substring(root_path.length));
2210
- }
2211
- return this.get_page_config(page);
2212
- }
2213
- get_page_config(page) {
2214
- if (!this.config) {
2215
- throw new Error(CONFIG_ERROR_MSG);
2216
- }
2217
- let config = this.config;
2218
- if (!(page in config.page)) {
2219
- page = "";
2220
- }
2221
- return {
2222
- ...config,
2223
- current_page: page,
2224
- layout: config.page[page].layout,
2225
- components: config.components.filter(
2226
- (c) => config.page[page].components.includes(c.id)
2227
- ),
2228
- dependencies: this.config.dependencies.filter(
2229
- (d) => config.page[page].dependencies.includes(d.id)
2230
- )
2231
- };
2232
- }
2233
- fetch(input, init) {
2234
- const headers = new Headers(init?.headers || {});
2235
- if (this && this.cookies) {
2236
- headers.append("Cookie", this.cookies);
2237
- }
2238
- if (this && this.options.headers) {
2239
- let additional_headers = new Headers(this.options.headers);
2240
- additional_headers.forEach((value, name) => {
2241
- headers.append(name, value);
2242
- });
2243
- }
2244
- return fetch(input, { ...init, headers });
2245
- }
2246
- stream(url) {
2247
- const headers = new Headers();
2248
- if (this && this.cookies) {
2249
- headers.append("Cookie", this.cookies);
2250
- }
2251
- if (this && this.options.headers) {
2252
- let additional_headers = new Headers(this.options.headers);
2253
- additional_headers.forEach((value, name) => {
2254
- headers.append(name, value);
2255
- });
2256
- }
2257
- if (this && this.options.token) {
2258
- headers.append("Authorization", `Bearer ${this.options.token}`);
2259
- }
2260
- this.abort_controller = new AbortController();
2261
- this.stream_instance = readable_stream(url.toString(), {
2262
- credentials: "include",
2263
- headers,
2264
- signal: this.abort_controller.signal
2265
- });
2266
- return this.stream_instance;
2267
- }
2268
- view_api;
2269
- upload_files;
2270
- upload;
2271
- handle_blob;
2272
- post_data;
2273
- submit;
2274
- predict;
2275
- open_stream;
2276
- resolve_config;
2277
- resolve_cookies;
2278
- constructor(app_reference, options = { events: ["data"] }) {
2279
- this.app_reference = app_reference;
2280
- this.deep_link = options.query_params?.deep_link || null;
2281
- if (!options.events) {
2282
- options.events = ["data"];
2283
- }
2284
- this.options = options;
2285
- this.current_payload = {};
2286
- if (options.cookies) {
2287
- this.cookies = options.cookies;
2288
- }
2289
- this.view_api = view_api.bind(this);
2290
- this.upload_files = upload_files.bind(this);
2291
- this.handle_blob = handle_blob.bind(this);
2292
- this.post_data = post_data.bind(this);
2293
- this.submit = submit.bind(this);
2294
- this.predict = predict.bind(this);
2295
- this.open_stream = open_stream.bind(this);
2296
- this.resolve_config = resolve_config.bind(this);
2297
- this.resolve_cookies = resolve_cookies.bind(this);
2298
- this.upload = upload.bind(this);
2299
- this.fetch = this.fetch.bind(this);
2300
- this.handle_space_success = this.handle_space_success.bind(this);
2301
- this.stream = this.stream.bind(this);
2302
- }
2303
- async init() {
2304
- initialize_zerogpu_handshake();
2305
- if (this.options.auth) {
2306
- await this.resolve_cookies();
2307
- }
2308
- await this._resolve_config().then(
2309
- ({ config }) => this._resolve_heartbeat(config)
2310
- );
2311
- this.api_info = await this.view_api();
2312
- this.api_map = map_names_to_ids(this.config?.dependencies || []);
2313
- }
2314
- async _resolve_heartbeat(_config) {
2315
- if (_config) {
2316
- this.config = _config;
2317
- this.api_prefix = _config.api_prefix || "";
2318
- if (this.config && this.config.connect_heartbeat) {
2319
- if (this.config.space_id && this.options.token) {
2320
- this.jwt = await get_jwt(
2321
- this.config.space_id,
2322
- this.options.token,
2323
- this.cookies
2324
- );
2325
- }
2326
- }
2327
- }
2328
- if (_config.space_id && this.options.token) {
2329
- this.jwt = await get_jwt(_config.space_id, this.options.token);
2330
- }
2331
- if (this.config && this.config.connect_heartbeat) {
2332
- const heartbeat_url = new URL(
2333
- `${this.config.root}${this.api_prefix}/${HEARTBEAT_URL}/${this.session_hash}`
2334
- );
2335
- if (this.jwt) {
2336
- heartbeat_url.searchParams.set("__sign", this.jwt);
2337
- }
2338
- if (!this.heartbeat_event) {
2339
- this.heartbeat_event = this.stream(heartbeat_url);
2340
- }
2341
- }
2342
- }
2343
- static async connect(app_reference, options = {
2344
- events: ["data"]
2345
- }) {
2346
- const client2 = new this(app_reference, options);
2347
- if (options.session_hash) {
2348
- client2.session_hash = options.session_hash;
2349
- }
2350
- await client2.init();
2351
- return client2;
2352
- }
2353
- async reconnect() {
2354
- const app_id_url = new URL(
2355
- `${this.config.root}${this.api_prefix}/${APP_ID_URL}`
2356
- );
2357
- let app_id;
2358
- try {
2359
- const response = await this.fetch(app_id_url);
2360
- if (!response.ok) {
2361
- throw new Error();
2362
- }
2363
- app_id = (await response.json()).app_id;
2364
- } catch (e) {
2365
- return "broken";
2366
- }
2367
- if (app_id !== this.config.app_id) {
2368
- return "changed";
2369
- }
2370
- return "connected";
2371
- }
2372
- close() {
2373
- this.closed = true;
2374
- close_stream(this.stream_status, this.abort_controller);
2375
- }
2376
- set_current_payload(payload) {
2377
- this.current_payload = payload;
2378
- }
2379
- static async duplicate(app_reference, options = {
2380
- events: ["data"]
2381
- }) {
2382
- return duplicate(app_reference, options);
2383
- }
2384
- async _resolve_config() {
2385
- const { http_protocol, host, space_id } = await process_endpoint(
2386
- this.app_reference,
2387
- this.options.token
2388
- );
2389
- const { status_callback } = this.options;
2390
- if (space_id && status_callback) {
2391
- await check_and_wake_space(space_id, status_callback);
2392
- }
2393
- let config;
2394
- try {
2395
- let configUrl = `${http_protocol}//${host}`;
2396
- config = await this.resolve_config(configUrl);
2397
- if (!config) {
2398
- throw new Error(CONFIG_ERROR_MSG);
2399
- }
2400
- return this.config_success(config);
2401
- } catch (e) {
2402
- if (space_id && status_callback) {
2403
- check_space_status(
2404
- space_id,
2405
- RE_SPACE_NAME.test(space_id) ? "space_name" : "subdomain",
2406
- this.handle_space_success
2407
- );
2408
- } else {
2409
- if (status_callback)
2410
- status_callback({
2411
- status: "error",
2412
- message: "Could not load this space.",
2413
- load_status: "error",
2414
- detail: "NOT_FOUND"
2415
- });
2416
- throw Error(e);
2417
- }
2418
- }
2419
- }
2420
- async config_success(_config) {
2421
- this.config = _config;
2422
- this.api_prefix = _config.api_prefix || "";
2423
- if (this.config.auth_required) {
2424
- return this.prepare_return_obj();
2425
- }
2426
- try {
2427
- this.api_info = await this.view_api();
2428
- } catch (e) {
2429
- console.error(API_INFO_ERROR_MSG + e.message);
2430
- }
2431
- return this.prepare_return_obj();
2432
- }
2433
- async handle_space_success(status) {
2434
- if (!this) {
2435
- throw new Error(CONFIG_ERROR_MSG);
2436
- }
2437
- const { status_callback } = this.options;
2438
- if (status_callback) status_callback(status);
2439
- if (status.status === "running") {
2440
- try {
2441
- this.config = await this._resolve_config();
2442
- this.api_prefix = this?.config?.api_prefix || "";
2443
- if (!this.config) {
2444
- throw new Error(CONFIG_ERROR_MSG);
2445
- }
2446
- const _config = await this.config_success(this.config);
2447
- return _config;
2448
- } catch (e) {
2449
- if (status_callback) {
2450
- status_callback({
2451
- status: "error",
2452
- message: "Could not load this space.",
2453
- load_status: "error",
2454
- detail: "NOT_FOUND"
2455
- });
2456
- }
2457
- throw e;
2458
- }
2459
- }
2460
- }
2461
- async component_server(component_id, fn_name, data) {
2462
- if (!this.config) {
2463
- throw new Error(CONFIG_ERROR_MSG);
2464
- }
2465
- const headers = {};
2466
- const { token } = this.options;
2467
- const { session_hash } = this;
2468
- if (token) {
2469
- headers.Authorization = `Bearer ${this.options.token}`;
2470
- }
2471
- let root_url;
2472
- let component = this.config.components.find(
2473
- (comp) => comp.id === component_id
2474
- );
2475
- if (component?.props?.root_url) {
2476
- root_url = component.props.root_url;
2477
- } else {
2478
- root_url = this.config.root;
2479
- }
2480
- let body;
2481
- if (typeof data === "object" && data !== null && "binary" in data) {
2482
- const _data = data;
2483
- body = new FormData();
2484
- for (const key in _data.data) {
2485
- if (key === "binary") continue;
2486
- body.append(key, _data.data[key]);
2487
- }
2488
- body.set("component_id", component_id.toString());
2489
- body.set("fn_name", fn_name);
2490
- body.set("session_hash", session_hash);
2491
- } else {
2492
- body = JSON.stringify({
2493
- data,
2494
- component_id,
2495
- fn_name,
2496
- session_hash
2497
- });
2498
- headers["Content-Type"] = "application/json";
2499
- }
2500
- if (token) {
2501
- headers.Authorization = `Bearer ${token}`;
2502
- }
2503
- try {
2504
- const response = await this.fetch(
2505
- `${root_url}${this.api_prefix}/${COMPONENT_SERVER_URL}/`,
2506
- {
2507
- method: "POST",
2508
- body,
2509
- headers,
2510
- credentials: "include"
2511
- }
2512
- );
2513
- if (!response.ok) {
2514
- throw new Error(
2515
- "Could not connect to component server: " + response.statusText
2516
- );
2517
- }
2518
- const output = await response.json();
2519
- return output;
2520
- } catch (e) {
2521
- console.warn(e);
2522
- }
2523
- }
2524
- set_cookies(raw_cookies) {
2525
- this.cookies = parse_and_set_cookies(raw_cookies).join("; ");
2526
- }
2527
- prepare_return_obj() {
2528
- return {
2529
- config: this.config,
2530
- predict: this.predict,
2531
- submit: this.submit,
2532
- view_api: this.view_api,
2533
- component_server: this.component_server
2534
- };
2535
- }
2536
- }
2537
- async function client(app_reference, options = {
2538
- events: ["data"]
2539
- }) {
2540
- return await Client.connect(app_reference, options);
1952
+ //#endregion
1953
+ //#region src/client.ts
1954
+ var Client = class {
1955
+ app_reference;
1956
+ options;
1957
+ deep_link = null;
1958
+ config;
1959
+ api_prefix = "";
1960
+ api_info;
1961
+ api_map = {};
1962
+ session_hash = Math.random().toString(36).substring(2);
1963
+ jwt = false;
1964
+ last_status = {};
1965
+ cookies = null;
1966
+ stream_status = { open: false };
1967
+ closed = false;
1968
+ pending_stream_messages = {};
1969
+ pending_diff_streams = {};
1970
+ event_callbacks = {};
1971
+ unclosed_events = /* @__PURE__ */ new Set();
1972
+ heartbeat_event = null;
1973
+ abort_controller = null;
1974
+ stream_instance = null;
1975
+ current_payload;
1976
+ get_url_config(url = null) {
1977
+ if (!this.config) throw new Error(CONFIG_ERROR_MSG);
1978
+ if (url === null) url = window.location.href;
1979
+ const stripSlashes = (str) => str.replace(/^\/+|\/+$/g, "");
1980
+ let root_path = stripSlashes(new URL(this.config.root).pathname);
1981
+ let url_path = stripSlashes(new URL(url).pathname);
1982
+ let page;
1983
+ if (!url_path.startsWith(root_path)) page = "";
1984
+ else page = stripSlashes(url_path.substring(root_path.length));
1985
+ return this.get_page_config(page);
1986
+ }
1987
+ get_page_config(page) {
1988
+ if (!this.config) throw new Error(CONFIG_ERROR_MSG);
1989
+ let config = this.config;
1990
+ if (!(page in config.page)) page = "";
1991
+ return {
1992
+ ...config,
1993
+ current_page: page,
1994
+ layout: config.page[page].layout,
1995
+ components: config.components.filter((c) => config.page[page].components.includes(c.id)),
1996
+ dependencies: this.config.dependencies.filter((d) => config.page[page].dependencies.includes(d.id))
1997
+ };
1998
+ }
1999
+ fetch(input, init) {
2000
+ const headers = new Headers(init?.headers || {});
2001
+ if (this && this.cookies) headers.append("Cookie", this.cookies);
2002
+ if (this && this.options.headers) new Headers(this.options.headers).forEach((value, name) => {
2003
+ headers.append(name, value);
2004
+ });
2005
+ return fetch(input, {
2006
+ ...init,
2007
+ headers
2008
+ });
2009
+ }
2010
+ stream(url) {
2011
+ const headers = new Headers();
2012
+ if (this && this.cookies) headers.append("Cookie", this.cookies);
2013
+ if (this && this.options.headers) new Headers(this.options.headers).forEach((value, name) => {
2014
+ headers.append(name, value);
2015
+ });
2016
+ if (this && this.options.token) headers.append("Authorization", `Bearer ${this.options.token}`);
2017
+ this.abort_controller = new AbortController();
2018
+ this.stream_instance = readable_stream(url.toString(), {
2019
+ credentials: this.options.credentials ?? "same-origin",
2020
+ headers,
2021
+ signal: this.abort_controller.signal
2022
+ });
2023
+ return this.stream_instance;
2024
+ }
2025
+ view_api;
2026
+ upload_files;
2027
+ upload;
2028
+ handle_blob;
2029
+ post_data;
2030
+ submit;
2031
+ predict;
2032
+ open_stream;
2033
+ resolve_config;
2034
+ resolve_cookies;
2035
+ constructor(app_reference, options = { events: ["data"] }) {
2036
+ this.app_reference = app_reference;
2037
+ this.deep_link = options.query_params?.deep_link || null;
2038
+ if (!options.events) options.events = ["data"];
2039
+ normalise_token_option(options);
2040
+ this.options = options;
2041
+ this.current_payload = {};
2042
+ if (options.cookies) this.cookies = options.cookies;
2043
+ this.view_api = view_api.bind(this);
2044
+ this.upload_files = upload_files.bind(this);
2045
+ this.handle_blob = handle_blob.bind(this);
2046
+ this.post_data = post_data.bind(this);
2047
+ this.submit = submit.bind(this);
2048
+ this.predict = predict.bind(this);
2049
+ this.open_stream = open_stream.bind(this);
2050
+ this.resolve_config = resolve_config.bind(this);
2051
+ this.resolve_cookies = resolve_cookies.bind(this);
2052
+ this.upload = upload.bind(this);
2053
+ this.fetch = this.fetch.bind(this);
2054
+ this.handle_space_success = this.handle_space_success.bind(this);
2055
+ this.stream = this.stream.bind(this);
2056
+ }
2057
+ async init() {
2058
+ initialize_zerogpu_handshake();
2059
+ if (this.options.auth) await this.resolve_cookies();
2060
+ await this._resolve_config().then((res) => res?.config && this._resolve_heartbeat(res.config));
2061
+ try {
2062
+ this.api_info = await this.view_api();
2063
+ } catch (e) {
2064
+ console.error(e.message);
2065
+ }
2066
+ this.api_map = map_names_to_ids(this.config?.dependencies || []);
2067
+ }
2068
+ async _resolve_heartbeat(_config) {
2069
+ if (_config) {
2070
+ this.config = _config;
2071
+ this.api_prefix = _config.api_prefix || "";
2072
+ if (this.config && this.config.connect_heartbeat) {
2073
+ if (this.config.space_id && this.options.token) this.jwt = await get_jwt(this.config.space_id, this.options.token, this.cookies);
2074
+ }
2075
+ }
2076
+ if (_config.space_id && this.options.token) this.jwt = await get_jwt(_config.space_id, this.options.token);
2077
+ if (this.config && this.config.connect_heartbeat) {
2078
+ const heartbeat_url = new URL(`${this.config.root}${this.api_prefix}/${HEARTBEAT_URL}/${this.session_hash}`);
2079
+ if (this.jwt) heartbeat_url.searchParams.set("__sign", this.jwt);
2080
+ if (!this.heartbeat_event) this.heartbeat_event = this.stream(heartbeat_url);
2081
+ }
2082
+ }
2083
+ static async connect(app_reference, options = { events: ["data"] }) {
2084
+ const client = new this(app_reference, options);
2085
+ if (options.session_hash) client.session_hash = options.session_hash;
2086
+ await client.init();
2087
+ return client;
2088
+ }
2089
+ async reconnect() {
2090
+ const app_id_url = new URL(`${this.config.root}${this.api_prefix}/${APP_ID_URL}`);
2091
+ let app_id;
2092
+ try {
2093
+ const response = await this.fetch(app_id_url);
2094
+ if (!response.ok) throw new Error();
2095
+ app_id = (await response.json()).app_id;
2096
+ } catch (e) {
2097
+ return "broken";
2098
+ }
2099
+ if (app_id !== this.config.app_id) return "changed";
2100
+ return "connected";
2101
+ }
2102
+ close() {
2103
+ this.closed = true;
2104
+ close_stream(this.stream_status, this.abort_controller);
2105
+ }
2106
+ /**
2107
+ * Re-fetch the app config without closing the SSE stream.
2108
+ * Used by hot-reload so in-flight generators keep delivering updates.
2109
+ */
2110
+ async refresh() {
2111
+ if (!this.config) throw new Error(CONFIG_ERROR_MSG);
2112
+ const config = await this.resolve_config(this.config.root, false);
2113
+ if (!config) throw new Error(CONFIG_ERROR_MSG);
2114
+ this.config = config;
2115
+ this.api_prefix = config.api_prefix || "";
2116
+ this.api_map = map_names_to_ids(config.dependencies || []);
2117
+ try {
2118
+ this.api_info = await this.view_api();
2119
+ } catch (e) {
2120
+ console.error(API_INFO_ERROR_MSG + e.message);
2121
+ }
2122
+ return this.get_url_config();
2123
+ }
2124
+ set_current_payload(payload) {
2125
+ this.current_payload = payload;
2126
+ }
2127
+ static async duplicate(app_reference, options = { events: ["data"] }) {
2128
+ return duplicate(app_reference, options);
2129
+ }
2130
+ async _resolve_config() {
2131
+ const { http_protocol, host, space_id } = await process_endpoint(this.app_reference, this.options.token);
2132
+ const { status_callback } = this.options;
2133
+ if (space_id && status_callback) await check_and_wake_space(space_id, status_callback);
2134
+ let config;
2135
+ try {
2136
+ let configUrl = `${http_protocol}//${host}`;
2137
+ config = await this.resolve_config(configUrl);
2138
+ if (!config) throw new Error(CONFIG_ERROR_MSG);
2139
+ return this.config_success(config);
2140
+ } catch (e) {
2141
+ if (space_id && status_callback) check_space_status(space_id, RE_SPACE_NAME.test(space_id) ? "space_name" : "subdomain", this.handle_space_success);
2142
+ else {
2143
+ if (status_callback) status_callback({
2144
+ status: "error",
2145
+ message: "Could not load this space.",
2146
+ load_status: "error",
2147
+ detail: "NOT_FOUND"
2148
+ });
2149
+ throw e instanceof Error ? e : new Error(String(e));
2150
+ }
2151
+ }
2152
+ }
2153
+ async config_success(_config) {
2154
+ this.config = _config;
2155
+ this.api_prefix = _config.api_prefix || "";
2156
+ if (this.config.auth_required) return this.prepare_return_obj();
2157
+ try {
2158
+ this.api_info = await this.view_api();
2159
+ } catch (e) {
2160
+ console.error(API_INFO_ERROR_MSG + e.message);
2161
+ }
2162
+ return this.prepare_return_obj();
2163
+ }
2164
+ async handle_space_success(status) {
2165
+ if (!this) throw new Error(CONFIG_ERROR_MSG);
2166
+ const { status_callback } = this.options;
2167
+ if (status_callback) status_callback(status);
2168
+ if (status.status === "running") try {
2169
+ this.config = await this._resolve_config();
2170
+ this.api_prefix = this?.config?.api_prefix || "";
2171
+ if (!this.config) throw new Error(CONFIG_ERROR_MSG);
2172
+ return await this.config_success(this.config);
2173
+ } catch (e) {
2174
+ if (status_callback) status_callback({
2175
+ status: "error",
2176
+ message: "Could not load this space.",
2177
+ load_status: "error",
2178
+ detail: "NOT_FOUND"
2179
+ });
2180
+ throw e;
2181
+ }
2182
+ }
2183
+ async component_server(component_id, fn_name, data) {
2184
+ if (!this.config) throw new Error(CONFIG_ERROR_MSG);
2185
+ const headers = {};
2186
+ const { token } = this.options;
2187
+ const { session_hash } = this;
2188
+ if (token) headers.Authorization = `Bearer ${this.options.token}`;
2189
+ let root_url;
2190
+ let component = this.config.components.find((comp) => comp.id === component_id);
2191
+ if (component?.props?.root_url) root_url = component.props.root_url;
2192
+ else root_url = this.config.root;
2193
+ let body;
2194
+ if (typeof data === "object" && data !== null && "binary" in data) {
2195
+ const _data = data;
2196
+ body = new FormData();
2197
+ for (const key in _data.data) {
2198
+ if (key === "binary") continue;
2199
+ body.append(key, _data.data[key]);
2200
+ }
2201
+ body.set("component_id", component_id.toString());
2202
+ body.set("fn_name", fn_name);
2203
+ body.set("session_hash", session_hash);
2204
+ } else {
2205
+ body = JSON.stringify({
2206
+ data,
2207
+ component_id,
2208
+ fn_name,
2209
+ session_hash
2210
+ });
2211
+ headers["Content-Type"] = "application/json";
2212
+ }
2213
+ if (token) headers.Authorization = `Bearer ${token}`;
2214
+ try {
2215
+ const response = await this.fetch(`${root_url}${this.api_prefix}/${COMPONENT_SERVER_URL}/`, {
2216
+ method: "POST",
2217
+ body,
2218
+ headers,
2219
+ credentials: this.options.credentials ?? "same-origin"
2220
+ });
2221
+ if (!response.ok) throw new Error("Could not connect to component server: " + response.statusText);
2222
+ return await response.json();
2223
+ } catch (e) {
2224
+ console.warn(e);
2225
+ }
2226
+ }
2227
+ set_cookies(raw_cookies) {
2228
+ this.cookies = parse_and_set_cookies(raw_cookies).join("; ");
2229
+ }
2230
+ prepare_return_obj() {
2231
+ return {
2232
+ config: this.config,
2233
+ predict: this.predict,
2234
+ submit: this.submit,
2235
+ view_api: this.view_api,
2236
+ component_server: this.component_server
2237
+ };
2238
+ }
2239
+ };
2240
+ /**
2241
+ * @deprecated This method will be removed in v1.0. Use `Client.connect()` instead.
2242
+ * Creates a client instance for interacting with Gradio apps.
2243
+ *
2244
+ * @param {string} app_reference - The reference or URL to a Gradio space or app.
2245
+ * @param {ClientOptions} options - Configuration options for the client.
2246
+ * @returns {Promise<Client>} A promise that resolves to a `Client` instance.
2247
+ */
2248
+ async function client(app_reference, options = { events: ["data"] }) {
2249
+ return await Client.connect(app_reference, options);
2541
2250
  }
2251
+ /**
2252
+ * @deprecated This method will be removed in v1.0. Use `Client.duplicate()` instead.
2253
+ * Creates a duplicate of a space and returns a client instance for the duplicated space.
2254
+ *
2255
+ * @param {string} app_reference - The reference or URL to a Gradio space or app to duplicate.
2256
+ * @param {DuplicateOptions} options - Configuration options for the client.
2257
+ * @returns {Promise<Client>} A promise that resolves to a `Client` instance.
2258
+ */
2542
2259
  async function duplicate_space(app_reference, options) {
2543
- return await Client.duplicate(app_reference, options);
2260
+ return await Client.duplicate(app_reference, options);
2544
2261
  }
2545
- export {
2546
- Client,
2547
- FileData,
2548
- MISSING_CREDENTIALS_MSG,
2549
- client,
2550
- duplicate_space as duplicate,
2551
- handle_file,
2552
- predict,
2553
- prepare_files,
2554
- submit,
2555
- upload,
2556
- upload_files
2557
- };
2262
+ //#endregion
2263
+ export { Client, FileData, MISSING_CREDENTIALS_MSG, client, duplicate_space as duplicate, handle_file, predict, prepare_files, submit, upload, upload_files };