@gradio/client 0.16.0 → 0.17.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 +41 -0
- package/README.md +49 -43
- package/dist/client.d.ts +52 -70
- package/dist/client.d.ts.map +1 -1
- package/dist/constants.d.ts +17 -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 +1544 -1357
- package/dist/types.d.ts +152 -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 +3 -2
- package/src/client.ts +289 -1692
- package/src/constants.ts +20 -0
- package/src/globals.d.ts +2 -21
- package/src/helpers/api_info.ts +300 -0
- package/src/helpers/data.ts +115 -0
- package/src/helpers/init_helpers.ts +134 -0
- package/src/helpers/spaces.ts +192 -0
- package/src/index.ts +16 -10
- package/src/types.ts +200 -59
- package/src/upload.ts +23 -15
- package/src/{client.node-test.ts → utils/client.node-test.ts} +11 -10
- package/src/utils/duplicate.ts +87 -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 +166 -0
- package/src/utils/submit.ts +689 -0
- package/src/utils/upload_files.ts +46 -0
- package/src/utils/view_api.ts +70 -0
- package/src/vite-env.d.ts +1 -0
- package/tsconfig.json +15 -2
- package/vite.config.js +4 -17
- package/dist/utils.d.ts.map +0 -1
- package/src/utils.ts +0 -314
@@ -0,0 +1,192 @@
|
|
1
|
+
import type { SpaceStatusCallback } from "../types";
|
2
|
+
|
3
|
+
export async function check_space_status(
|
4
|
+
id: string,
|
5
|
+
type: "subdomain" | "space_name",
|
6
|
+
status_callback: SpaceStatusCallback
|
7
|
+
): Promise<void> {
|
8
|
+
let endpoint =
|
9
|
+
type === "subdomain"
|
10
|
+
? `https://huggingface.co/api/spaces/by-subdomain/${id}`
|
11
|
+
: `https://huggingface.co/api/spaces/${id}`;
|
12
|
+
let response;
|
13
|
+
let _status;
|
14
|
+
try {
|
15
|
+
response = await fetch(endpoint);
|
16
|
+
_status = response.status;
|
17
|
+
if (_status !== 200) {
|
18
|
+
throw new Error();
|
19
|
+
}
|
20
|
+
response = await response.json();
|
21
|
+
} catch (e) {
|
22
|
+
status_callback({
|
23
|
+
status: "error",
|
24
|
+
load_status: "error",
|
25
|
+
message: "Could not get space status",
|
26
|
+
detail: "NOT_FOUND"
|
27
|
+
});
|
28
|
+
return;
|
29
|
+
}
|
30
|
+
|
31
|
+
if (!response || _status !== 200) return;
|
32
|
+
const {
|
33
|
+
runtime: { stage },
|
34
|
+
id: space_name
|
35
|
+
} = response;
|
36
|
+
|
37
|
+
switch (stage) {
|
38
|
+
case "STOPPED":
|
39
|
+
case "SLEEPING":
|
40
|
+
status_callback({
|
41
|
+
status: "sleeping",
|
42
|
+
load_status: "pending",
|
43
|
+
message: "Space is asleep. Waking it up...",
|
44
|
+
detail: stage
|
45
|
+
});
|
46
|
+
|
47
|
+
setTimeout(() => {
|
48
|
+
check_space_status(id, type, status_callback);
|
49
|
+
}, 1000); // poll for status
|
50
|
+
break;
|
51
|
+
case "PAUSED":
|
52
|
+
status_callback({
|
53
|
+
status: "paused",
|
54
|
+
load_status: "error",
|
55
|
+
message:
|
56
|
+
"This space has been paused by the author. If you would like to try this demo, consider duplicating the space.",
|
57
|
+
detail: stage,
|
58
|
+
discussions_enabled: await discussions_enabled(space_name)
|
59
|
+
});
|
60
|
+
break;
|
61
|
+
case "RUNNING":
|
62
|
+
case "RUNNING_BUILDING":
|
63
|
+
status_callback({
|
64
|
+
status: "running",
|
65
|
+
load_status: "complete",
|
66
|
+
message: "",
|
67
|
+
detail: stage
|
68
|
+
});
|
69
|
+
break;
|
70
|
+
case "BUILDING":
|
71
|
+
status_callback({
|
72
|
+
status: "building",
|
73
|
+
load_status: "pending",
|
74
|
+
message: "Space is building...",
|
75
|
+
detail: stage
|
76
|
+
});
|
77
|
+
|
78
|
+
setTimeout(() => {
|
79
|
+
check_space_status(id, type, status_callback);
|
80
|
+
}, 1000);
|
81
|
+
break;
|
82
|
+
default:
|
83
|
+
status_callback({
|
84
|
+
status: "space_error",
|
85
|
+
load_status: "error",
|
86
|
+
message: "This space is experiencing an issue.",
|
87
|
+
detail: stage,
|
88
|
+
discussions_enabled: await discussions_enabled(space_name)
|
89
|
+
});
|
90
|
+
break;
|
91
|
+
}
|
92
|
+
}
|
93
|
+
|
94
|
+
const RE_DISABLED_DISCUSSION =
|
95
|
+
/^(?=[^]*\b[dD]iscussions{0,1}\b)(?=[^]*\b[dD]isabled\b)[^]*$/;
|
96
|
+
export async function discussions_enabled(space_id: string): Promise<boolean> {
|
97
|
+
try {
|
98
|
+
const r = await fetch(
|
99
|
+
`https://huggingface.co/api/spaces/${space_id}/discussions`,
|
100
|
+
{
|
101
|
+
method: "HEAD"
|
102
|
+
}
|
103
|
+
);
|
104
|
+
const error = r.headers.get("x-error-message");
|
105
|
+
|
106
|
+
if (error && RE_DISABLED_DISCUSSION.test(error)) return false;
|
107
|
+
return true;
|
108
|
+
} catch (e) {
|
109
|
+
return false;
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
export async function get_space_hardware(
|
114
|
+
space_id: string,
|
115
|
+
hf_token?: `hf_${string}` | undefined
|
116
|
+
): Promise<(typeof hardware_types)[number]> {
|
117
|
+
const headers: { Authorization?: string } = {};
|
118
|
+
if (hf_token) {
|
119
|
+
headers.Authorization = `Bearer ${hf_token}`;
|
120
|
+
}
|
121
|
+
|
122
|
+
try {
|
123
|
+
const res = await fetch(
|
124
|
+
`https://huggingface.co/api/spaces/${space_id}/runtime`,
|
125
|
+
{ headers }
|
126
|
+
);
|
127
|
+
|
128
|
+
if (res.status !== 200)
|
129
|
+
throw new Error("Space hardware could not be obtained.");
|
130
|
+
|
131
|
+
const { hardware } = await res.json();
|
132
|
+
|
133
|
+
return hardware.current;
|
134
|
+
} catch (e: any) {
|
135
|
+
throw new Error(e.message);
|
136
|
+
}
|
137
|
+
}
|
138
|
+
|
139
|
+
export async function set_space_timeout(
|
140
|
+
space_id: string,
|
141
|
+
timeout: number,
|
142
|
+
hf_token?: `hf_${string}`
|
143
|
+
): Promise<any> {
|
144
|
+
const headers: { Authorization?: string } = {};
|
145
|
+
if (hf_token) {
|
146
|
+
headers.Authorization = `Bearer ${hf_token}`;
|
147
|
+
}
|
148
|
+
|
149
|
+
const body: {
|
150
|
+
seconds?: number;
|
151
|
+
} = {
|
152
|
+
seconds: timeout
|
153
|
+
};
|
154
|
+
|
155
|
+
try {
|
156
|
+
const res = await fetch(
|
157
|
+
`https://huggingface.co/api/spaces/${space_id}/sleeptime`,
|
158
|
+
{
|
159
|
+
method: "POST",
|
160
|
+
headers: { "Content-Type": "application/json", ...headers },
|
161
|
+
body: JSON.stringify(body)
|
162
|
+
}
|
163
|
+
);
|
164
|
+
|
165
|
+
if (res.status !== 200) {
|
166
|
+
throw new Error(
|
167
|
+
"Could not set sleep timeout on duplicated Space. Please visit *ADD HF LINK TO SETTINGS* to set a timeout manually to reduce billing charges."
|
168
|
+
);
|
169
|
+
}
|
170
|
+
|
171
|
+
const response = await res.json();
|
172
|
+
return response;
|
173
|
+
} catch (e: any) {
|
174
|
+
throw new Error(e.message);
|
175
|
+
}
|
176
|
+
}
|
177
|
+
|
178
|
+
export const hardware_types = [
|
179
|
+
"cpu-basic",
|
180
|
+
"cpu-upgrade",
|
181
|
+
"cpu-xl",
|
182
|
+
"t4-small",
|
183
|
+
"t4-medium",
|
184
|
+
"a10g-small",
|
185
|
+
"a10g-large",
|
186
|
+
"a10g-largex2",
|
187
|
+
"a10g-largex4",
|
188
|
+
"a100-large",
|
189
|
+
"zero-a10g",
|
190
|
+
"h100",
|
191
|
+
"h100x8"
|
192
|
+
] as const;
|
package/src/index.ts
CHANGED
@@ -1,11 +1,17 @@
|
|
1
|
-
export {
|
2
|
-
client,
|
3
|
-
post_data,
|
4
|
-
upload_files,
|
5
|
-
duplicate,
|
6
|
-
api_factory
|
7
|
-
} from "./client.js";
|
8
|
-
export type { client_return } from "./client.js";
|
9
|
-
export type { SpaceStatus } from "./types.js";
|
1
|
+
export { Client } from "./client";
|
10
2
|
|
11
|
-
export {
|
3
|
+
export { predict } from "./utils/predict";
|
4
|
+
export { submit } from "./utils/submit";
|
5
|
+
export { upload_files } from "./utils/upload_files";
|
6
|
+
export { FileData, upload, prepare_files } from "./upload";
|
7
|
+
|
8
|
+
export type {
|
9
|
+
SpaceStatus,
|
10
|
+
Status,
|
11
|
+
client_return,
|
12
|
+
UploadResponse
|
13
|
+
} from "./types";
|
14
|
+
|
15
|
+
// todo: remove in @gradio/client v1.0
|
16
|
+
export { client } from "./client";
|
17
|
+
export { duplicate } from "./utils/duplicate";
|
package/src/types.ts
CHANGED
@@ -1,13 +1,130 @@
|
|
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 | false;
|
42
|
+
}
|
43
|
+
|
44
|
+
export type ParamType = 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_implementation: 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;
|
3
119
|
auth_message: string;
|
4
120
|
components: any[];
|
5
121
|
css: string | null;
|
6
122
|
js: string | null;
|
7
123
|
head: string | null;
|
8
|
-
dependencies:
|
124
|
+
dependencies: Dependency[];
|
9
125
|
dev_mode: boolean;
|
10
126
|
enable_queue: boolean;
|
127
|
+
show_error: boolean;
|
11
128
|
layout: any;
|
12
129
|
mode: "blocks" | "interface";
|
13
130
|
root: string;
|
@@ -16,81 +133,91 @@ export interface Config {
|
|
16
133
|
title: string;
|
17
134
|
version: string;
|
18
135
|
space_id: string | null;
|
136
|
+
is_space: boolean;
|
19
137
|
is_colab: boolean;
|
20
138
|
show_api: boolean;
|
21
139
|
stylesheets: string[];
|
22
140
|
path: string;
|
23
|
-
protocol
|
141
|
+
protocol: "sse_v3" | "sse_v2.1" | "sse_v2" | "sse_v1" | "sse" | "ws";
|
142
|
+
max_file_size?: number;
|
143
|
+
}
|
144
|
+
|
145
|
+
export interface Dependency {
|
146
|
+
targets: [number, string][];
|
147
|
+
inputs: number[];
|
148
|
+
outputs: number[];
|
149
|
+
backend_fn: boolean;
|
150
|
+
js: string | null;
|
151
|
+
scroll_to_output: boolean;
|
152
|
+
trigger: "click" | "load" | string;
|
153
|
+
max_batch_size: number;
|
154
|
+
show_progress: "full" | "minimal" | "hidden";
|
155
|
+
frontend_fn: ((...args: unknown[]) => Promise<unknown[]>) | null;
|
156
|
+
status?: string;
|
157
|
+
queue: boolean | null;
|
158
|
+
every: number | null;
|
159
|
+
batch: boolean;
|
160
|
+
api_name: string | null;
|
161
|
+
cancels: number[];
|
162
|
+
types: DependencyTypes;
|
163
|
+
collects_event_data: boolean;
|
164
|
+
pending_request?: boolean;
|
165
|
+
trigger_after?: number;
|
166
|
+
trigger_only_on_success?: boolean;
|
167
|
+
trigger_mode: "once" | "multiple" | "always_last";
|
168
|
+
final_event: Payload | null;
|
169
|
+
show_api: boolean;
|
170
|
+
zerogpu?: boolean;
|
171
|
+
}
|
172
|
+
|
173
|
+
export interface DependencyTypes {
|
174
|
+
continuous: boolean;
|
175
|
+
generator: boolean;
|
24
176
|
}
|
25
177
|
|
26
178
|
export interface Payload {
|
179
|
+
fn_index: number;
|
27
180
|
data: unknown[];
|
28
|
-
fn_index?: number;
|
29
|
-
event_data?: unknown;
|
30
181
|
time?: Date;
|
182
|
+
event_data?: unknown;
|
183
|
+
trigger_id?: number | null;
|
31
184
|
}
|
32
185
|
|
33
186
|
export interface PostResponse {
|
34
187
|
error?: string;
|
35
188
|
[x: string]: any;
|
36
189
|
}
|
190
|
+
|
37
191
|
export interface UploadResponse {
|
38
192
|
error?: string;
|
39
193
|
files?: string[];
|
40
194
|
}
|
41
195
|
|
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
|
-
}
|
196
|
+
// Client and File Handling Types
|
61
197
|
|
62
|
-
export interface
|
63
|
-
|
64
|
-
|
198
|
+
export interface DuplicateOptions extends ClientOptions {
|
199
|
+
private?: boolean;
|
200
|
+
hardware?: (typeof hardware_types)[number];
|
201
|
+
timeout?: number;
|
65
202
|
}
|
66
203
|
|
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;
|
204
|
+
export interface ClientOptions {
|
205
|
+
hf_token?: `hf_${string}`;
|
206
|
+
status_callback?: SpaceStatusCallback | null;
|
77
207
|
}
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
discussions_enabled: boolean;
|
208
|
+
|
209
|
+
export interface FileData {
|
210
|
+
name: string;
|
211
|
+
orig_name?: string;
|
212
|
+
size?: number;
|
213
|
+
data: string;
|
214
|
+
blob?: File;
|
215
|
+
is_file?: boolean;
|
216
|
+
mime_type?: string;
|
217
|
+
alt_text?: string;
|
89
218
|
}
|
90
|
-
export type SpaceStatus = SpaceStatusNormal | SpaceStatusError;
|
91
219
|
|
92
|
-
|
93
|
-
export type SpaceStatusCallback = (a: SpaceStatus) => void;
|
220
|
+
// Event and Listener Types
|
94
221
|
|
95
222
|
export type EventType = "data" | "status" | "log";
|
96
223
|
|
@@ -107,13 +234,27 @@ export type EventListener<K extends EventType> = (event: Event<K>) => void;
|
|
107
234
|
export type ListenerMap<K extends EventType> = {
|
108
235
|
[P in K]?: EventListener<K>[];
|
109
236
|
};
|
110
|
-
export interface
|
111
|
-
|
112
|
-
|
237
|
+
export interface LogMessage {
|
238
|
+
log: string;
|
239
|
+
level: "warning" | "info";
|
240
|
+
}
|
241
|
+
|
242
|
+
export interface Status {
|
243
|
+
queue: boolean;
|
244
|
+
code?: string;
|
245
|
+
success?: boolean;
|
246
|
+
stage: "pending" | "error" | "complete" | "generating";
|
247
|
+
broken?: boolean;
|
113
248
|
size?: number;
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
249
|
+
position?: number;
|
250
|
+
eta?: number;
|
251
|
+
message?: string;
|
252
|
+
progress_data?: {
|
253
|
+
progress: number | null;
|
254
|
+
index: number | null;
|
255
|
+
length: number | null;
|
256
|
+
unit: string | null;
|
257
|
+
desc: string | null;
|
258
|
+
}[];
|
259
|
+
time?: Date;
|
119
260
|
}
|
package/src/upload.ts
CHANGED
@@ -1,26 +1,34 @@
|
|
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 { upload_files } from ".";
|
11
3
|
|
12
4
|
export async function upload(
|
13
5
|
file_data: FileData[],
|
14
|
-
|
6
|
+
root_url: string,
|
15
7
|
upload_id?: string,
|
16
|
-
|
8
|
+
max_file_size?: number,
|
9
|
+
upload_fn: (
|
10
|
+
root_url: string,
|
11
|
+
files: (Blob | File)[],
|
12
|
+
upload_id?: string
|
13
|
+
) => Promise<UploadResponse> = upload_files
|
17
14
|
): Promise<(FileData | null)[] | null> {
|
18
15
|
let files = (Array.isArray(file_data) ? file_data : [file_data]).map(
|
19
16
|
(file_data) => file_data.blob!
|
20
17
|
);
|
21
18
|
|
19
|
+
const oversized_files = files.filter(
|
20
|
+
(f) => f.size > (max_file_size ?? Infinity)
|
21
|
+
);
|
22
|
+
if (oversized_files.length) {
|
23
|
+
throw new Error(
|
24
|
+
`File size exceeds the maximum allowed size of ${max_file_size} bytes: ${oversized_files
|
25
|
+
.map((f) => f.name)
|
26
|
+
.join(", ")}`
|
27
|
+
);
|
28
|
+
}
|
29
|
+
|
22
30
|
return await Promise.all(
|
23
|
-
await upload_fn(
|
31
|
+
await upload_fn(root_url, files, upload_id).then(
|
24
32
|
async (response: { files?: string[]; error?: string }) => {
|
25
33
|
if (response.error) {
|
26
34
|
throw new Error(response.error);
|
@@ -30,7 +38,7 @@ export async function upload(
|
|
30
38
|
const file = new FileData({
|
31
39
|
...file_data[i],
|
32
40
|
path: f,
|
33
|
-
url:
|
41
|
+
url: root_url + "/file=" + f
|
34
42
|
});
|
35
43
|
return file;
|
36
44
|
});
|
@@ -48,7 +56,7 @@ export async function prepare_files(
|
|
48
56
|
is_stream?: boolean
|
49
57
|
): Promise<FileData[]> {
|
50
58
|
return files.map(
|
51
|
-
(f
|
59
|
+
(f) =>
|
52
60
|
new FileData({
|
53
61
|
path: f.name,
|
54
62
|
orig_name: f.name,
|
@@ -16,12 +16,13 @@ const image_path = join(
|
|
16
16
|
"lion.jpg"
|
17
17
|
);
|
18
18
|
|
19
|
-
import { walk_and_store_blobs
|
19
|
+
import { walk_and_store_blobs } from "../helpers/data";
|
20
|
+
import { Client } from "..";
|
20
21
|
|
21
22
|
describe.skip("extract blob parts", () => {
|
22
23
|
test("convert Buffer to Blob", async () => {
|
23
24
|
const image = readFileSync(image_path);
|
24
|
-
await
|
25
|
+
await Client.connect("gradio/hello_world_main");
|
25
26
|
const parts = walk_and_store_blobs({
|
26
27
|
data: {
|
27
28
|
image
|
@@ -34,7 +35,7 @@ describe.skip("extract blob parts", () => {
|
|
34
35
|
test("leave node Blob as Blob", async () => {
|
35
36
|
const image = new Blob([readFileSync(image_path)]);
|
36
37
|
|
37
|
-
await
|
38
|
+
await Client.connect("gradio/hello_world_main");
|
38
39
|
const parts = walk_and_store_blobs({
|
39
40
|
data: {
|
40
41
|
image
|
@@ -47,7 +48,7 @@ describe.skip("extract blob parts", () => {
|
|
47
48
|
test("handle deep structures", async () => {
|
48
49
|
const image = new Blob([readFileSync(image_path)]);
|
49
50
|
|
50
|
-
await
|
51
|
+
await Client.connect("gradio/hello_world_main");
|
51
52
|
const parts = walk_and_store_blobs({
|
52
53
|
a: {
|
53
54
|
b: {
|
@@ -64,7 +65,7 @@ describe.skip("extract blob parts", () => {
|
|
64
65
|
test("handle deep structures with arrays", async () => {
|
65
66
|
const image = new Blob([readFileSync(image_path)]);
|
66
67
|
|
67
|
-
await
|
68
|
+
await Client.connect("gradio/hello_world_main");
|
68
69
|
const parts = walk_and_store_blobs({
|
69
70
|
a: [
|
70
71
|
{
|
@@ -87,7 +88,7 @@ describe.skip("extract blob parts", () => {
|
|
87
88
|
test("handle deep structures with arrays 2", async () => {
|
88
89
|
const image = new Blob([readFileSync(image_path)]);
|
89
90
|
|
90
|
-
await
|
91
|
+
await Client.connect("gradio/hello_world_main");
|
91
92
|
const obj = {
|
92
93
|
a: [
|
93
94
|
{
|
@@ -121,7 +122,7 @@ describe("handle_blob", () => {
|
|
121
122
|
test("handle blobs", async () => {
|
122
123
|
const image = new Blob([readFileSync(image_path)]);
|
123
124
|
|
124
|
-
const app = await
|
125
|
+
const app = await Client.connect("gradio/hello_world_main");
|
125
126
|
const obj = [
|
126
127
|
{
|
127
128
|
a: [
|
@@ -136,7 +137,7 @@ describe("handle_blob", () => {
|
|
136
137
|
}
|
137
138
|
];
|
138
139
|
|
139
|
-
const parts = await handle_blob(app.config.root, obj, undefined);
|
140
|
+
const parts = await app.handle_blob(app.config.root, obj, undefined);
|
140
141
|
//@ts-ignore
|
141
142
|
// assert.isString(parts.data[0].a[0].b[0].data[0][0]);
|
142
143
|
});
|
@@ -146,7 +147,7 @@ describe.skip("private space", () => {
|
|
146
147
|
test("can access a private space", async () => {
|
147
148
|
const image = new Blob([readFileSync(image_path)]);
|
148
149
|
|
149
|
-
const app = await
|
150
|
+
const app = await Client.connect("pngwn/hello_world", {
|
150
151
|
hf_token: "hf_"
|
151
152
|
});
|
152
153
|
|
@@ -165,7 +166,7 @@ describe.skip("private space", () => {
|
|
165
166
|
}
|
166
167
|
];
|
167
168
|
|
168
|
-
const parts = await handle_blob(app.config.root, obj,
|
169
|
+
const parts = await app.handle_blob(app.config.root, obj, undefined);
|
169
170
|
//@ts-ignore
|
170
171
|
assert.isString(parts.data[0].a[0].b[0].data[0][0]);
|
171
172
|
});
|