@gradio/client 2.3.1 → 2.5.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 +21 -0
- package/README.md +4 -2
- package/dist/__vite-browser-external-Cgmn0awE.js +7 -0
- package/dist/browser.js +1949 -1963
- 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 +11 -2
- package/dist/helpers/init_helpers.d.ts.map +1 -1
- package/dist/index.cjs +2584 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2471 -2466
- package/dist/index.min.js +1962 -0
- package/dist/types.d.ts +29 -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/run_history.d.ts +64 -0
- package/dist/utils/run_history.d.ts.map +1 -0
- package/dist/utils/stream.d.ts.map +1 -1
- package/dist/utils/submit.d.ts.map +1 -1
- package/package.json +11 -4
- package/scripts/verify_dist.mjs +46 -0
- package/src/client.ts +54 -5
- package/src/constants.ts +10 -0
- package/src/helpers/api_info.ts +46 -19
- package/src/helpers/data.ts +8 -3
- package/src/helpers/init_helpers.ts +54 -7
- package/src/index.ts +12 -0
- package/src/test/api_info.test.ts +77 -12
- package/src/test/data.test.ts +26 -3
- package/src/test/init.test.ts +21 -3
- package/src/test/init_helpers.test.ts +67 -1
- package/src/test/refresh.test.ts +31 -0
- package/src/test/run_history.test.ts +345 -0
- package/src/test/submit.test.ts +1 -3
- package/src/types.ts +29 -0
- package/src/utils/duplicate.ts +2 -0
- package/src/utils/predict.ts +14 -1
- package/src/utils/run_history.ts +520 -0
- package/src/utils/stream.ts +17 -4
- package/src/utils/submit.ts +105 -12
- package/vite.config.ts +20 -4
- package/dist/__vite-browser-external-DYxpcVy9.js +0 -4
package/src/utils/submit.ts
CHANGED
|
@@ -19,14 +19,21 @@ import {
|
|
|
19
19
|
} from "../helpers/api_info";
|
|
20
20
|
import {
|
|
21
21
|
BROKEN_CONNECTION_MSG,
|
|
22
|
+
NO_API_INFO_MSG,
|
|
22
23
|
QUEUE_FULL_MSG,
|
|
23
24
|
SSE_URL,
|
|
24
25
|
SSE_DATA_URL,
|
|
25
26
|
RESET_URL,
|
|
26
|
-
CANCEL_URL
|
|
27
|
+
CANCEL_URL,
|
|
28
|
+
WS_PROTOCOL_MSG
|
|
27
29
|
} from "../constants";
|
|
28
30
|
import { apply_diff_stream, close_stream } from "./stream";
|
|
29
31
|
import { Client } from "../client";
|
|
32
|
+
import {
|
|
33
|
+
start_run_history,
|
|
34
|
+
update_run_history,
|
|
35
|
+
update_run_inputs
|
|
36
|
+
} from "./run_history";
|
|
30
37
|
|
|
31
38
|
export function submit(
|
|
32
39
|
this: Client,
|
|
@@ -60,7 +67,7 @@ export function submit(
|
|
|
60
67
|
|
|
61
68
|
const that = this;
|
|
62
69
|
|
|
63
|
-
if (!api_info) throw new Error(
|
|
70
|
+
if (!api_info) throw new Error(NO_API_INFO_MSG);
|
|
64
71
|
if (!config) throw new Error("Could not resolve app config");
|
|
65
72
|
|
|
66
73
|
let { fn_index, endpoint_info, dependency } = get_endpoint_info(
|
|
@@ -71,12 +78,65 @@ export function submit(
|
|
|
71
78
|
);
|
|
72
79
|
|
|
73
80
|
let resolved_data = map_data_to_params(data, endpoint_info);
|
|
74
|
-
|
|
75
|
-
let stream: EventSource | null;
|
|
76
81
|
let protocol = config.protocol ?? "ws";
|
|
77
82
|
if (protocol === "ws") {
|
|
78
|
-
throw new Error(
|
|
83
|
+
throw new Error(WS_PROTOCOL_MSG);
|
|
79
84
|
}
|
|
85
|
+
const history_endpoint =
|
|
86
|
+
typeof dependency.api_name === "string"
|
|
87
|
+
? `/${dependency.api_name}`
|
|
88
|
+
: endpoint;
|
|
89
|
+
const history_api_name =
|
|
90
|
+
typeof dependency.api_name === "string"
|
|
91
|
+
? `/${dependency.api_name}`
|
|
92
|
+
: `Function ${fn_index}`;
|
|
93
|
+
// Kept index-aligned with the stored payloads (null for components we
|
|
94
|
+
// cannot resolve) so every saved value stays matched to its component.
|
|
95
|
+
const component_metadata = (id: number) => {
|
|
96
|
+
const component = config.components.find((item) => item.id === id);
|
|
97
|
+
if (!component) return null;
|
|
98
|
+
return {
|
|
99
|
+
type: component.type,
|
|
100
|
+
component_class_id: component.component_class_id,
|
|
101
|
+
props: component.props
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
// The run history covers the same endpoints the API page documents, which
|
|
105
|
+
// it selects with exactly this predicate (see `ApiDocs.svelte`). That also
|
|
106
|
+
// keeps out the dependencies Gradio wires up for itself, since example
|
|
107
|
+
// loading, flagging and clear buttons are all "undocumented" or "private"
|
|
108
|
+
// and some of them fire on page load. The trade is that a component whose
|
|
109
|
+
// UI submits through an undocumented dependency — `gr.ChatInterface` does
|
|
110
|
+
// — records nothing for its in-app use.
|
|
111
|
+
const is_documented_endpoint = dependency.api_visibility === "public";
|
|
112
|
+
// Either side may opt out: the app for everyone who uses it, and this
|
|
113
|
+
// caller for itself.
|
|
114
|
+
const history_enabled =
|
|
115
|
+
config.run_history !== false && this.options.record_history !== false;
|
|
116
|
+
const history_scope = { app_id: config.app_id, username: config.username };
|
|
117
|
+
const history_run_id =
|
|
118
|
+
!history_enabled || !is_documented_endpoint
|
|
119
|
+
? null
|
|
120
|
+
: start_run_history({
|
|
121
|
+
...history_scope,
|
|
122
|
+
endpoint: history_endpoint,
|
|
123
|
+
api_name: history_api_name,
|
|
124
|
+
fn_index,
|
|
125
|
+
// Aligned to `dependency.inputs` the same way the submitted payload
|
|
126
|
+
// is, so this placeholder matches the components until the uploaded
|
|
127
|
+
// files are swapped in by `update_run_inputs` below.
|
|
128
|
+
inputs: handle_payload(
|
|
129
|
+
resolved_data,
|
|
130
|
+
dependency,
|
|
131
|
+
config.components,
|
|
132
|
+
"input",
|
|
133
|
+
true
|
|
134
|
+
),
|
|
135
|
+
input_components: dependency.inputs.map(component_metadata),
|
|
136
|
+
output_components: dependency.outputs.map(component_metadata)
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
let stream: EventSource | null;
|
|
80
140
|
let event_id_final = "";
|
|
81
141
|
let event_id_cb: () => string = () => event_id_final;
|
|
82
142
|
|
|
@@ -101,6 +161,7 @@ export function submit(
|
|
|
101
161
|
|
|
102
162
|
// event subscription methods
|
|
103
163
|
function fire_event(event: GradioEvent): void {
|
|
164
|
+
update_run_history(history_scope, history_run_id, event);
|
|
104
165
|
if (all_events || events_to_publish[event.type]) {
|
|
105
166
|
push_event(event);
|
|
106
167
|
}
|
|
@@ -178,11 +239,15 @@ export function submit(
|
|
|
178
239
|
"input",
|
|
179
240
|
true
|
|
180
241
|
);
|
|
242
|
+
update_run_inputs(history_scope, history_run_id, input_data || []);
|
|
181
243
|
payload = {
|
|
182
244
|
data: input_data || [],
|
|
183
245
|
event_data,
|
|
184
246
|
fn_index,
|
|
185
|
-
trigger_id
|
|
247
|
+
trigger_id,
|
|
248
|
+
...(options.oauth_token && endpoint_info?.oauth_token
|
|
249
|
+
? { oauth_token: options.oauth_token }
|
|
250
|
+
: {})
|
|
186
251
|
};
|
|
187
252
|
if (skip_queue(fn_index, config)) {
|
|
188
253
|
fire_event({
|
|
@@ -630,6 +695,22 @@ export function submit(
|
|
|
630
695
|
}
|
|
631
696
|
});
|
|
632
697
|
|
|
698
|
+
// Surface internal failures (e.g. malformed payloads or configs) as an
|
|
699
|
+
// error event instead of leaving the returned iterator hanging forever
|
|
700
|
+
// with an unhandled promise rejection.
|
|
701
|
+
job.catch((e) => {
|
|
702
|
+
fire_event({
|
|
703
|
+
type: "status",
|
|
704
|
+
stage: "error",
|
|
705
|
+
message: e instanceof Error ? e.message : String(e),
|
|
706
|
+
queue: !skip_queue(fn_index, config),
|
|
707
|
+
endpoint: _endpoint,
|
|
708
|
+
fn_index,
|
|
709
|
+
time: new Date()
|
|
710
|
+
});
|
|
711
|
+
close();
|
|
712
|
+
});
|
|
713
|
+
|
|
633
714
|
let done = false;
|
|
634
715
|
const values: (IteratorResult<GradioEvent> | PromiseLike<never>)[] = [];
|
|
635
716
|
const resolvers: ((
|
|
@@ -735,25 +816,37 @@ function get_endpoint_info(
|
|
|
735
816
|
} {
|
|
736
817
|
let fn_index: number;
|
|
737
818
|
let endpoint_info: EndpointInfo<JsApiData>;
|
|
738
|
-
let dependency: Dependency;
|
|
819
|
+
let dependency: Dependency | undefined;
|
|
739
820
|
|
|
740
821
|
if (typeof endpoint === "number") {
|
|
741
822
|
fn_index = endpoint;
|
|
742
823
|
endpoint_info = api_info.unnamed_endpoints[fn_index];
|
|
743
|
-
dependency = config.dependencies.find((dep) => dep.id == endpoint)
|
|
824
|
+
dependency = config.dependencies.find((dep) => dep.id == endpoint);
|
|
744
825
|
} else {
|
|
745
826
|
const trimmed_endpoint = endpoint.replace(/^\//, "");
|
|
746
827
|
|
|
747
828
|
fn_index = api_map[trimmed_endpoint];
|
|
748
|
-
|
|
829
|
+
// named endpoints are keyed with a leading slash in the API info, but
|
|
830
|
+
// accept endpoint names passed without one (e.g. "predict")
|
|
831
|
+
endpoint_info =
|
|
832
|
+
api_info.named_endpoints[endpoint.trim()] ??
|
|
833
|
+
api_info.named_endpoints[`/${trimmed_endpoint}`];
|
|
749
834
|
dependency = config.dependencies.find(
|
|
750
835
|
(dep) => dep.id == api_map[trimmed_endpoint]
|
|
751
|
-
)
|
|
836
|
+
);
|
|
752
837
|
}
|
|
753
838
|
|
|
754
|
-
if (typeof fn_index !== "number") {
|
|
839
|
+
if (typeof fn_index !== "number" || !dependency) {
|
|
840
|
+
const valid_endpoints = config.dependencies
|
|
841
|
+
.filter((dep) => dep.api_name)
|
|
842
|
+
.map((dep) => `"/${dep.api_name}"`)
|
|
843
|
+
.join(", ");
|
|
755
844
|
throw new Error(
|
|
756
|
-
|
|
845
|
+
`No endpoint matching ${JSON.stringify(endpoint)} was found. ` +
|
|
846
|
+
(valid_endpoints
|
|
847
|
+
? `Valid named endpoints are: ${valid_endpoints}. `
|
|
848
|
+
: "This app exposes no named endpoints. ") +
|
|
849
|
+
"An fn_index (number) of an existing dependency can also be used."
|
|
757
850
|
);
|
|
758
851
|
}
|
|
759
852
|
return { fn_index, endpoint_info, dependency };
|
package/vite.config.ts
CHANGED
|
@@ -38,7 +38,12 @@ logger.info = (log, options) => {
|
|
|
38
38
|
};
|
|
39
39
|
export default defineConfig(({ mode }) => {
|
|
40
40
|
const production = mode === "production";
|
|
41
|
-
|
|
41
|
+
// Single-file, minified browser bundle served from CDNs at
|
|
42
|
+
// dist/index.min.js (see https://github.com/gradio-app/gradio/issues/10028)
|
|
43
|
+
const isCdnBuild = process.env.CDN_BUILD === "true";
|
|
44
|
+
// a CDN build is always a browser build (guards against CDN_BUILD=true
|
|
45
|
+
// without BROWSER_BUILD=true emitting es+cjs into the same file name)
|
|
46
|
+
const isBrowserBuild = process.env.BROWSER_BUILD === "true" || isCdnBuild;
|
|
42
47
|
|
|
43
48
|
if (mode === "preview") {
|
|
44
49
|
return {
|
|
@@ -50,15 +55,26 @@ export default defineConfig(({ mode }) => {
|
|
|
50
55
|
customLogger: logger,
|
|
51
56
|
build: {
|
|
52
57
|
emptyOutDir: false,
|
|
58
|
+
...(isCdnBuild ? { minify: true } : {}),
|
|
53
59
|
lib: {
|
|
54
60
|
entry: "src/index.ts",
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
// the node build also emits a CommonJS bundle (dist/index.cjs)
|
|
62
|
+
// so that require("@gradio/client") works on all supported
|
|
63
|
+
// node versions (see https://github.com/gradio-app/gradio/issues/9214)
|
|
64
|
+
formats: isBrowserBuild ? ["es"] : ["es", "cjs"],
|
|
65
|
+
fileName: (format) => {
|
|
66
|
+
if (isCdnBuild) return "index.min.js";
|
|
67
|
+
if (isBrowserBuild) return "browser.js";
|
|
68
|
+
return format === "cjs" ? "index.cjs" : "index.js";
|
|
69
|
+
}
|
|
57
70
|
},
|
|
58
71
|
rollupOptions: {
|
|
59
72
|
input: "src/index.ts",
|
|
60
73
|
output: {
|
|
61
|
-
dir: "dist"
|
|
74
|
+
dir: "dist",
|
|
75
|
+
// keep the CDN bundle as a single file so the documented
|
|
76
|
+
// <script type="module"> import works without extra chunks
|
|
77
|
+
inlineDynamicImports: isCdnBuild
|
|
62
78
|
}
|
|
63
79
|
}
|
|
64
80
|
},
|