@gradio/core 0.22.0 → 0.23.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 +31 -0
- package/dist/src/Blocks.svelte +70 -17
- package/dist/src/api_docs/ApiDocs.svelte +98 -65
- package/dist/src/api_docs/CodeSnippet.svelte +8 -10
- package/dist/src/api_docs/CodeSnippet.svelte.d.ts +1 -2
- package/dist/src/api_docs/EndpointDetail.svelte +12 -13
- package/dist/src/api_docs/EndpointDetail.svelte.d.ts +1 -2
- package/dist/src/init.js +6 -2
- package/package.json +47 -47
- package/src/Blocks.svelte +79 -19
- package/src/api_docs/ApiDocs.svelte +106 -65
- package/src/api_docs/CodeSnippet.svelte +8 -10
- package/src/api_docs/EndpointDetail.svelte +12 -13
- package/src/init.ts +8 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# @gradio/core
|
|
2
2
|
|
|
3
|
+
## 0.23.0
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- [#11578](https://github.com/gradio-app/gradio/pull/11578) [`872798a`](https://github.com/gradio-app/gradio/commit/872798a780dd81c834a44b05277f6c9ebe09de8b) - Add an `api_description` parameter for API and MCP server. Thanks @abidlabs!
|
|
8
|
+
- [#11543](https://github.com/gradio-app/gradio/pull/11543) [`ac95ac0`](https://github.com/gradio-app/gradio/commit/ac95ac0d8c2e65d1632376e632fb7d16131334b6) - Connection handling messaging. Thanks @aliabid94!
|
|
9
|
+
- [#11508](https://github.com/gradio-app/gradio/pull/11508) [`f5a6fa8`](https://github.com/gradio-app/gradio/commit/f5a6fa8c52bcb8f508e10ea54a3427f3dab8e3f8) - Handle uploading files in mcp server automatically. Thanks @freddyaboulton!
|
|
10
|
+
- [#11515](https://github.com/gradio-app/gradio/pull/11515) [`2c24ca7`](https://github.com/gradio-app/gradio/commit/2c24ca709396291a344d981c19ed1655028b5d64) - Making it easier for MCP developers call APIs with user credentials. Thanks @freddyaboulton!
|
|
11
|
+
- [#11584](https://github.com/gradio-app/gradio/pull/11584) [`78428cb`](https://github.com/gradio-app/gradio/commit/78428cb29bf6dc66d583b7cf93dd404aef737e75) - Fix reload mode. Thanks @aliabid94!
|
|
12
|
+
|
|
13
|
+
### Fixes
|
|
14
|
+
|
|
15
|
+
- [#11590](https://github.com/gradio-app/gradio/pull/11590) [`33b6057`](https://github.com/gradio-app/gradio/commit/33b6057dc5cbdfdab15b1ee000b0f0b3d9f3fff6) - Add Gradio File Input keyword to gradio file inputs. Thanks @freddyaboulton!
|
|
16
|
+
|
|
17
|
+
### Dependency updates
|
|
18
|
+
|
|
19
|
+
- @gradio/video@0.14.21
|
|
20
|
+
- @gradio/client@1.15.6
|
|
21
|
+
- @gradio/statustracker@0.10.15
|
|
22
|
+
- @gradio/button@0.5.7
|
|
23
|
+
- @gradio/upload@0.16.11
|
|
24
|
+
- @gradio/checkbox@0.4.26
|
|
25
|
+
- @gradio/image@0.22.13
|
|
26
|
+
- @gradio/gallery@0.15.27
|
|
27
|
+
- @gradio/plot@0.9.20
|
|
28
|
+
- @gradio/textbox@0.10.17
|
|
29
|
+
- @gradio/file@0.12.24
|
|
30
|
+
- @gradio/code@0.14.11
|
|
31
|
+
- @gradio/paramviewer@0.7.13
|
|
32
|
+
- @gradio/column@0.2.1
|
|
33
|
+
|
|
3
34
|
## 0.22.0
|
|
4
35
|
|
|
5
36
|
### Features
|
package/dist/src/Blocks.svelte
CHANGED
|
@@ -35,6 +35,7 @@ export let api_prefix = "";
|
|
|
35
35
|
export let max_file_size = void 0;
|
|
36
36
|
export let initial_layout = void 0;
|
|
37
37
|
export let css = null;
|
|
38
|
+
let broken_connection = false;
|
|
38
39
|
let {
|
|
39
40
|
layout: _layout,
|
|
40
41
|
targets,
|
|
@@ -203,11 +204,13 @@ export function add_new_message(title2, message, type) {
|
|
|
203
204
|
messages = [new_message(title2, message, -1, type), ...messages];
|
|
204
205
|
}
|
|
205
206
|
let _error_id = -1;
|
|
206
|
-
let user_left_page = false;
|
|
207
207
|
const MESSAGE_QUOTE_RE = /^'([^]+)'$/;
|
|
208
208
|
const DUPLICATE_MESSAGE = $_("blocks.long_requests_queue");
|
|
209
209
|
const MOBILE_QUEUE_WARNING = $_("blocks.connection_can_break");
|
|
210
|
-
const
|
|
210
|
+
const LOST_CONNECTION_MESSAGE = "Connection to the server was lost. Attempting reconnection...";
|
|
211
|
+
const CHANGED_CONNECTION_MESSAGE = "Reconnected to server, but the server has changed. You may need to <a href=''>refresh the page</a>.";
|
|
212
|
+
const RECONNECTION_MESSAGE = "Connection re-established.";
|
|
213
|
+
const SESSION_NOT_FOUND_MESSAGE = "Session not found - this is likely because the machine you were connected to has changed. <a href=''>Refresh the page</a> to continue.";
|
|
211
214
|
const WAITING_FOR_INPUTS_MESSAGE = $_("blocks.waiting_for_inputs");
|
|
212
215
|
const SHOW_DUPLICATE_MESSAGE_ON_ETA = 15;
|
|
213
216
|
const SHOW_MOBILE_QUEUE_WARNING_ON_ETA = 10;
|
|
@@ -322,6 +325,42 @@ async function trigger_api_call(dep_index, trigger_id = null, event_data = null)
|
|
|
322
325
|
}
|
|
323
326
|
}
|
|
324
327
|
}
|
|
328
|
+
async function reconnect() {
|
|
329
|
+
const connection_status = await app.reconnect();
|
|
330
|
+
if (connection_status === "broken") {
|
|
331
|
+
setTimeout(reconnect, 1e3);
|
|
332
|
+
} else if (connection_status === "changed") {
|
|
333
|
+
broken_connection = false;
|
|
334
|
+
messages = [
|
|
335
|
+
new_message(
|
|
336
|
+
"Changed Connection",
|
|
337
|
+
CHANGED_CONNECTION_MESSAGE,
|
|
338
|
+
-1,
|
|
339
|
+
"info",
|
|
340
|
+
3,
|
|
341
|
+
true
|
|
342
|
+
),
|
|
343
|
+
...messages.map(
|
|
344
|
+
(m) => m.message === LOST_CONNECTION_MESSAGE ? { ...m, visible: false } : m
|
|
345
|
+
)
|
|
346
|
+
];
|
|
347
|
+
} else if (connection_status === "connected") {
|
|
348
|
+
broken_connection = false;
|
|
349
|
+
messages = [
|
|
350
|
+
new_message(
|
|
351
|
+
"Reconnected",
|
|
352
|
+
RECONNECTION_MESSAGE,
|
|
353
|
+
-1,
|
|
354
|
+
"success",
|
|
355
|
+
null,
|
|
356
|
+
true
|
|
357
|
+
),
|
|
358
|
+
...messages.map(
|
|
359
|
+
(m) => m.message === LOST_CONNECTION_MESSAGE ? { ...m, visible: false } : m
|
|
360
|
+
)
|
|
361
|
+
];
|
|
362
|
+
}
|
|
363
|
+
}
|
|
325
364
|
async function make_prediction(payload2, streaming = false) {
|
|
326
365
|
if (allow_video_trim) {
|
|
327
366
|
screen_recorder.markRemoveSegmentStart();
|
|
@@ -439,6 +478,34 @@ async function trigger_api_call(dep_index, trigger_id = null, event_data = null)
|
|
|
439
478
|
}
|
|
440
479
|
}
|
|
441
480
|
function handle_status_update(message) {
|
|
481
|
+
if (message.broken && !broken_connection) {
|
|
482
|
+
messages = [
|
|
483
|
+
new_message(
|
|
484
|
+
"Broken Connection",
|
|
485
|
+
LOST_CONNECTION_MESSAGE,
|
|
486
|
+
-1,
|
|
487
|
+
"error",
|
|
488
|
+
null,
|
|
489
|
+
true
|
|
490
|
+
),
|
|
491
|
+
...messages
|
|
492
|
+
];
|
|
493
|
+
broken_connection = true;
|
|
494
|
+
setTimeout(reconnect, 1e3);
|
|
495
|
+
}
|
|
496
|
+
if (message.session_not_found) {
|
|
497
|
+
messages = [
|
|
498
|
+
new_message(
|
|
499
|
+
"Session Not Found",
|
|
500
|
+
SESSION_NOT_FOUND_MESSAGE,
|
|
501
|
+
-1,
|
|
502
|
+
"error",
|
|
503
|
+
null,
|
|
504
|
+
true
|
|
505
|
+
),
|
|
506
|
+
...messages
|
|
507
|
+
];
|
|
508
|
+
}
|
|
442
509
|
const { fn_index, ...status } = message;
|
|
443
510
|
if (status.stage === "streaming" && status.time_limit) {
|
|
444
511
|
dep.inputs.forEach((id) => {
|
|
@@ -492,16 +559,7 @@ async function trigger_api_call(dep_index, trigger_id = null, event_data = null)
|
|
|
492
559
|
});
|
|
493
560
|
submit_map.delete(dep_index);
|
|
494
561
|
}
|
|
495
|
-
if (status.
|
|
496
|
-
window.setTimeout(() => {
|
|
497
|
-
messages = [
|
|
498
|
-
new_message("Error", MOBILE_RECONNECT_MESSAGE, fn_index, "error"),
|
|
499
|
-
...messages
|
|
500
|
-
];
|
|
501
|
-
}, 0);
|
|
502
|
-
wait_then_trigger_api_call(dep.id, payload2.trigger_id, event_data);
|
|
503
|
-
user_left_page = false;
|
|
504
|
-
} else if (status.stage === "error") {
|
|
562
|
+
if (status.stage === "error" && !broken_connection && !message.session_not_found) {
|
|
505
563
|
if (status.message) {
|
|
506
564
|
const _message = status.message.replace(
|
|
507
565
|
MESSAGE_QUOTE_RE,
|
|
@@ -672,11 +730,6 @@ function isCustomEvent(event) {
|
|
|
672
730
|
}
|
|
673
731
|
let is_screen_recording = writable(false);
|
|
674
732
|
onMount(() => {
|
|
675
|
-
document.addEventListener("visibilitychange", function() {
|
|
676
|
-
if (document.visibilityState === "hidden") {
|
|
677
|
-
user_left_page = true;
|
|
678
|
-
}
|
|
679
|
-
});
|
|
680
733
|
is_mobile_device = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
|
|
681
734
|
navigator.userAgent
|
|
682
735
|
);
|
|
@@ -65,16 +65,83 @@ get_js_info().then((js_api_info) => {
|
|
|
65
65
|
const dispatch = createEventDispatcher();
|
|
66
66
|
const mcp_server_url = `${root}gradio_api/mcp/sse`;
|
|
67
67
|
let tools = [];
|
|
68
|
+
let headers = [];
|
|
69
|
+
let mcp_json_sse;
|
|
70
|
+
let mcp_json_stdio;
|
|
71
|
+
let file_data_present = false;
|
|
72
|
+
const upload_file_mcp_server = {
|
|
73
|
+
command: "uvx",
|
|
74
|
+
args: [
|
|
75
|
+
"--from",
|
|
76
|
+
"gradio[mcp]",
|
|
77
|
+
"gradio",
|
|
78
|
+
"upload-mcp",
|
|
79
|
+
root,
|
|
80
|
+
"<UPLOAD_DIRECTORY>"
|
|
81
|
+
]
|
|
82
|
+
};
|
|
68
83
|
async function fetchMcpTools() {
|
|
69
84
|
try {
|
|
70
85
|
const response = await fetch(`${root}gradio_api/mcp/schema`);
|
|
71
86
|
const schema = await response.json();
|
|
87
|
+
file_data_present = schema.map((tool) => tool.meta?.file_data_present).some((present) => present);
|
|
72
88
|
tools = schema.map((tool) => ({
|
|
73
89
|
name: tool.name,
|
|
74
90
|
description: tool.description || "",
|
|
75
91
|
parameters: tool.inputSchema?.properties || {},
|
|
76
92
|
expanded: false
|
|
77
93
|
}));
|
|
94
|
+
headers = schema.map((tool) => tool.meta?.headers || []).flat();
|
|
95
|
+
if (headers.length > 0) {
|
|
96
|
+
mcp_json_sse = {
|
|
97
|
+
mcpServers: {
|
|
98
|
+
gradio: {
|
|
99
|
+
url: mcp_server_url,
|
|
100
|
+
headers: headers.reduce((accumulator, current_key) => {
|
|
101
|
+
accumulator[current_key] = "<YOUR_HEADER_VALUE>";
|
|
102
|
+
return accumulator;
|
|
103
|
+
}, {})
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
mcp_json_stdio = {
|
|
108
|
+
mcpServers: {
|
|
109
|
+
gradio: {
|
|
110
|
+
command: "npx",
|
|
111
|
+
args: [
|
|
112
|
+
"mcp-remote",
|
|
113
|
+
mcp_server_url,
|
|
114
|
+
"--transport",
|
|
115
|
+
"sse-only",
|
|
116
|
+
...headers.map((header) => [
|
|
117
|
+
"--header",
|
|
118
|
+
`${header}: <YOUR_HEADER_VALUE>`
|
|
119
|
+
]).flat()
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
} else {
|
|
125
|
+
mcp_json_sse = {
|
|
126
|
+
mcpServers: {
|
|
127
|
+
gradio: {
|
|
128
|
+
url: mcp_server_url
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
mcp_json_stdio = {
|
|
133
|
+
mcpServers: {
|
|
134
|
+
gradio: {
|
|
135
|
+
command: "npx",
|
|
136
|
+
args: ["mcp-remote", mcp_server_url, "--transport", "sse-only"]
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
if (file_data_present) {
|
|
141
|
+
mcp_json_sse.mcpServers.upload_files_to_gradio = upload_file_mcp_server;
|
|
142
|
+
mcp_json_stdio.mcpServers.upload_files_to_gradio = upload_file_mcp_server;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
78
145
|
} catch (error) {
|
|
79
146
|
console.error("Failed to fetch MCP tools:", error);
|
|
80
147
|
tools = [];
|
|
@@ -180,7 +247,7 @@ onMount(() => {
|
|
|
180
247
|
<div class="mcp-url">
|
|
181
248
|
<label
|
|
182
249
|
><span class="status-indicator active">●</span>MCP Server
|
|
183
|
-
URL</label
|
|
250
|
+
URL (SSE)</label
|
|
184
251
|
>
|
|
185
252
|
<div class="textbox">
|
|
186
253
|
<input type="text" readonly value={mcp_server_url} />
|
|
@@ -239,45 +306,42 @@ onMount(() => {
|
|
|
239
306
|
</div>
|
|
240
307
|
<p> </p>
|
|
241
308
|
|
|
242
|
-
<strong>
|
|
309
|
+
<strong>SSE Transport</strong>: To add this MCP to clients that
|
|
243
310
|
support SSE (e.g. Cursor, Windsurf, Cline), simply add the
|
|
244
|
-
following configuration to your MCP config
|
|
311
|
+
following configuration to your MCP config.
|
|
245
312
|
<p> </p>
|
|
246
313
|
<Block>
|
|
247
314
|
<code>
|
|
248
315
|
<div class="copy">
|
|
249
316
|
<CopyButton
|
|
250
|
-
code={JSON.stringify(
|
|
251
|
-
{
|
|
252
|
-
mcpServers: {
|
|
253
|
-
gradio: {
|
|
254
|
-
url: mcp_server_url
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
},
|
|
258
|
-
null,
|
|
259
|
-
2
|
|
260
|
-
)}
|
|
317
|
+
code={JSON.stringify(mcp_json_sse, null, 2)}
|
|
261
318
|
/>
|
|
262
319
|
</div>
|
|
263
320
|
<div>
|
|
264
|
-
<pre>{JSON.stringify(
|
|
265
|
-
{
|
|
266
|
-
mcpServers: {
|
|
267
|
-
gradio: {
|
|
268
|
-
url: mcp_server_url
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
},
|
|
272
|
-
null,
|
|
273
|
-
2
|
|
274
|
-
)}</pre>
|
|
321
|
+
<pre>{JSON.stringify(mcp_json_sse, null, 2)}</pre>
|
|
275
322
|
</div>
|
|
276
323
|
</code>
|
|
277
324
|
</Block>
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
325
|
+
{#if file_data_present}
|
|
326
|
+
<p> </p>
|
|
327
|
+
<em>Note about files</em>: Gradio MCP servers that have files
|
|
328
|
+
as inputs need the files as URLs, so the
|
|
329
|
+
<code>upload_files_to_gradio</code>
|
|
330
|
+
tool is included for your convenience. This tool can upload files
|
|
331
|
+
located in the specified <code>UPLOAD_DIRECTORY</code>
|
|
332
|
+
argument (an absolute path in your local machine) or any of its
|
|
333
|
+
subdirectories to the Gradio app. You can omit this tool if you
|
|
334
|
+
are fine manually uploading files yourself and providing the URLs.
|
|
335
|
+
Before using this tool, you must have
|
|
336
|
+
<a
|
|
337
|
+
href="https://docs.astral.sh/uv/getting-started/installation/"
|
|
338
|
+
target="_blank">uv installed</a
|
|
339
|
+
>.
|
|
340
|
+
<p> </p>
|
|
341
|
+
{/if}
|
|
342
|
+
|
|
343
|
+
<strong>STDIO Transport</strong>: For clients that only support
|
|
344
|
+
stdio (e.g. Claude Desktop), first
|
|
281
345
|
<a href="https://nodejs.org/en/download/" target="_blank"
|
|
282
346
|
>install Node.js</a
|
|
283
347
|
>. Then, you can use the following command:
|
|
@@ -286,43 +350,11 @@ onMount(() => {
|
|
|
286
350
|
<code>
|
|
287
351
|
<div class="copy">
|
|
288
352
|
<CopyButton
|
|
289
|
-
code={JSON.stringify(
|
|
290
|
-
{
|
|
291
|
-
mcpServers: {
|
|
292
|
-
gradio: {
|
|
293
|
-
command: "npx",
|
|
294
|
-
args: [
|
|
295
|
-
"mcp-remote",
|
|
296
|
-
mcp_server_url,
|
|
297
|
-
"--transport",
|
|
298
|
-
"sse-only"
|
|
299
|
-
]
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
},
|
|
303
|
-
null,
|
|
304
|
-
2
|
|
305
|
-
)}
|
|
353
|
+
code={JSON.stringify(mcp_json_stdio, null, 2)}
|
|
306
354
|
/>
|
|
307
355
|
</div>
|
|
308
356
|
<div>
|
|
309
|
-
<pre>{JSON.stringify(
|
|
310
|
-
{
|
|
311
|
-
mcpServers: {
|
|
312
|
-
gradio: {
|
|
313
|
-
command: "npx",
|
|
314
|
-
args: [
|
|
315
|
-
"mcp-remote",
|
|
316
|
-
mcp_server_url,
|
|
317
|
-
"--transport",
|
|
318
|
-
"sse-only"
|
|
319
|
-
]
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
},
|
|
323
|
-
null,
|
|
324
|
-
2
|
|
325
|
-
)}</pre>
|
|
357
|
+
<pre>{JSON.stringify(mcp_json_stdio, null, 2)}</pre>
|
|
326
358
|
</div>
|
|
327
359
|
</code>
|
|
328
360
|
</Block>
|
|
@@ -398,21 +430,22 @@ onMount(() => {
|
|
|
398
430
|
{/if}
|
|
399
431
|
|
|
400
432
|
{#if current_language !== "mcp"}
|
|
401
|
-
{#each dependencies as dependency
|
|
433
|
+
{#each dependencies as dependency}
|
|
402
434
|
{#if dependency.show_api && info.named_endpoints["/" + dependency.api_name]}
|
|
403
435
|
<div class="endpoint-container">
|
|
404
436
|
<CodeSnippet
|
|
405
|
-
named={true}
|
|
406
437
|
endpoint_parameters={info.named_endpoints[
|
|
407
438
|
"/" + dependency.api_name
|
|
408
439
|
].parameters}
|
|
409
440
|
{dependency}
|
|
410
|
-
{dependency_index}
|
|
411
441
|
{current_language}
|
|
412
442
|
{root}
|
|
413
443
|
{space_id}
|
|
414
444
|
{username}
|
|
415
445
|
api_prefix={app.api_prefix}
|
|
446
|
+
api_description={info.named_endpoints[
|
|
447
|
+
"/" + dependency.api_name
|
|
448
|
+
].description}
|
|
416
449
|
/>
|
|
417
450
|
|
|
418
451
|
<ParametersSnippet
|
|
@@ -3,14 +3,13 @@ import { represent_value, is_potentially_nested_file_data } from "./utils";
|
|
|
3
3
|
import { Block } from "@gradio/atoms";
|
|
4
4
|
import EndpointDetail from "./EndpointDetail.svelte";
|
|
5
5
|
export let dependency;
|
|
6
|
-
export let dependency_index;
|
|
7
6
|
export let root;
|
|
8
7
|
export let api_prefix;
|
|
9
8
|
export let space_id;
|
|
10
9
|
export let endpoint_parameters;
|
|
11
|
-
export let named;
|
|
12
10
|
export let username;
|
|
13
11
|
export let current_language;
|
|
12
|
+
export let api_description = null;
|
|
14
13
|
let python_code;
|
|
15
14
|
let js_code;
|
|
16
15
|
let bash_post_code;
|
|
@@ -29,11 +28,10 @@ $:
|
|
|
29
28
|
</script>
|
|
30
29
|
|
|
31
30
|
<div class="container">
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
{/if}
|
|
31
|
+
<EndpointDetail
|
|
32
|
+
api_name={dependency.api_name}
|
|
33
|
+
description={api_description}
|
|
34
|
+
/>
|
|
37
35
|
{#if current_language === "python"}
|
|
38
36
|
<Block>
|
|
39
37
|
<code>
|
|
@@ -86,9 +84,9 @@ const example{component} = await response_{i}.blob();
|
|
|
86
84
|
const client = await Client.connect(<span class="token string"
|
|
87
85
|
>"{space_id || root}"</span
|
|
88
86
|
>{#if username !== null}, {auth: ["{username}", **password**]}{/if});
|
|
89
|
-
const result = await client.predict(
|
|
90
|
-
|
|
91
|
-
|
|
87
|
+
const result = await client.predict(<span class="api-name"
|
|
88
|
+
>"/{dependency.api_name}"</span
|
|
89
|
+
>, { <!--
|
|
92
90
|
-->{#each endpoint_parameters as { label, parameter_name, type, python_type, component, example_input, serializer }, i}<!--
|
|
93
91
|
-->{#if blob_components.includes(component)}<!--
|
|
94
92
|
-->
|
|
@@ -3,14 +3,13 @@ import type { Dependency } from "../types";
|
|
|
3
3
|
declare const __propDef: {
|
|
4
4
|
props: {
|
|
5
5
|
dependency: Dependency;
|
|
6
|
-
dependency_index: number;
|
|
7
6
|
root: string;
|
|
8
7
|
api_prefix: string;
|
|
9
8
|
space_id: string | null;
|
|
10
9
|
endpoint_parameters: any;
|
|
11
|
-
named: boolean;
|
|
12
10
|
username: string | null;
|
|
13
11
|
current_language: "python" | "javascript" | "bash";
|
|
12
|
+
api_description?: (string | null) | undefined;
|
|
14
13
|
};
|
|
15
14
|
events: {
|
|
16
15
|
[evt: string]: CustomEvent<any>;
|
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
<script>export let api_name = null;
|
|
2
|
-
export let
|
|
3
|
-
export let named;
|
|
2
|
+
export let description = null;
|
|
4
3
|
</script>
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
{:else}
|
|
12
|
-
<h3>
|
|
13
|
-
fn_index:
|
|
14
|
-
<span class="post">{fn_index}</span>
|
|
15
|
-
</h3>
|
|
16
|
-
{/if}
|
|
5
|
+
<h3>
|
|
6
|
+
API name:
|
|
7
|
+
<span class="post">{"/" + api_name}</span>
|
|
8
|
+
<span class="desc">{description}</span>
|
|
9
|
+
</h3>
|
|
17
10
|
|
|
18
11
|
<style>
|
|
19
12
|
h3 {
|
|
@@ -33,4 +26,10 @@ export let named;
|
|
|
33
26
|
color: var(--color-accent);
|
|
34
27
|
font-weight: var(--weight-semibold);
|
|
35
28
|
}
|
|
29
|
+
|
|
30
|
+
.desc {
|
|
31
|
+
color: var(--body-text-color-subdued);
|
|
32
|
+
font-size: var(--text-lg);
|
|
33
|
+
margin-top: var(--size-1);
|
|
34
|
+
}
|
|
36
35
|
</style>
|
|
@@ -2,8 +2,7 @@ import { SvelteComponent } from "svelte";
|
|
|
2
2
|
declare const __propDef: {
|
|
3
3
|
props: {
|
|
4
4
|
api_name?: (string | null) | undefined;
|
|
5
|
-
|
|
6
|
-
named: boolean;
|
|
5
|
+
description?: (string | null) | undefined;
|
|
7
6
|
};
|
|
8
7
|
events: {
|
|
9
8
|
[evt: string]: CustomEvent<any>;
|
package/dist/src/init.js
CHANGED
|
@@ -48,8 +48,12 @@ export function create_components(initial_layout) {
|
|
|
48
48
|
if (instance_map) {
|
|
49
49
|
// re-render in reload mode
|
|
50
50
|
components.forEach((c) => {
|
|
51
|
-
if (c.props.value == null && c.
|
|
52
|
-
|
|
51
|
+
if (c.props.value == null && c.key) {
|
|
52
|
+
// If the component has a key, we preserve its value by finding a matching instance with the same key
|
|
53
|
+
const matching_instance = Object.values(instance_map).find((instance) => instance.key === c.key);
|
|
54
|
+
if (matching_instance) {
|
|
55
|
+
c.props.value = matching_instance.props.value;
|
|
56
|
+
}
|
|
53
57
|
}
|
|
54
58
|
});
|
|
55
59
|
}
|
package/package.json
CHANGED
|
@@ -1,67 +1,67 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gradio/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"devDependencies": {
|
|
6
|
-
"@gradio/accordion": "^0.5.19",
|
|
7
6
|
"@gradio/atoms": "^0.16.3",
|
|
8
|
-
"@gradio/audio": "^0.17.
|
|
7
|
+
"@gradio/audio": "^0.17.21",
|
|
8
|
+
"@gradio/accordion": "^0.5.20",
|
|
9
|
+
"@gradio/annotatedimage": "^0.9.25",
|
|
9
10
|
"@gradio/box": "^0.2.21",
|
|
10
|
-
"@gradio/
|
|
11
|
-
"@gradio/
|
|
12
|
-
"@gradio/
|
|
13
|
-
"@gradio/checkboxgroup": "^0.6.
|
|
14
|
-
"@gradio/
|
|
15
|
-
"@gradio/code": "^0.14.
|
|
16
|
-
"@gradio/
|
|
17
|
-
"@gradio/
|
|
11
|
+
"@gradio/button": "^0.5.7",
|
|
12
|
+
"@gradio/chatbot": "^0.26.18",
|
|
13
|
+
"@gradio/checkbox": "^0.4.26",
|
|
14
|
+
"@gradio/checkboxgroup": "^0.6.25",
|
|
15
|
+
"@gradio/client": "^1.15.6",
|
|
16
|
+
"@gradio/code": "^0.14.11",
|
|
17
|
+
"@gradio/colorpicker": "^0.4.25",
|
|
18
|
+
"@gradio/dataset": "^0.4.27",
|
|
19
|
+
"@gradio/datetime": "^0.3.18",
|
|
18
20
|
"@gradio/column": "^0.2.1",
|
|
19
|
-
"@gradio/dataframe": "^0.18.
|
|
20
|
-
"@gradio/
|
|
21
|
-
"@gradio/
|
|
22
|
-
"@gradio/
|
|
23
|
-
"@gradio/
|
|
24
|
-
"@gradio/
|
|
25
|
-
"@gradio/fileexplorer": "^0.5.34",
|
|
21
|
+
"@gradio/dataframe": "^0.18.3",
|
|
22
|
+
"@gradio/downloadbutton": "^0.4.7",
|
|
23
|
+
"@gradio/dropdown": "^0.9.25",
|
|
24
|
+
"@gradio/fallback": "^0.4.25",
|
|
25
|
+
"@gradio/file": "^0.12.24",
|
|
26
|
+
"@gradio/fileexplorer": "^0.5.35",
|
|
26
27
|
"@gradio/form": "^0.2.21",
|
|
27
|
-
"@gradio/gallery": "^0.15.26",
|
|
28
|
-
"@gradio/file": "^0.12.23",
|
|
29
28
|
"@gradio/group": "^0.2.0",
|
|
30
|
-
"@gradio/
|
|
29
|
+
"@gradio/gallery": "^0.15.27",
|
|
30
|
+
"@gradio/highlightedtext": "^0.9.8",
|
|
31
|
+
"@gradio/html": "^0.6.17",
|
|
31
32
|
"@gradio/icons": "^0.12.0",
|
|
32
|
-
"@gradio/image": "^0.22.
|
|
33
|
-
"@gradio/
|
|
34
|
-
"@gradio/
|
|
35
|
-
"@gradio/
|
|
36
|
-
"@gradio/label": "^0.5.16",
|
|
33
|
+
"@gradio/image": "^0.22.13",
|
|
34
|
+
"@gradio/imageeditor": "^0.16.1",
|
|
35
|
+
"@gradio/imageslider": "^0.2.9",
|
|
36
|
+
"@gradio/json": "^0.5.27",
|
|
37
37
|
"@gradio/browserstate": "^0.3.2",
|
|
38
|
-
"@gradio/
|
|
39
|
-
"@gradio/markdown": "^0.13.
|
|
40
|
-
"@gradio/
|
|
41
|
-
"@gradio/nativeplot": "^0.7.
|
|
42
|
-
"@gradio/
|
|
43
|
-
"@gradio/
|
|
44
|
-
"@gradio/
|
|
45
|
-
"@gradio/plot": "^0.9.
|
|
46
|
-
"@gradio/radio": "^0.7.
|
|
38
|
+
"@gradio/model3d": "^0.14.20",
|
|
39
|
+
"@gradio/markdown": "^0.13.18",
|
|
40
|
+
"@gradio/label": "^0.5.17",
|
|
41
|
+
"@gradio/nativeplot": "^0.7.2",
|
|
42
|
+
"@gradio/number": "^0.6.2",
|
|
43
|
+
"@gradio/paramviewer": "^0.7.13",
|
|
44
|
+
"@gradio/multimodaltextbox": "^0.10.13",
|
|
45
|
+
"@gradio/plot": "^0.9.20",
|
|
46
|
+
"@gradio/radio": "^0.7.8",
|
|
47
47
|
"@gradio/row": "^0.2.1",
|
|
48
|
-
"@gradio/sidebar": "^0.1.
|
|
49
|
-
"@gradio/
|
|
50
|
-
"@gradio/simpleimage": "^0.8.
|
|
51
|
-
"@gradio/
|
|
52
|
-
"@gradio/
|
|
48
|
+
"@gradio/sidebar": "^0.1.18",
|
|
49
|
+
"@gradio/simpletextbox": "^0.3.26",
|
|
50
|
+
"@gradio/simpleimage": "^0.8.35",
|
|
51
|
+
"@gradio/sketchbox": "^0.6.13",
|
|
52
|
+
"@gradio/slider": "^0.6.14",
|
|
53
|
+
"@gradio/simpledropdown": "^0.3.25",
|
|
53
54
|
"@gradio/state": "^0.1.2",
|
|
54
|
-
"@gradio/
|
|
55
|
-
"@gradio/statustracker": "^0.10.14",
|
|
56
|
-
"@gradio/tabitem": "^0.5.0",
|
|
55
|
+
"@gradio/statustracker": "^0.10.15",
|
|
57
56
|
"@gradio/tabs": "^0.4.5",
|
|
58
|
-
"@gradio/textbox": "^0.10.
|
|
57
|
+
"@gradio/textbox": "^0.10.17",
|
|
58
|
+
"@gradio/tabitem": "^0.5.0",
|
|
59
59
|
"@gradio/theme": "^0.4.0",
|
|
60
60
|
"@gradio/timer": "^0.4.5",
|
|
61
|
-
"@gradio/upload": "^0.16.
|
|
62
|
-
"@gradio/uploadbutton": "^0.9.
|
|
61
|
+
"@gradio/upload": "^0.16.11",
|
|
62
|
+
"@gradio/uploadbutton": "^0.9.7",
|
|
63
63
|
"@gradio/utils": "^0.10.2",
|
|
64
|
-
"@gradio/video": "^0.14.
|
|
64
|
+
"@gradio/video": "^0.14.21",
|
|
65
65
|
"@gradio/wasm": "^0.18.1"
|
|
66
66
|
},
|
|
67
67
|
"msw": {
|
package/src/Blocks.svelte
CHANGED
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
export let max_file_size: number | undefined = undefined;
|
|
57
57
|
export let initial_layout: ComponentMeta | undefined = undefined;
|
|
58
58
|
export let css: string | null | undefined = null;
|
|
59
|
+
let broken_connection = false;
|
|
59
60
|
|
|
60
61
|
let {
|
|
61
62
|
layout: _layout,
|
|
@@ -275,13 +276,17 @@
|
|
|
275
276
|
|
|
276
277
|
let _error_id = -1;
|
|
277
278
|
|
|
278
|
-
let user_left_page = false;
|
|
279
|
-
|
|
280
279
|
const MESSAGE_QUOTE_RE = /^'([^]+)'$/;
|
|
281
280
|
|
|
282
281
|
const DUPLICATE_MESSAGE = $_("blocks.long_requests_queue");
|
|
283
282
|
const MOBILE_QUEUE_WARNING = $_("blocks.connection_can_break");
|
|
284
|
-
const
|
|
283
|
+
const LOST_CONNECTION_MESSAGE =
|
|
284
|
+
"Connection to the server was lost. Attempting reconnection...";
|
|
285
|
+
const CHANGED_CONNECTION_MESSAGE =
|
|
286
|
+
"Reconnected to server, but the server has changed. You may need to <a href=''>refresh the page</a>.";
|
|
287
|
+
const RECONNECTION_MESSAGE = "Connection re-established.";
|
|
288
|
+
const SESSION_NOT_FOUND_MESSAGE =
|
|
289
|
+
"Session not found - this is likely because the machine you were connected to has changed. <a href=''>Refresh the page</a> to continue.";
|
|
285
290
|
const WAITING_FOR_INPUTS_MESSAGE = $_("blocks.waiting_for_inputs");
|
|
286
291
|
const SHOW_DUPLICATE_MESSAGE_ON_ETA = 15;
|
|
287
292
|
const SHOW_MOBILE_QUEUE_WARNING_ON_ETA = 10;
|
|
@@ -424,6 +429,43 @@
|
|
|
424
429
|
}
|
|
425
430
|
}
|
|
426
431
|
|
|
432
|
+
async function reconnect(): Promise<void> {
|
|
433
|
+
const connection_status = await app.reconnect();
|
|
434
|
+
if (connection_status === "broken") {
|
|
435
|
+
setTimeout(reconnect, 1000);
|
|
436
|
+
} else if (connection_status === "changed") {
|
|
437
|
+
broken_connection = false;
|
|
438
|
+
messages = [
|
|
439
|
+
new_message(
|
|
440
|
+
"Changed Connection",
|
|
441
|
+
CHANGED_CONNECTION_MESSAGE,
|
|
442
|
+
-1,
|
|
443
|
+
"info",
|
|
444
|
+
3,
|
|
445
|
+
true
|
|
446
|
+
),
|
|
447
|
+
...messages.map((m) =>
|
|
448
|
+
m.message === LOST_CONNECTION_MESSAGE ? { ...m, visible: false } : m
|
|
449
|
+
)
|
|
450
|
+
];
|
|
451
|
+
} else if (connection_status === "connected") {
|
|
452
|
+
broken_connection = false;
|
|
453
|
+
messages = [
|
|
454
|
+
new_message(
|
|
455
|
+
"Reconnected",
|
|
456
|
+
RECONNECTION_MESSAGE,
|
|
457
|
+
-1,
|
|
458
|
+
"success",
|
|
459
|
+
null,
|
|
460
|
+
true
|
|
461
|
+
),
|
|
462
|
+
...messages.map((m) =>
|
|
463
|
+
m.message === LOST_CONNECTION_MESSAGE ? { ...m, visible: false } : m
|
|
464
|
+
)
|
|
465
|
+
];
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
427
469
|
async function make_prediction(
|
|
428
470
|
payload: Payload,
|
|
429
471
|
streaming = false
|
|
@@ -567,6 +609,35 @@
|
|
|
567
609
|
|
|
568
610
|
/* eslint-disable complexity */
|
|
569
611
|
function handle_status_update(message: StatusMessage): void {
|
|
612
|
+
if (message.broken && !broken_connection) {
|
|
613
|
+
messages = [
|
|
614
|
+
new_message(
|
|
615
|
+
"Broken Connection",
|
|
616
|
+
LOST_CONNECTION_MESSAGE,
|
|
617
|
+
-1,
|
|
618
|
+
"error",
|
|
619
|
+
null,
|
|
620
|
+
true
|
|
621
|
+
),
|
|
622
|
+
...messages
|
|
623
|
+
];
|
|
624
|
+
|
|
625
|
+
broken_connection = true;
|
|
626
|
+
setTimeout(reconnect, 1000);
|
|
627
|
+
}
|
|
628
|
+
if (message.session_not_found) {
|
|
629
|
+
messages = [
|
|
630
|
+
new_message(
|
|
631
|
+
"Session Not Found",
|
|
632
|
+
SESSION_NOT_FOUND_MESSAGE,
|
|
633
|
+
-1,
|
|
634
|
+
"error",
|
|
635
|
+
null,
|
|
636
|
+
true
|
|
637
|
+
),
|
|
638
|
+
...messages
|
|
639
|
+
];
|
|
640
|
+
}
|
|
570
641
|
const { fn_index, ...status } = message;
|
|
571
642
|
if (status.stage === "streaming" && status.time_limit) {
|
|
572
643
|
dep.inputs.forEach((id) => {
|
|
@@ -636,16 +707,11 @@
|
|
|
636
707
|
});
|
|
637
708
|
submit_map.delete(dep_index);
|
|
638
709
|
}
|
|
639
|
-
if (
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
];
|
|
645
|
-
}, 0);
|
|
646
|
-
wait_then_trigger_api_call(dep.id, payload.trigger_id, event_data);
|
|
647
|
-
user_left_page = false;
|
|
648
|
-
} else if (status.stage === "error") {
|
|
710
|
+
if (
|
|
711
|
+
status.stage === "error" &&
|
|
712
|
+
!broken_connection &&
|
|
713
|
+
!message.session_not_found
|
|
714
|
+
) {
|
|
649
715
|
if (status.message) {
|
|
650
716
|
const _message = status.message.replace(
|
|
651
717
|
MESSAGE_QUOTE_RE,
|
|
@@ -851,12 +917,6 @@
|
|
|
851
917
|
let is_screen_recording = writable(false);
|
|
852
918
|
|
|
853
919
|
onMount(() => {
|
|
854
|
-
document.addEventListener("visibilitychange", function () {
|
|
855
|
-
if (document.visibilityState === "hidden") {
|
|
856
|
-
user_left_page = true;
|
|
857
|
-
}
|
|
858
|
-
});
|
|
859
|
-
|
|
860
920
|
is_mobile_device =
|
|
861
921
|
/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
|
|
862
922
|
navigator.userAgent
|
|
@@ -112,11 +112,30 @@
|
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
let tools: Tool[] = [];
|
|
115
|
+
let headers: string[] = [];
|
|
116
|
+
let mcp_json_sse: any;
|
|
117
|
+
let mcp_json_stdio: any;
|
|
118
|
+
let file_data_present = false;
|
|
119
|
+
|
|
120
|
+
const upload_file_mcp_server = {
|
|
121
|
+
command: "uvx",
|
|
122
|
+
args: [
|
|
123
|
+
"--from",
|
|
124
|
+
"gradio[mcp]",
|
|
125
|
+
"gradio",
|
|
126
|
+
"upload-mcp",
|
|
127
|
+
root,
|
|
128
|
+
"<UPLOAD_DIRECTORY>"
|
|
129
|
+
]
|
|
130
|
+
};
|
|
115
131
|
|
|
116
132
|
async function fetchMcpTools() {
|
|
117
133
|
try {
|
|
118
134
|
const response = await fetch(`${root}gradio_api/mcp/schema`);
|
|
119
135
|
const schema = await response.json();
|
|
136
|
+
file_data_present = schema
|
|
137
|
+
.map((tool: any) => tool.meta?.file_data_present)
|
|
138
|
+
.some((present: boolean) => present);
|
|
120
139
|
|
|
121
140
|
tools = schema.map((tool: any) => ({
|
|
122
141
|
name: tool.name,
|
|
@@ -124,6 +143,62 @@
|
|
|
124
143
|
parameters: tool.inputSchema?.properties || {},
|
|
125
144
|
expanded: false
|
|
126
145
|
}));
|
|
146
|
+
headers = schema.map((tool: any) => tool.meta?.headers || []).flat();
|
|
147
|
+
if (headers.length > 0) {
|
|
148
|
+
mcp_json_sse = {
|
|
149
|
+
mcpServers: {
|
|
150
|
+
gradio: {
|
|
151
|
+
url: mcp_server_url,
|
|
152
|
+
headers: headers.reduce((accumulator, current_key) => {
|
|
153
|
+
// @ts-ignore
|
|
154
|
+
accumulator[current_key] = "<YOUR_HEADER_VALUE>";
|
|
155
|
+
return accumulator;
|
|
156
|
+
}, {})
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
mcp_json_stdio = {
|
|
161
|
+
mcpServers: {
|
|
162
|
+
gradio: {
|
|
163
|
+
command: "npx",
|
|
164
|
+
args: [
|
|
165
|
+
"mcp-remote",
|
|
166
|
+
mcp_server_url,
|
|
167
|
+
"--transport",
|
|
168
|
+
"sse-only",
|
|
169
|
+
...headers
|
|
170
|
+
.map((header) => [
|
|
171
|
+
"--header",
|
|
172
|
+
`${header}: <YOUR_HEADER_VALUE>`
|
|
173
|
+
])
|
|
174
|
+
.flat()
|
|
175
|
+
]
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
} else {
|
|
180
|
+
mcp_json_sse = {
|
|
181
|
+
mcpServers: {
|
|
182
|
+
gradio: {
|
|
183
|
+
url: mcp_server_url
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
mcp_json_stdio = {
|
|
188
|
+
mcpServers: {
|
|
189
|
+
gradio: {
|
|
190
|
+
command: "npx",
|
|
191
|
+
args: ["mcp-remote", mcp_server_url, "--transport", "sse-only"]
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
if (file_data_present) {
|
|
196
|
+
mcp_json_sse.mcpServers.upload_files_to_gradio =
|
|
197
|
+
upload_file_mcp_server;
|
|
198
|
+
mcp_json_stdio.mcpServers.upload_files_to_gradio =
|
|
199
|
+
upload_file_mcp_server;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
127
202
|
} catch (error) {
|
|
128
203
|
console.error("Failed to fetch MCP tools:", error);
|
|
129
204
|
tools = [];
|
|
@@ -235,7 +310,7 @@
|
|
|
235
310
|
<div class="mcp-url">
|
|
236
311
|
<label
|
|
237
312
|
><span class="status-indicator active">●</span>MCP Server
|
|
238
|
-
URL</label
|
|
313
|
+
URL (SSE)</label
|
|
239
314
|
>
|
|
240
315
|
<div class="textbox">
|
|
241
316
|
<input type="text" readonly value={mcp_server_url} />
|
|
@@ -294,45 +369,42 @@
|
|
|
294
369
|
</div>
|
|
295
370
|
<p> </p>
|
|
296
371
|
|
|
297
|
-
<strong>
|
|
372
|
+
<strong>SSE Transport</strong>: To add this MCP to clients that
|
|
298
373
|
support SSE (e.g. Cursor, Windsurf, Cline), simply add the
|
|
299
|
-
following configuration to your MCP config
|
|
374
|
+
following configuration to your MCP config.
|
|
300
375
|
<p> </p>
|
|
301
376
|
<Block>
|
|
302
377
|
<code>
|
|
303
378
|
<div class="copy">
|
|
304
379
|
<CopyButton
|
|
305
|
-
code={JSON.stringify(
|
|
306
|
-
{
|
|
307
|
-
mcpServers: {
|
|
308
|
-
gradio: {
|
|
309
|
-
url: mcp_server_url
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
},
|
|
313
|
-
null,
|
|
314
|
-
2
|
|
315
|
-
)}
|
|
380
|
+
code={JSON.stringify(mcp_json_sse, null, 2)}
|
|
316
381
|
/>
|
|
317
382
|
</div>
|
|
318
383
|
<div>
|
|
319
|
-
<pre>{JSON.stringify(
|
|
320
|
-
{
|
|
321
|
-
mcpServers: {
|
|
322
|
-
gradio: {
|
|
323
|
-
url: mcp_server_url
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
},
|
|
327
|
-
null,
|
|
328
|
-
2
|
|
329
|
-
)}</pre>
|
|
384
|
+
<pre>{JSON.stringify(mcp_json_sse, null, 2)}</pre>
|
|
330
385
|
</div>
|
|
331
386
|
</code>
|
|
332
387
|
</Block>
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
388
|
+
{#if file_data_present}
|
|
389
|
+
<p> </p>
|
|
390
|
+
<em>Note about files</em>: Gradio MCP servers that have files
|
|
391
|
+
as inputs need the files as URLs, so the
|
|
392
|
+
<code>upload_files_to_gradio</code>
|
|
393
|
+
tool is included for your convenience. This tool can upload files
|
|
394
|
+
located in the specified <code>UPLOAD_DIRECTORY</code>
|
|
395
|
+
argument (an absolute path in your local machine) or any of its
|
|
396
|
+
subdirectories to the Gradio app. You can omit this tool if you
|
|
397
|
+
are fine manually uploading files yourself and providing the URLs.
|
|
398
|
+
Before using this tool, you must have
|
|
399
|
+
<a
|
|
400
|
+
href="https://docs.astral.sh/uv/getting-started/installation/"
|
|
401
|
+
target="_blank">uv installed</a
|
|
402
|
+
>.
|
|
403
|
+
<p> </p>
|
|
404
|
+
{/if}
|
|
405
|
+
|
|
406
|
+
<strong>STDIO Transport</strong>: For clients that only support
|
|
407
|
+
stdio (e.g. Claude Desktop), first
|
|
336
408
|
<a href="https://nodejs.org/en/download/" target="_blank"
|
|
337
409
|
>install Node.js</a
|
|
338
410
|
>. Then, you can use the following command:
|
|
@@ -341,43 +413,11 @@
|
|
|
341
413
|
<code>
|
|
342
414
|
<div class="copy">
|
|
343
415
|
<CopyButton
|
|
344
|
-
code={JSON.stringify(
|
|
345
|
-
{
|
|
346
|
-
mcpServers: {
|
|
347
|
-
gradio: {
|
|
348
|
-
command: "npx",
|
|
349
|
-
args: [
|
|
350
|
-
"mcp-remote",
|
|
351
|
-
mcp_server_url,
|
|
352
|
-
"--transport",
|
|
353
|
-
"sse-only"
|
|
354
|
-
]
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
},
|
|
358
|
-
null,
|
|
359
|
-
2
|
|
360
|
-
)}
|
|
416
|
+
code={JSON.stringify(mcp_json_stdio, null, 2)}
|
|
361
417
|
/>
|
|
362
418
|
</div>
|
|
363
419
|
<div>
|
|
364
|
-
<pre>{JSON.stringify(
|
|
365
|
-
{
|
|
366
|
-
mcpServers: {
|
|
367
|
-
gradio: {
|
|
368
|
-
command: "npx",
|
|
369
|
-
args: [
|
|
370
|
-
"mcp-remote",
|
|
371
|
-
mcp_server_url,
|
|
372
|
-
"--transport",
|
|
373
|
-
"sse-only"
|
|
374
|
-
]
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
},
|
|
378
|
-
null,
|
|
379
|
-
2
|
|
380
|
-
)}</pre>
|
|
420
|
+
<pre>{JSON.stringify(mcp_json_stdio, null, 2)}</pre>
|
|
381
421
|
</div>
|
|
382
422
|
</code>
|
|
383
423
|
</Block>
|
|
@@ -453,21 +493,22 @@
|
|
|
453
493
|
{/if}
|
|
454
494
|
|
|
455
495
|
{#if current_language !== "mcp"}
|
|
456
|
-
{#each dependencies as dependency
|
|
496
|
+
{#each dependencies as dependency}
|
|
457
497
|
{#if dependency.show_api && info.named_endpoints["/" + dependency.api_name]}
|
|
458
498
|
<div class="endpoint-container">
|
|
459
499
|
<CodeSnippet
|
|
460
|
-
named={true}
|
|
461
500
|
endpoint_parameters={info.named_endpoints[
|
|
462
501
|
"/" + dependency.api_name
|
|
463
502
|
].parameters}
|
|
464
503
|
{dependency}
|
|
465
|
-
{dependency_index}
|
|
466
504
|
{current_language}
|
|
467
505
|
{root}
|
|
468
506
|
{space_id}
|
|
469
507
|
{username}
|
|
470
508
|
api_prefix={app.api_prefix}
|
|
509
|
+
api_description={info.named_endpoints[
|
|
510
|
+
"/" + dependency.api_name
|
|
511
|
+
].description}
|
|
471
512
|
/>
|
|
472
513
|
|
|
473
514
|
<ParametersSnippet
|
|
@@ -15,14 +15,13 @@
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export let dependency: Dependency;
|
|
18
|
-
export let dependency_index: number;
|
|
19
18
|
export let root: string;
|
|
20
19
|
export let api_prefix: string;
|
|
21
20
|
export let space_id: string | null;
|
|
22
21
|
export let endpoint_parameters: any;
|
|
23
|
-
export let named: boolean;
|
|
24
22
|
export let username: string | null;
|
|
25
23
|
export let current_language: "python" | "javascript" | "bash";
|
|
24
|
+
export let api_description: string | null = null;
|
|
26
25
|
|
|
27
26
|
let python_code: HTMLElement;
|
|
28
27
|
let js_code: HTMLElement;
|
|
@@ -42,11 +41,10 @@
|
|
|
42
41
|
</script>
|
|
43
42
|
|
|
44
43
|
<div class="container">
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
{/if}
|
|
44
|
+
<EndpointDetail
|
|
45
|
+
api_name={dependency.api_name}
|
|
46
|
+
description={api_description}
|
|
47
|
+
/>
|
|
50
48
|
{#if current_language === "python"}
|
|
51
49
|
<Block>
|
|
52
50
|
<code>
|
|
@@ -99,9 +97,9 @@ const example{component} = await response_{i}.blob();
|
|
|
99
97
|
const client = await Client.connect(<span class="token string"
|
|
100
98
|
>"{space_id || root}"</span
|
|
101
99
|
>{#if username !== null}, {auth: ["{username}", **password**]}{/if});
|
|
102
|
-
const result = await client.predict(
|
|
103
|
-
|
|
104
|
-
|
|
100
|
+
const result = await client.predict(<span class="api-name"
|
|
101
|
+
>"/{dependency.api_name}"</span
|
|
102
|
+
>, { <!--
|
|
105
103
|
-->{#each endpoint_parameters as { label, parameter_name, type, python_type, component, example_input, serializer }, i}<!--
|
|
106
104
|
-->{#if blob_components.includes(component)}<!--
|
|
107
105
|
-->
|
|
@@ -1,20 +1,13 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
export let api_name: string | null = null;
|
|
3
|
-
export let
|
|
4
|
-
export let named: boolean;
|
|
3
|
+
export let description: string | null = null;
|
|
5
4
|
</script>
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
{:else}
|
|
13
|
-
<h3>
|
|
14
|
-
fn_index:
|
|
15
|
-
<span class="post">{fn_index}</span>
|
|
16
|
-
</h3>
|
|
17
|
-
{/if}
|
|
6
|
+
<h3>
|
|
7
|
+
API name:
|
|
8
|
+
<span class="post">{"/" + api_name}</span>
|
|
9
|
+
<span class="desc">{description}</span>
|
|
10
|
+
</h3>
|
|
18
11
|
|
|
19
12
|
<style>
|
|
20
13
|
h3 {
|
|
@@ -34,4 +27,10 @@
|
|
|
34
27
|
color: var(--color-accent);
|
|
35
28
|
font-weight: var(--weight-semibold);
|
|
36
29
|
}
|
|
30
|
+
|
|
31
|
+
.desc {
|
|
32
|
+
color: var(--body-text-color-subdued);
|
|
33
|
+
font-size: var(--text-lg);
|
|
34
|
+
margin-top: var(--size-1);
|
|
35
|
+
}
|
|
37
36
|
</style>
|
package/src/init.ts
CHANGED
|
@@ -114,8 +114,14 @@ export function create_components(initial_layout: ComponentMeta | undefined): {
|
|
|
114
114
|
if (instance_map) {
|
|
115
115
|
// re-render in reload mode
|
|
116
116
|
components.forEach((c) => {
|
|
117
|
-
if (c.props.value == null && c.
|
|
118
|
-
|
|
117
|
+
if (c.props.value == null && c.key) {
|
|
118
|
+
// If the component has a key, we preserve its value by finding a matching instance with the same key
|
|
119
|
+
const matching_instance = Object.values(instance_map).find(
|
|
120
|
+
(instance) => instance.key === c.key
|
|
121
|
+
);
|
|
122
|
+
if (matching_instance) {
|
|
123
|
+
c.props.value = matching_instance.props.value;
|
|
124
|
+
}
|
|
119
125
|
}
|
|
120
126
|
});
|
|
121
127
|
}
|