@gradio/client 0.16.0 → 0.18.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 +57 -0
- package/README.md +49 -43
- package/dist/client.d.ts +63 -70
- package/dist/client.d.ts.map +1 -1
- package/dist/constants.d.ts +23 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/helpers/api_info.d.ts +25 -0
- package/dist/helpers/api_info.d.ts.map +1 -0
- package/dist/helpers/data.d.ts +8 -0
- package/dist/helpers/data.d.ts.map +1 -0
- package/dist/{utils.d.ts → helpers/init_helpers.d.ts} +6 -18
- package/dist/helpers/init_helpers.d.ts.map +1 -0
- package/dist/helpers/spaces.d.ts +7 -0
- package/dist/helpers/spaces.d.ts.map +1 -0
- package/dist/index.d.ts +8 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1628 -1398
- package/dist/test/handlers.d.ts +3 -0
- package/dist/test/handlers.d.ts.map +1 -0
- package/dist/test/mock_eventsource.d.ts +2 -0
- package/dist/test/mock_eventsource.d.ts.map +1 -0
- package/dist/test/server.d.ts +2 -0
- package/dist/test/server.d.ts.map +1 -0
- package/dist/test/test_data.d.ts +76 -0
- package/dist/test/test_data.d.ts.map +1 -0
- package/dist/types.d.ts +153 -49
- package/dist/types.d.ts.map +1 -1
- package/dist/upload.d.ts +2 -2
- package/dist/upload.d.ts.map +1 -1
- package/dist/utils/duplicate.d.ts +4 -0
- package/dist/utils/duplicate.d.ts.map +1 -0
- package/dist/utils/handle_blob.d.ts +4 -0
- package/dist/utils/handle_blob.d.ts.map +1 -0
- package/dist/utils/post_data.d.ts +4 -0
- package/dist/utils/post_data.d.ts.map +1 -0
- package/dist/utils/predict.d.ts +4 -0
- package/dist/utils/predict.d.ts.map +1 -0
- package/dist/utils/stream.d.ts +8 -0
- package/dist/utils/stream.d.ts.map +1 -0
- package/dist/utils/submit.d.ts +4 -0
- package/dist/utils/submit.d.ts.map +1 -0
- package/dist/utils/upload_files.d.ts +4 -0
- package/dist/utils/upload_files.d.ts.map +1 -0
- package/dist/utils/view_api.d.ts +3 -0
- package/dist/utils/view_api.d.ts.map +1 -0
- package/dist/{wrapper-6f348d45.js → wrapper-CviSselG.js} +259 -17
- package/package.json +10 -3
- package/src/client.ts +314 -1691
- package/src/constants.ts +27 -0
- package/src/globals.d.ts +2 -21
- package/src/helpers/api_info.ts +300 -0
- package/src/helpers/data.ts +133 -0
- package/src/helpers/init_helpers.ts +130 -0
- package/src/helpers/spaces.ts +197 -0
- package/src/index.ts +16 -10
- package/src/test/api_info.test.ts +456 -0
- package/src/test/data.test.ts +281 -0
- package/src/test/handlers.ts +438 -0
- package/src/test/init.test.ts +139 -0
- package/src/test/init_helpers.test.ts +94 -0
- package/src/test/mock_eventsource.ts +11 -0
- package/src/test/post_data.test.ts +45 -0
- package/src/test/server.ts +6 -0
- package/src/test/spaces.test.ts +145 -0
- package/src/test/stream.test.ts +67 -0
- package/src/test/test_data.ts +557 -0
- package/src/test/upload_files.test.ts +42 -0
- package/src/test/view_api.test.ts +53 -0
- package/src/types.ts +201 -59
- package/src/upload.ts +19 -15
- package/src/utils/duplicate.ts +104 -0
- package/src/utils/handle_blob.ts +47 -0
- package/src/utils/post_data.ts +37 -0
- package/src/utils/predict.ts +56 -0
- package/src/utils/stream.ts +175 -0
- package/src/utils/submit.ts +697 -0
- package/src/utils/upload_files.ts +51 -0
- package/src/utils/view_api.ts +67 -0
- package/src/vite-env.d.ts +1 -0
- package/tsconfig.json +15 -2
- package/vite.config.js +11 -17
- package/dist/utils.d.ts.map +0 -1
- package/src/client.node-test.ts +0 -172
- package/src/utils.ts +0 -314
package/src/types.ts
CHANGED
@@ -1,13 +1,131 @@
|
|
1
|
+
// API Data Types
|
2
|
+
|
3
|
+
import { hardware_types } from "./helpers/spaces";
|
4
|
+
|
5
|
+
export interface ApiData {
|
6
|
+
label: string;
|
7
|
+
type: {
|
8
|
+
type: any;
|
9
|
+
description: string;
|
10
|
+
};
|
11
|
+
component: string;
|
12
|
+
example_input?: any;
|
13
|
+
python_type: { type: string; description: string };
|
14
|
+
serializer: string;
|
15
|
+
}
|
16
|
+
|
17
|
+
export interface JsApiData {
|
18
|
+
label: string;
|
19
|
+
type: string;
|
20
|
+
description: string;
|
21
|
+
component: string;
|
22
|
+
example_input?: any;
|
23
|
+
serializer: string;
|
24
|
+
python_type: { type: string; description: string };
|
25
|
+
}
|
26
|
+
|
27
|
+
export interface EndpointInfo<T extends ApiData | JsApiData> {
|
28
|
+
parameters: T[];
|
29
|
+
returns: T[];
|
30
|
+
type?: DependencyTypes;
|
31
|
+
}
|
32
|
+
|
33
|
+
export interface ApiInfo<T extends ApiData | JsApiData> {
|
34
|
+
named_endpoints: Record<string, EndpointInfo<T>>;
|
35
|
+
unnamed_endpoints: Record<string, EndpointInfo<T>>;
|
36
|
+
}
|
37
|
+
|
38
|
+
export interface BlobRef {
|
39
|
+
path: string[];
|
40
|
+
type: string | undefined;
|
41
|
+
blob: Blob | File | false;
|
42
|
+
}
|
43
|
+
|
44
|
+
export type DataType = string | Buffer | Record<string, any> | any[];
|
45
|
+
|
46
|
+
// Event and Submission Types
|
47
|
+
|
48
|
+
type event = <K extends EventType>(
|
49
|
+
eventType: K,
|
50
|
+
listener: EventListener<K>
|
51
|
+
) => SubmitReturn;
|
52
|
+
|
53
|
+
type predict = (
|
54
|
+
endpoint: string | number,
|
55
|
+
data?: unknown[],
|
56
|
+
event_data?: unknown
|
57
|
+
) => Promise<unknown>;
|
58
|
+
|
59
|
+
export type client_return = {
|
60
|
+
config: Config | undefined;
|
61
|
+
predict: predict;
|
62
|
+
submit: (
|
63
|
+
endpoint: string | number,
|
64
|
+
data: unknown[],
|
65
|
+
event_data?: unknown,
|
66
|
+
trigger_id?: number | null
|
67
|
+
) => SubmitReturn;
|
68
|
+
component_server: (
|
69
|
+
component_id: number,
|
70
|
+
fn_name: string,
|
71
|
+
data: unknown[]
|
72
|
+
) => any;
|
73
|
+
view_api: (_fetch: typeof fetch) => Promise<ApiInfo<JsApiData>>;
|
74
|
+
};
|
75
|
+
|
76
|
+
export type SubmitReturn = {
|
77
|
+
on: event;
|
78
|
+
off: event;
|
79
|
+
cancel: () => Promise<void>;
|
80
|
+
destroy: () => void;
|
81
|
+
};
|
82
|
+
|
83
|
+
// Space Status Types
|
84
|
+
|
85
|
+
export type SpaceStatus = SpaceStatusNormal | SpaceStatusError;
|
86
|
+
|
87
|
+
export interface SpaceStatusNormal {
|
88
|
+
status: "sleeping" | "running" | "building" | "error" | "stopped";
|
89
|
+
detail:
|
90
|
+
| "SLEEPING"
|
91
|
+
| "RUNNING"
|
92
|
+
| "RUNNING_BUILDING"
|
93
|
+
| "BUILDING"
|
94
|
+
| "NOT_FOUND";
|
95
|
+
load_status: "pending" | "error" | "complete" | "generating";
|
96
|
+
message: string;
|
97
|
+
}
|
98
|
+
|
99
|
+
export interface SpaceStatusError {
|
100
|
+
status: "space_error" | "paused";
|
101
|
+
detail:
|
102
|
+
| "NO_APP_FILE"
|
103
|
+
| "CONFIG_ERROR"
|
104
|
+
| "BUILD_ERROR"
|
105
|
+
| "RUNTIME_ERROR"
|
106
|
+
| "PAUSED";
|
107
|
+
load_status: "error";
|
108
|
+
message: string;
|
109
|
+
discussions_enabled: boolean;
|
110
|
+
}
|
111
|
+
|
112
|
+
export type SpaceStatusCallback = (a: SpaceStatus) => void;
|
113
|
+
|
114
|
+
// Configuration and Response Types
|
115
|
+
// --------------------------------
|
1
116
|
export interface Config {
|
2
|
-
auth_required: boolean
|
117
|
+
auth_required: boolean;
|
118
|
+
analytics_enabled: boolean;
|
119
|
+
connect_heartbeat: boolean;
|
3
120
|
auth_message: string;
|
4
121
|
components: any[];
|
5
122
|
css: string | null;
|
6
123
|
js: string | null;
|
7
124
|
head: string | null;
|
8
|
-
dependencies:
|
125
|
+
dependencies: Dependency[];
|
9
126
|
dev_mode: boolean;
|
10
127
|
enable_queue: boolean;
|
128
|
+
show_error: boolean;
|
11
129
|
layout: any;
|
12
130
|
mode: "blocks" | "interface";
|
13
131
|
root: string;
|
@@ -16,81 +134,91 @@ export interface Config {
|
|
16
134
|
title: string;
|
17
135
|
version: string;
|
18
136
|
space_id: string | null;
|
137
|
+
is_space: boolean;
|
19
138
|
is_colab: boolean;
|
20
139
|
show_api: boolean;
|
21
140
|
stylesheets: string[];
|
22
141
|
path: string;
|
23
|
-
protocol
|
142
|
+
protocol: "sse_v3" | "sse_v2.1" | "sse_v2" | "sse_v1" | "sse" | "ws";
|
143
|
+
max_file_size?: number;
|
144
|
+
}
|
145
|
+
|
146
|
+
export interface Dependency {
|
147
|
+
targets: [number, string][];
|
148
|
+
inputs: number[];
|
149
|
+
outputs: number[];
|
150
|
+
backend_fn: boolean;
|
151
|
+
js: string | null;
|
152
|
+
scroll_to_output: boolean;
|
153
|
+
trigger: "click" | "load" | string;
|
154
|
+
max_batch_size: number;
|
155
|
+
show_progress: "full" | "minimal" | "hidden";
|
156
|
+
frontend_fn: ((...args: unknown[]) => Promise<unknown[]>) | null;
|
157
|
+
status?: string;
|
158
|
+
queue: boolean | null;
|
159
|
+
every: number | null;
|
160
|
+
batch: boolean;
|
161
|
+
api_name: string | null;
|
162
|
+
cancels: number[];
|
163
|
+
types: DependencyTypes;
|
164
|
+
collects_event_data: boolean;
|
165
|
+
pending_request?: boolean;
|
166
|
+
trigger_after?: number;
|
167
|
+
trigger_only_on_success?: boolean;
|
168
|
+
trigger_mode: "once" | "multiple" | "always_last";
|
169
|
+
final_event: Payload | null;
|
170
|
+
show_api: boolean;
|
171
|
+
zerogpu?: boolean;
|
172
|
+
}
|
173
|
+
|
174
|
+
export interface DependencyTypes {
|
175
|
+
continuous: boolean;
|
176
|
+
generator: boolean;
|
24
177
|
}
|
25
178
|
|
26
179
|
export interface Payload {
|
180
|
+
fn_index: number;
|
27
181
|
data: unknown[];
|
28
|
-
fn_index?: number;
|
29
|
-
event_data?: unknown;
|
30
182
|
time?: Date;
|
183
|
+
event_data?: unknown;
|
184
|
+
trigger_id?: number | null;
|
31
185
|
}
|
32
186
|
|
33
187
|
export interface PostResponse {
|
34
188
|
error?: string;
|
35
189
|
[x: string]: any;
|
36
190
|
}
|
191
|
+
|
37
192
|
export interface UploadResponse {
|
38
193
|
error?: string;
|
39
194
|
files?: string[];
|
40
195
|
}
|
41
196
|
|
42
|
-
|
43
|
-
queue: boolean;
|
44
|
-
code?: string;
|
45
|
-
success?: boolean;
|
46
|
-
stage: "pending" | "error" | "complete" | "generating";
|
47
|
-
broken?: boolean;
|
48
|
-
size?: number;
|
49
|
-
position?: number;
|
50
|
-
eta?: number;
|
51
|
-
message?: string;
|
52
|
-
progress_data?: {
|
53
|
-
progress: number | null;
|
54
|
-
index: number | null;
|
55
|
-
length: number | null;
|
56
|
-
unit: string | null;
|
57
|
-
desc: string | null;
|
58
|
-
}[];
|
59
|
-
time?: Date;
|
60
|
-
}
|
197
|
+
// Client and File Handling Types
|
61
198
|
|
62
|
-
export interface
|
63
|
-
|
64
|
-
|
199
|
+
export interface DuplicateOptions extends ClientOptions {
|
200
|
+
private?: boolean;
|
201
|
+
hardware?: (typeof hardware_types)[number];
|
202
|
+
timeout?: number;
|
65
203
|
}
|
66
204
|
|
67
|
-
export interface
|
68
|
-
|
69
|
-
|
70
|
-
| "SLEEPING"
|
71
|
-
| "RUNNING"
|
72
|
-
| "RUNNING_BUILDING"
|
73
|
-
| "BUILDING"
|
74
|
-
| "NOT_FOUND";
|
75
|
-
load_status: "pending" | "error" | "complete" | "generating";
|
76
|
-
message: string;
|
205
|
+
export interface ClientOptions {
|
206
|
+
hf_token?: `hf_${string}`;
|
207
|
+
status_callback?: SpaceStatusCallback | null;
|
77
208
|
}
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
discussions_enabled: boolean;
|
209
|
+
|
210
|
+
export interface FileData {
|
211
|
+
name: string;
|
212
|
+
orig_name?: string;
|
213
|
+
size?: number;
|
214
|
+
data: string;
|
215
|
+
blob?: File;
|
216
|
+
is_file?: boolean;
|
217
|
+
mime_type?: string;
|
218
|
+
alt_text?: string;
|
89
219
|
}
|
90
|
-
export type SpaceStatus = SpaceStatusNormal | SpaceStatusError;
|
91
220
|
|
92
|
-
|
93
|
-
export type SpaceStatusCallback = (a: SpaceStatus) => void;
|
221
|
+
// Event and Listener Types
|
94
222
|
|
95
223
|
export type EventType = "data" | "status" | "log";
|
96
224
|
|
@@ -107,13 +235,27 @@ export type EventListener<K extends EventType> = (event: Event<K>) => void;
|
|
107
235
|
export type ListenerMap<K extends EventType> = {
|
108
236
|
[P in K]?: EventListener<K>[];
|
109
237
|
};
|
110
|
-
export interface
|
111
|
-
|
112
|
-
|
238
|
+
export interface LogMessage {
|
239
|
+
log: string;
|
240
|
+
level: "warning" | "info";
|
241
|
+
}
|
242
|
+
|
243
|
+
export interface Status {
|
244
|
+
queue: boolean;
|
245
|
+
code?: string;
|
246
|
+
success?: boolean;
|
247
|
+
stage: "pending" | "error" | "complete" | "generating";
|
248
|
+
broken?: boolean;
|
113
249
|
size?: number;
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
250
|
+
position?: number;
|
251
|
+
eta?: number;
|
252
|
+
message?: string;
|
253
|
+
progress_data?: {
|
254
|
+
progress: number | null;
|
255
|
+
index: number | null;
|
256
|
+
length: number | null;
|
257
|
+
unit: string | null;
|
258
|
+
desc: string | null;
|
259
|
+
}[];
|
260
|
+
time?: Date;
|
119
261
|
}
|
package/src/upload.ts
CHANGED
@@ -1,26 +1,30 @@
|
|
1
|
-
import {
|
2
|
-
|
3
|
-
function is_url(str: string): boolean {
|
4
|
-
try {
|
5
|
-
const url = new URL(str);
|
6
|
-
return url.protocol === "http:" || url.protocol === "https:";
|
7
|
-
} catch {
|
8
|
-
return false;
|
9
|
-
}
|
10
|
-
}
|
1
|
+
import type { UploadResponse } from "./types";
|
2
|
+
import type { Client } from "./client";
|
11
3
|
|
12
4
|
export async function upload(
|
5
|
+
this: Client,
|
13
6
|
file_data: FileData[],
|
14
|
-
|
7
|
+
root_url: string,
|
15
8
|
upload_id?: string,
|
16
|
-
|
9
|
+
max_file_size?: number
|
17
10
|
): Promise<(FileData | null)[] | null> {
|
18
11
|
let files = (Array.isArray(file_data) ? file_data : [file_data]).map(
|
19
12
|
(file_data) => file_data.blob!
|
20
13
|
);
|
21
14
|
|
15
|
+
const oversized_files = files.filter(
|
16
|
+
(f) => f.size > (max_file_size ?? Infinity)
|
17
|
+
);
|
18
|
+
if (oversized_files.length) {
|
19
|
+
throw new Error(
|
20
|
+
`File size exceeds the maximum allowed size of ${max_file_size} bytes: ${oversized_files
|
21
|
+
.map((f) => f.name)
|
22
|
+
.join(", ")}`
|
23
|
+
);
|
24
|
+
}
|
25
|
+
|
22
26
|
return await Promise.all(
|
23
|
-
await
|
27
|
+
await this.upload_files(root_url, files, upload_id).then(
|
24
28
|
async (response: { files?: string[]; error?: string }) => {
|
25
29
|
if (response.error) {
|
26
30
|
throw new Error(response.error);
|
@@ -30,7 +34,7 @@ export async function upload(
|
|
30
34
|
const file = new FileData({
|
31
35
|
...file_data[i],
|
32
36
|
path: f,
|
33
|
-
url:
|
37
|
+
url: root_url + "/file=" + f
|
34
38
|
});
|
35
39
|
return file;
|
36
40
|
});
|
@@ -48,7 +52,7 @@ export async function prepare_files(
|
|
48
52
|
is_stream?: boolean
|
49
53
|
): Promise<FileData[]> {
|
50
54
|
return files.map(
|
51
|
-
(f
|
55
|
+
(f) =>
|
52
56
|
new FileData({
|
53
57
|
path: f.name,
|
54
58
|
orig_name: f.name,
|
@@ -0,0 +1,104 @@
|
|
1
|
+
import {
|
2
|
+
get_space_hardware,
|
3
|
+
hardware_types,
|
4
|
+
set_space_timeout
|
5
|
+
} from "../helpers/spaces";
|
6
|
+
import type { DuplicateOptions } from "../types";
|
7
|
+
import { Client } from "../client";
|
8
|
+
import { SPACE_METADATA_ERROR_MSG } from "../constants";
|
9
|
+
|
10
|
+
export async function duplicate(
|
11
|
+
app_reference: string,
|
12
|
+
options: DuplicateOptions
|
13
|
+
): Promise<Client> {
|
14
|
+
const { hf_token, private: _private, hardware, timeout } = options;
|
15
|
+
|
16
|
+
if (hardware && !hardware_types.includes(hardware)) {
|
17
|
+
throw new Error(
|
18
|
+
`Invalid hardware type provided. Valid types are: ${hardware_types
|
19
|
+
.map((v) => `"${v}"`)
|
20
|
+
.join(",")}.`
|
21
|
+
);
|
22
|
+
}
|
23
|
+
const headers = {
|
24
|
+
Authorization: `Bearer ${hf_token}`,
|
25
|
+
"Content-Type": "application/json"
|
26
|
+
};
|
27
|
+
|
28
|
+
const user = (
|
29
|
+
await (
|
30
|
+
await fetch(`https://huggingface.co/api/whoami-v2`, {
|
31
|
+
headers
|
32
|
+
})
|
33
|
+
).json()
|
34
|
+
).name;
|
35
|
+
|
36
|
+
const space_name = app_reference.split("/")[1];
|
37
|
+
const body: {
|
38
|
+
repository: string;
|
39
|
+
private?: boolean;
|
40
|
+
hardware?: string;
|
41
|
+
} = {
|
42
|
+
repository: `${user}/${space_name}`
|
43
|
+
};
|
44
|
+
|
45
|
+
if (_private) {
|
46
|
+
body.private = true;
|
47
|
+
}
|
48
|
+
|
49
|
+
let original_hardware;
|
50
|
+
|
51
|
+
try {
|
52
|
+
if (!hardware) {
|
53
|
+
original_hardware = await get_space_hardware(app_reference, hf_token);
|
54
|
+
}
|
55
|
+
} catch (e) {
|
56
|
+
throw Error(SPACE_METADATA_ERROR_MSG + (e as Error).message);
|
57
|
+
}
|
58
|
+
|
59
|
+
const requested_hardware = hardware || original_hardware || "cpu-basic";
|
60
|
+
|
61
|
+
body.hardware = requested_hardware;
|
62
|
+
|
63
|
+
try {
|
64
|
+
const response = await fetch(
|
65
|
+
`https://huggingface.co/api/spaces/${app_reference}/duplicate`,
|
66
|
+
{
|
67
|
+
method: "POST",
|
68
|
+
headers,
|
69
|
+
body: JSON.stringify(body)
|
70
|
+
}
|
71
|
+
);
|
72
|
+
|
73
|
+
if (response.status === 409) {
|
74
|
+
try {
|
75
|
+
const client = await Client.connect(`${user}/${space_name}`, options);
|
76
|
+
return client;
|
77
|
+
} catch (error) {
|
78
|
+
console.error("Failed to connect Client instance:", error);
|
79
|
+
throw error;
|
80
|
+
}
|
81
|
+
} else if (response.status !== 200) {
|
82
|
+
throw new Error(response.statusText);
|
83
|
+
}
|
84
|
+
|
85
|
+
const duplicated_space = await response.json();
|
86
|
+
|
87
|
+
await set_space_timeout(`${user}/${space_name}`, timeout || 300, hf_token);
|
88
|
+
|
89
|
+
return await Client.connect(
|
90
|
+
get_space_reference(duplicated_space.url),
|
91
|
+
options
|
92
|
+
);
|
93
|
+
} catch (e: any) {
|
94
|
+
throw new Error(e);
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
98
|
+
function get_space_reference(url: string): any {
|
99
|
+
const regex = /https:\/\/huggingface.co\/spaces\/([^/]+\/[^/]+)/;
|
100
|
+
const match = url.match(regex);
|
101
|
+
if (match) {
|
102
|
+
return match[1];
|
103
|
+
}
|
104
|
+
}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
import { update_object, walk_and_store_blobs } from "../helpers/data";
|
2
|
+
import type { ApiData, EndpointInfo, JsApiData } from "../types";
|
3
|
+
import { FileData } from "../upload";
|
4
|
+
import type { Client } from "..";
|
5
|
+
|
6
|
+
export async function handle_blob(
|
7
|
+
this: Client,
|
8
|
+
endpoint: string,
|
9
|
+
data: unknown[],
|
10
|
+
api_info: EndpointInfo<JsApiData | ApiData>
|
11
|
+
): Promise<unknown[]> {
|
12
|
+
const self = this;
|
13
|
+
|
14
|
+
const blobRefs = await walk_and_store_blobs(
|
15
|
+
data,
|
16
|
+
undefined,
|
17
|
+
[],
|
18
|
+
true,
|
19
|
+
api_info
|
20
|
+
);
|
21
|
+
|
22
|
+
const results = await Promise.all(
|
23
|
+
blobRefs.map(async ({ path, blob, type }) => {
|
24
|
+
if (!blob) return { path, type };
|
25
|
+
|
26
|
+
const response = await self.upload_files(endpoint, [blob]);
|
27
|
+
const file_url = response.files && response.files[0];
|
28
|
+
return {
|
29
|
+
path,
|
30
|
+
file_url,
|
31
|
+
type,
|
32
|
+
name: blob instanceof File ? blob?.name : undefined
|
33
|
+
};
|
34
|
+
})
|
35
|
+
);
|
36
|
+
|
37
|
+
results.forEach(({ path, file_url, type, name }) => {
|
38
|
+
if (type === "Gallery") {
|
39
|
+
update_object(data, file_url, path);
|
40
|
+
} else if (file_url) {
|
41
|
+
const file = new FileData({ path: file_url, orig_name: name });
|
42
|
+
update_object(data, file, path);
|
43
|
+
}
|
44
|
+
});
|
45
|
+
|
46
|
+
return data;
|
47
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import { BROKEN_CONNECTION_MSG } from "../constants";
|
2
|
+
import type { PostResponse } from "../types";
|
3
|
+
import { Client } from "..";
|
4
|
+
|
5
|
+
export async function post_data(
|
6
|
+
this: Client,
|
7
|
+
url: string,
|
8
|
+
body: unknown,
|
9
|
+
additional_headers?: any
|
10
|
+
): Promise<[PostResponse, number]> {
|
11
|
+
const headers: {
|
12
|
+
Authorization?: string;
|
13
|
+
"Content-Type": "application/json";
|
14
|
+
} = { "Content-Type": "application/json" };
|
15
|
+
if (this.options.hf_token) {
|
16
|
+
headers.Authorization = `Bearer ${this.options.hf_token}`;
|
17
|
+
}
|
18
|
+
try {
|
19
|
+
var response = await this.fetch(url, {
|
20
|
+
method: "POST",
|
21
|
+
body: JSON.stringify(body),
|
22
|
+
headers: { ...headers, ...additional_headers }
|
23
|
+
});
|
24
|
+
} catch (e) {
|
25
|
+
return [{ error: BROKEN_CONNECTION_MSG }, 500];
|
26
|
+
}
|
27
|
+
let output: PostResponse;
|
28
|
+
let status: number;
|
29
|
+
try {
|
30
|
+
output = await response.json();
|
31
|
+
status = response.status;
|
32
|
+
} catch (e) {
|
33
|
+
output = { error: `Could not parse server response: ${e}` };
|
34
|
+
status = 500;
|
35
|
+
}
|
36
|
+
return [output, status];
|
37
|
+
}
|
@@ -0,0 +1,56 @@
|
|
1
|
+
import { Client } from "../client";
|
2
|
+
import type { Dependency, SubmitReturn } from "../types";
|
3
|
+
|
4
|
+
export async function predict(
|
5
|
+
this: Client,
|
6
|
+
endpoint: string | number,
|
7
|
+
data?: unknown[]
|
8
|
+
): Promise<SubmitReturn> {
|
9
|
+
let data_returned = false;
|
10
|
+
let status_complete = false;
|
11
|
+
let dependency: Dependency;
|
12
|
+
|
13
|
+
if (!this.config) {
|
14
|
+
throw new Error("Could not resolve app config");
|
15
|
+
}
|
16
|
+
|
17
|
+
if (typeof endpoint === "number") {
|
18
|
+
dependency = this.config.dependencies[endpoint];
|
19
|
+
} else {
|
20
|
+
const trimmed_endpoint = endpoint.replace(/^\//, "");
|
21
|
+
dependency = this.config.dependencies[this.api_map[trimmed_endpoint]];
|
22
|
+
}
|
23
|
+
|
24
|
+
if (dependency?.types.continuous) {
|
25
|
+
throw new Error(
|
26
|
+
"Cannot call predict on this function as it may run forever. Use submit instead"
|
27
|
+
);
|
28
|
+
}
|
29
|
+
|
30
|
+
return new Promise(async (resolve, reject) => {
|
31
|
+
const app = this.submit(endpoint, data || []);
|
32
|
+
let result: unknown;
|
33
|
+
|
34
|
+
app
|
35
|
+
.on("data", (d: unknown) => {
|
36
|
+
// if complete message comes before data, resolve here
|
37
|
+
if (status_complete) {
|
38
|
+
app.destroy();
|
39
|
+
resolve(d as SubmitReturn);
|
40
|
+
}
|
41
|
+
data_returned = true;
|
42
|
+
result = d;
|
43
|
+
})
|
44
|
+
.on("status", (status) => {
|
45
|
+
if (status.stage === "error") reject(status);
|
46
|
+
if (status.stage === "complete") {
|
47
|
+
status_complete = true;
|
48
|
+
// if complete message comes after data, resolve here
|
49
|
+
if (data_returned) {
|
50
|
+
app.destroy();
|
51
|
+
resolve(result as SubmitReturn);
|
52
|
+
}
|
53
|
+
}
|
54
|
+
});
|
55
|
+
});
|
56
|
+
}
|