@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.
- package/CHANGELOG.md +23 -0
- package/README.md +4 -2
- package/dist/__vite-browser-external-Cgmn0awE.js +7 -0
- package/dist/browser.js +1672 -1902
- package/dist/client.d.ts +5 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/constants.d.ts +4 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/helpers/api_info.d.ts.map +1 -1
- package/dist/helpers/data.d.ts.map +1 -1
- package/dist/helpers/init_helpers.d.ts +12 -3
- package/dist/helpers/init_helpers.d.ts.map +1 -1
- package/dist/index.cjs +2274 -0
- package/dist/index.js +2155 -2449
- package/dist/index.min.js +1735 -0
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/duplicate.d.ts.map +1 -1
- package/dist/utils/predict.d.ts.map +1 -1
- package/dist/utils/stream.d.ts.map +1 -1
- package/dist/utils/submit.d.ts.map +1 -1
- package/dist/utils/view_api.d.ts.map +1 -1
- package/package.json +11 -4
- package/scripts/verify_dist.mjs +46 -0
- package/src/client.ts +46 -7
- package/src/constants.ts +10 -0
- package/src/helpers/api_info.ts +47 -19
- package/src/helpers/data.ts +8 -3
- package/src/helpers/init_helpers.ts +61 -14
- package/src/test/api_info.test.ts +105 -12
- package/src/test/data.test.ts +26 -3
- package/src/test/init.test.ts +21 -3
- package/src/test/init_helpers.test.ts +94 -1
- package/src/test/post_data.test.ts +21 -0
- package/src/test/refresh.test.ts +31 -0
- package/src/test/submit.test.ts +14 -0
- package/src/types.ts +16 -0
- package/src/utils/duplicate.ts +5 -1
- package/src/utils/post_data.ts +1 -1
- package/src/utils/predict.ts +34 -19
- package/src/utils/stream.ts +17 -4
- package/src/utils/submit.ts +43 -10
- package/src/utils/upload_files.ts +1 -1
- package/src/utils/view_api.ts +2 -3
- package/vite.config.ts +20 -4
- package/dist/__vite-browser-external-DYxpcVy9.js +0 -4
package/dist/index.js
CHANGED
|
@@ -1,2557 +1,2263 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
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
|
-
|
|
180
|
-
|
|
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
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
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
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
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
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
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
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
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
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
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
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
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
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
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
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
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
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
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
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
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
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
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
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
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
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
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
|
-
|
|
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
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
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
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
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
|
-
|
|
755
|
-
|
|
756
|
-
|
|
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
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
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
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
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
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
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
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
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(
|
|
867
|
-
|
|
868
|
-
|
|
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(
|
|
874
|
-
|
|
875
|
-
|
|
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(
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
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
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
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
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
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
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
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
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
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
|
-
|
|
1002
|
+
var RE_DISABLED_DISCUSSION = /^(?=[^]*\b[dD]iscussions{0,1}\b)(?=[^]*\b[dD]isabled\b)[^]*$/;
|
|
1096
1003
|
async function discussions_enabled(space_id) {
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
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
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
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
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
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
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
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
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
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
|
-
|
|
1247
|
-
|
|
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
|
-
|
|
1253
|
-
|
|
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
|
-
|
|
1116
|
+
return typeof window !== "undefined" && typeof document !== "undefined" && typeof window.addEventListener === "function";
|
|
1256
1117
|
}
|
|
1257
1118
|
function get_zerogpu_origin(hostname) {
|
|
1258
|
-
|
|
1259
|
-
|
|
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
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
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
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
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
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
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
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
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
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
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
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
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
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
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
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
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
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
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
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
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
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
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
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
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
|
-
|
|
2260
|
+
return await Client.duplicate(app_reference, options);
|
|
2544
2261
|
}
|
|
2545
|
-
|
|
2546
|
-
|
|
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 };
|