@gradio/core 0.23.2 → 0.25.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/dist/src/Blocks.svelte +28 -1
- package/dist/src/Blocks.svelte.d.ts +1 -0
- package/dist/src/api_docs/ApiBanner.svelte +1 -1
- package/dist/src/api_docs/ApiDocs.svelte +52 -270
- package/dist/src/api_docs/MCPSnippet.svelte +571 -0
- package/dist/src/api_docs/MCPSnippet.svelte.d.ts +47 -0
- package/package.json +32 -31
- package/src/Blocks.svelte +32 -1
- package/src/api_docs/ApiBanner.svelte +1 -1
- package/src/api_docs/ApiDocs.svelte +58 -271
- package/src/api_docs/MCPSnippet.svelte +602 -0
|
@@ -0,0 +1,602 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Block } from "@gradio/atoms";
|
|
3
|
+
import CopyButton from "./CopyButton.svelte";
|
|
4
|
+
|
|
5
|
+
export let mcp_server_active: boolean;
|
|
6
|
+
export let mcp_server_url: string;
|
|
7
|
+
export let mcp_server_url_streamable: string;
|
|
8
|
+
export let tools: Tool[];
|
|
9
|
+
export let all_tools: Tool[] = [];
|
|
10
|
+
export let selected_tools: Set<string> = new Set();
|
|
11
|
+
export let mcp_json_sse: any;
|
|
12
|
+
export let mcp_json_stdio: any;
|
|
13
|
+
export let file_data_present: boolean;
|
|
14
|
+
export let mcp_docs: string;
|
|
15
|
+
|
|
16
|
+
interface ToolParameter {
|
|
17
|
+
title?: string;
|
|
18
|
+
type: string;
|
|
19
|
+
description: string;
|
|
20
|
+
format?: string;
|
|
21
|
+
default?: any;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface Tool {
|
|
25
|
+
name: string;
|
|
26
|
+
description: string;
|
|
27
|
+
parameters: Record<string, ToolParameter>;
|
|
28
|
+
expanded?: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
type Transport = "streamable_http" | "sse" | "stdio";
|
|
32
|
+
let current_transport: Transport = "streamable_http";
|
|
33
|
+
let include_file_upload = true;
|
|
34
|
+
|
|
35
|
+
const transports = [
|
|
36
|
+
["streamable_http", "Streamable HTTP"],
|
|
37
|
+
["sse", "SSE"],
|
|
38
|
+
["stdio", "STDIO"]
|
|
39
|
+
] as const;
|
|
40
|
+
|
|
41
|
+
$: display_url =
|
|
42
|
+
current_transport === "sse" ? mcp_server_url : mcp_server_url_streamable;
|
|
43
|
+
|
|
44
|
+
// Helper function to add/remove file upload tool from config
|
|
45
|
+
function update_config_with_file_upload(
|
|
46
|
+
base_config: any,
|
|
47
|
+
include_upload: boolean
|
|
48
|
+
): any {
|
|
49
|
+
if (!base_config) return null;
|
|
50
|
+
|
|
51
|
+
const config = JSON.parse(JSON.stringify(base_config));
|
|
52
|
+
|
|
53
|
+
if (include_upload && file_data_present) {
|
|
54
|
+
const upload_file_mcp_server = {
|
|
55
|
+
command: "uvx",
|
|
56
|
+
args: [
|
|
57
|
+
"--from",
|
|
58
|
+
"gradio[mcp]",
|
|
59
|
+
"gradio",
|
|
60
|
+
"upload-mcp",
|
|
61
|
+
current_transport === "sse"
|
|
62
|
+
? mcp_server_url
|
|
63
|
+
: mcp_server_url_streamable,
|
|
64
|
+
"<UPLOAD_DIRECTORY>"
|
|
65
|
+
]
|
|
66
|
+
};
|
|
67
|
+
config.mcpServers.upload_files_to_gradio = upload_file_mcp_server;
|
|
68
|
+
} else {
|
|
69
|
+
delete config.mcpServers?.upload_files_to_gradio;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return config;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
$: mcp_json_streamable_http = update_config_with_file_upload(
|
|
76
|
+
mcp_json_sse
|
|
77
|
+
? {
|
|
78
|
+
...mcp_json_sse,
|
|
79
|
+
mcpServers: {
|
|
80
|
+
...mcp_json_sse.mcpServers,
|
|
81
|
+
gradio: {
|
|
82
|
+
...mcp_json_sse.mcpServers.gradio,
|
|
83
|
+
url: mcp_server_url_streamable
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
: null,
|
|
88
|
+
include_file_upload
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
$: mcp_json_sse_updated = update_config_with_file_upload(
|
|
92
|
+
mcp_json_sse,
|
|
93
|
+
include_file_upload
|
|
94
|
+
);
|
|
95
|
+
$: mcp_json_stdio_updated = update_config_with_file_upload(
|
|
96
|
+
mcp_json_stdio,
|
|
97
|
+
include_file_upload
|
|
98
|
+
);
|
|
99
|
+
</script>
|
|
100
|
+
|
|
101
|
+
{#if mcp_server_active}
|
|
102
|
+
<div class="transport-selection">
|
|
103
|
+
<div class="snippets">
|
|
104
|
+
<span class="transport-label">Transport:</span>
|
|
105
|
+
{#each transports as [transport, display_name]}
|
|
106
|
+
<button
|
|
107
|
+
type="button"
|
|
108
|
+
class="snippet {current_transport === transport
|
|
109
|
+
? 'current-lang'
|
|
110
|
+
: 'inactive-lang'}"
|
|
111
|
+
on:click={() => (current_transport = transport)}
|
|
112
|
+
>
|
|
113
|
+
{display_name}
|
|
114
|
+
</button>
|
|
115
|
+
{/each}
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
|
|
119
|
+
{#if current_transport !== "stdio"}
|
|
120
|
+
<Block>
|
|
121
|
+
<div class="mcp-url">
|
|
122
|
+
<label for="mcp-server-url"
|
|
123
|
+
><span class="status-indicator active">●</span>MCP Server URL ({current_transport ===
|
|
124
|
+
"sse"
|
|
125
|
+
? "SSE"
|
|
126
|
+
: "Streamable HTTP"})</label
|
|
127
|
+
>
|
|
128
|
+
<div class="textbox">
|
|
129
|
+
<input id="mcp-server-url" type="text" readonly value={display_url} />
|
|
130
|
+
<CopyButton code={display_url} />
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
</Block>
|
|
134
|
+
<p> </p>
|
|
135
|
+
{/if}
|
|
136
|
+
|
|
137
|
+
<div class="tool-selection">
|
|
138
|
+
<strong
|
|
139
|
+
>{all_tools.length > 0 ? all_tools.length : tools.length} Available MCP Tools</strong
|
|
140
|
+
>
|
|
141
|
+
{#if all_tools.length > 0}
|
|
142
|
+
<div class="tool-selection-controls">
|
|
143
|
+
<button
|
|
144
|
+
class="select-all-btn"
|
|
145
|
+
on:click={() => {
|
|
146
|
+
selected_tools = new Set(all_tools.map((t) => t.name));
|
|
147
|
+
}}
|
|
148
|
+
>
|
|
149
|
+
Select All
|
|
150
|
+
</button>
|
|
151
|
+
<button
|
|
152
|
+
class="select-none-btn"
|
|
153
|
+
on:click={() => {
|
|
154
|
+
selected_tools = new Set();
|
|
155
|
+
}}
|
|
156
|
+
>
|
|
157
|
+
Select None
|
|
158
|
+
</button>
|
|
159
|
+
</div>
|
|
160
|
+
{/if}
|
|
161
|
+
</div>
|
|
162
|
+
<div class="mcp-tools">
|
|
163
|
+
{#each all_tools.length > 0 ? all_tools : tools as tool}
|
|
164
|
+
<div class="tool-item">
|
|
165
|
+
<div class="tool-header-wrapper">
|
|
166
|
+
{#if all_tools.length > 0}
|
|
167
|
+
<input
|
|
168
|
+
type="checkbox"
|
|
169
|
+
class="tool-checkbox"
|
|
170
|
+
checked={selected_tools.has(tool.name) ||
|
|
171
|
+
current_transport !== "streamable_http"}
|
|
172
|
+
disabled={current_transport !== "streamable_http"}
|
|
173
|
+
style={current_transport !== "streamable_http"
|
|
174
|
+
? "opacity: 0.5; cursor: not-allowed;"
|
|
175
|
+
: ""}
|
|
176
|
+
on:change={(e) => {
|
|
177
|
+
if (e.currentTarget.checked) {
|
|
178
|
+
selected_tools.add(tool.name);
|
|
179
|
+
} else {
|
|
180
|
+
selected_tools.delete(tool.name);
|
|
181
|
+
}
|
|
182
|
+
selected_tools = selected_tools;
|
|
183
|
+
}}
|
|
184
|
+
/>
|
|
185
|
+
{/if}
|
|
186
|
+
<button
|
|
187
|
+
class="tool-header"
|
|
188
|
+
on:click={() => (tool.expanded = !tool.expanded)}
|
|
189
|
+
>
|
|
190
|
+
<span
|
|
191
|
+
><span class="tool-name">{tool.name}</span>
|
|
192
|
+
<span class="tool-description"
|
|
193
|
+
>{tool.description
|
|
194
|
+
? tool.description
|
|
195
|
+
: "⚠︎ No description provided in function docstring"}</span
|
|
196
|
+
></span
|
|
197
|
+
>
|
|
198
|
+
<span class="tool-arrow">{tool.expanded ? "▼" : "▶"}</span>
|
|
199
|
+
</button>
|
|
200
|
+
</div>
|
|
201
|
+
{#if tool.expanded}
|
|
202
|
+
<div class="tool-content">
|
|
203
|
+
{#if Object.keys(tool.parameters).length > 0}
|
|
204
|
+
<div class="tool-parameters">
|
|
205
|
+
{#each Object.entries(tool.parameters) as [name, param]}
|
|
206
|
+
<div class="parameter">
|
|
207
|
+
<code>{name}</code>
|
|
208
|
+
<span class="parameter-type">
|
|
209
|
+
({param.type}{param.default !== undefined
|
|
210
|
+
? `, default: ${JSON.stringify(param.default)}`
|
|
211
|
+
: ""})
|
|
212
|
+
</span>
|
|
213
|
+
<p class="parameter-description">
|
|
214
|
+
{param.description
|
|
215
|
+
? param.description
|
|
216
|
+
: "⚠︎ No description for this parameter in function docstring"}
|
|
217
|
+
</p>
|
|
218
|
+
</div>
|
|
219
|
+
{/each}
|
|
220
|
+
</div>
|
|
221
|
+
{:else}
|
|
222
|
+
<p>Takes no input parameters</p>
|
|
223
|
+
{/if}
|
|
224
|
+
</div>
|
|
225
|
+
{/if}
|
|
226
|
+
</div>
|
|
227
|
+
{/each}
|
|
228
|
+
</div>
|
|
229
|
+
<p> </p>
|
|
230
|
+
|
|
231
|
+
{#if current_transport === "streamable_http"}
|
|
232
|
+
<strong>Streamable HTTP Transport</strong>: To add this MCP to clients that
|
|
233
|
+
support Streamable HTTP, simply add the following configuration to your MCP
|
|
234
|
+
config.
|
|
235
|
+
<p> </p>
|
|
236
|
+
<Block>
|
|
237
|
+
<code>
|
|
238
|
+
<div class="copy">
|
|
239
|
+
<CopyButton
|
|
240
|
+
code={JSON.stringify(mcp_json_streamable_http, null, 2)}
|
|
241
|
+
/>
|
|
242
|
+
</div>
|
|
243
|
+
<div>
|
|
244
|
+
<pre>{JSON.stringify(mcp_json_streamable_http, null, 2)}</pre>
|
|
245
|
+
</div>
|
|
246
|
+
</code>
|
|
247
|
+
</Block>
|
|
248
|
+
{:else if current_transport === "sse"}
|
|
249
|
+
<strong>SSE Transport</strong>: The SSE transport has been deprecated by the
|
|
250
|
+
MCP spec. We recommend using the Streamable HTTP transport instead. But to
|
|
251
|
+
add this MCP to clients that only support server-sent events (SSE), simply
|
|
252
|
+
add the following configuration to your MCP config.
|
|
253
|
+
<p> </p>
|
|
254
|
+
<Block>
|
|
255
|
+
<code>
|
|
256
|
+
<div class="copy">
|
|
257
|
+
<CopyButton code={JSON.stringify(mcp_json_sse_updated, null, 2)} />
|
|
258
|
+
</div>
|
|
259
|
+
<div>
|
|
260
|
+
<pre>{JSON.stringify(mcp_json_sse_updated, null, 2)}</pre>
|
|
261
|
+
</div>
|
|
262
|
+
</code>
|
|
263
|
+
</Block>
|
|
264
|
+
{:else if current_transport === "stdio"}
|
|
265
|
+
<strong>STDIO Transport</strong>: For clients that only support stdio (e.g.
|
|
266
|
+
Claude Desktop), first
|
|
267
|
+
<a href="https://nodejs.org/en/download/" target="_blank">install Node.js</a
|
|
268
|
+
>. Then, you can use the following command:
|
|
269
|
+
<p> </p>
|
|
270
|
+
<Block>
|
|
271
|
+
<code>
|
|
272
|
+
<div class="copy">
|
|
273
|
+
<CopyButton code={JSON.stringify(mcp_json_stdio_updated, null, 2)} />
|
|
274
|
+
</div>
|
|
275
|
+
<div>
|
|
276
|
+
<pre>{JSON.stringify(mcp_json_stdio_updated, null, 2)}</pre>
|
|
277
|
+
</div>
|
|
278
|
+
</code>
|
|
279
|
+
</Block>
|
|
280
|
+
{/if}
|
|
281
|
+
{#if file_data_present}
|
|
282
|
+
<div class="file-upload-section">
|
|
283
|
+
<label class="checkbox-label">
|
|
284
|
+
<input
|
|
285
|
+
type="checkbox"
|
|
286
|
+
bind:checked={include_file_upload}
|
|
287
|
+
class="checkbox"
|
|
288
|
+
/>
|
|
289
|
+
Include Gradio file upload tool
|
|
290
|
+
</label>
|
|
291
|
+
<p class="file-upload-explanation">
|
|
292
|
+
The <code>upload_files_to_gradio</code> tool uploads files from your
|
|
293
|
+
local <code>UPLOAD_DIRECTORY</code> (or any of its subdirectories) to
|
|
294
|
+
the Gradio app. This is needed because MCP servers require files to be
|
|
295
|
+
provided as URLs. You can omit this tool if you prefer to upload files
|
|
296
|
+
manually. This tool requires
|
|
297
|
+
<a
|
|
298
|
+
href="https://docs.astral.sh/uv/getting-started/installation/"
|
|
299
|
+
target="_blank">uv</a
|
|
300
|
+
> to be installed.
|
|
301
|
+
</p>
|
|
302
|
+
</div>
|
|
303
|
+
{/if}
|
|
304
|
+
|
|
305
|
+
<p> </p>
|
|
306
|
+
<p>
|
|
307
|
+
<a href={mcp_docs} target="_blank">
|
|
308
|
+
Read more about MCP in the Gradio docs
|
|
309
|
+
</a>
|
|
310
|
+
</p>
|
|
311
|
+
{:else}
|
|
312
|
+
This Gradio app can also serve as an MCP server, with an MCP tool
|
|
313
|
+
corresponding to each API endpoint. To enable this, launch this Gradio app
|
|
314
|
+
with <code>.launch(mcp_server=True)</code> or set the
|
|
315
|
+
<code>GRADIO_MCP_SERVER</code>
|
|
316
|
+
env variable to
|
|
317
|
+
<code>"True"</code>.
|
|
318
|
+
{/if}
|
|
319
|
+
|
|
320
|
+
<style>
|
|
321
|
+
.transport-selection {
|
|
322
|
+
margin-bottom: var(--size-4);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.snippets {
|
|
326
|
+
display: flex;
|
|
327
|
+
align-items: center;
|
|
328
|
+
margin-bottom: var(--size-4);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.snippets > * + * {
|
|
332
|
+
margin-left: var(--size-2);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.transport-label {
|
|
336
|
+
font-weight: 600;
|
|
337
|
+
color: var(--body-text-color);
|
|
338
|
+
margin-right: var(--size-2);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.file-upload-section {
|
|
342
|
+
margin-top: var(--size-4);
|
|
343
|
+
padding: var(--size-3);
|
|
344
|
+
border: 1px solid var(--border-color-primary);
|
|
345
|
+
border-radius: var(--radius-md);
|
|
346
|
+
background: var(--background-fill-secondary);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
.checkbox-label {
|
|
350
|
+
display: flex;
|
|
351
|
+
align-items: center;
|
|
352
|
+
font-weight: 600;
|
|
353
|
+
color: var(--body-text-color);
|
|
354
|
+
cursor: pointer;
|
|
355
|
+
margin-bottom: var(--size-2);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.checkbox {
|
|
359
|
+
margin-right: var(--size-2);
|
|
360
|
+
width: var(--size-4);
|
|
361
|
+
height: var(--size-4);
|
|
362
|
+
cursor: pointer;
|
|
363
|
+
accent-color: var(--color-accent);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
.checkbox:checked {
|
|
367
|
+
background-color: var(--color-accent);
|
|
368
|
+
border-color: var(--color-accent);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
.file-upload-explanation {
|
|
372
|
+
margin: 0;
|
|
373
|
+
color: var(--body-text-color);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.snippet {
|
|
377
|
+
display: flex;
|
|
378
|
+
align-items: center;
|
|
379
|
+
border: 1px solid var(--border-color-primary);
|
|
380
|
+
border-radius: var(--radius-md);
|
|
381
|
+
padding: var(--size-1) var(--size-1-5);
|
|
382
|
+
color: var(--body-text-color-subdued);
|
|
383
|
+
color: var(--body-text-color);
|
|
384
|
+
line-height: 1;
|
|
385
|
+
user-select: none;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.current-lang {
|
|
389
|
+
border: 1px solid var(--body-text-color-subdued);
|
|
390
|
+
color: var(--body-text-color);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
.inactive-lang {
|
|
394
|
+
cursor: pointer;
|
|
395
|
+
color: var(--body-text-color-subdued);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
.inactive-lang:hover,
|
|
399
|
+
.inactive-lang:focus {
|
|
400
|
+
box-shadow: var(--shadow-drop);
|
|
401
|
+
color: var(--body-text-color);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
code pre {
|
|
405
|
+
overflow-x: auto;
|
|
406
|
+
color: var(--body-text-color);
|
|
407
|
+
font-family: var(--font-mono);
|
|
408
|
+
tab-size: 2;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
.copy {
|
|
412
|
+
position: absolute;
|
|
413
|
+
top: 0;
|
|
414
|
+
right: 0;
|
|
415
|
+
margin-top: 5px;
|
|
416
|
+
margin-right: 5px;
|
|
417
|
+
z-index: 10;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
.mcp-url {
|
|
421
|
+
padding: var(--size-2);
|
|
422
|
+
position: relative;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
.mcp-url label {
|
|
426
|
+
display: block;
|
|
427
|
+
margin-bottom: var(--size-2);
|
|
428
|
+
font-weight: 600;
|
|
429
|
+
color: var(--body-text-color);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
.mcp-url .textbox {
|
|
433
|
+
display: flex;
|
|
434
|
+
align-items: center;
|
|
435
|
+
gap: var(--size-2);
|
|
436
|
+
border: 1px solid var(--border-color-primary);
|
|
437
|
+
border-radius: var(--radius-sm);
|
|
438
|
+
padding: var(--size-2);
|
|
439
|
+
background: var(--background-fill-primary);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
.mcp-url input {
|
|
443
|
+
flex: 1;
|
|
444
|
+
border: none;
|
|
445
|
+
background: none;
|
|
446
|
+
color: var(--body-text-color);
|
|
447
|
+
font-family: var(--font-mono);
|
|
448
|
+
font-size: var(--text-md);
|
|
449
|
+
width: 100%;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
.mcp-url input:focus {
|
|
453
|
+
outline: none;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
.status-indicator {
|
|
457
|
+
display: inline-block;
|
|
458
|
+
margin-right: var(--size-1-5);
|
|
459
|
+
position: relative;
|
|
460
|
+
top: -1px;
|
|
461
|
+
font-size: 0.8em;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
.status-indicator.active {
|
|
465
|
+
color: #4caf50;
|
|
466
|
+
animation: pulse 1s infinite;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
@keyframes pulse {
|
|
470
|
+
0% {
|
|
471
|
+
opacity: 1;
|
|
472
|
+
}
|
|
473
|
+
50% {
|
|
474
|
+
opacity: 0.6;
|
|
475
|
+
}
|
|
476
|
+
100% {
|
|
477
|
+
opacity: 1;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
.mcp-tools {
|
|
482
|
+
margin-top: var(--size-4);
|
|
483
|
+
border: 1px solid var(--border-color-primary);
|
|
484
|
+
border-radius: var(--radius-md);
|
|
485
|
+
overflow: hidden;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
.tool-selection {
|
|
489
|
+
display: flex;
|
|
490
|
+
justify-content: space-between;
|
|
491
|
+
align-items: center;
|
|
492
|
+
margin-bottom: var(--size-2);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
.tool-selection-controls {
|
|
496
|
+
display: flex;
|
|
497
|
+
gap: var(--size-2);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
.select-all-btn,
|
|
501
|
+
.select-none-btn {
|
|
502
|
+
padding: var(--size-1) var(--size-2);
|
|
503
|
+
border: 1px solid var(--border-color-primary);
|
|
504
|
+
border-radius: var(--radius-sm);
|
|
505
|
+
background: var(--background-fill-primary);
|
|
506
|
+
color: var(--body-text-color);
|
|
507
|
+
cursor: pointer;
|
|
508
|
+
font-size: var(--text-sm);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
.select-all-btn:hover,
|
|
512
|
+
.select-none-btn:hover {
|
|
513
|
+
background: var(--background-fill-secondary);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
.tool-item {
|
|
517
|
+
border-bottom: 1px solid var(--border-color-primary);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
.tool-item:last-child {
|
|
521
|
+
border-bottom: none;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
.tool-header-wrapper {
|
|
525
|
+
display: flex;
|
|
526
|
+
align-items: center;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
.tool-checkbox {
|
|
530
|
+
margin-left: var(--size-3);
|
|
531
|
+
margin-right: var(--size-2);
|
|
532
|
+
width: var(--size-4);
|
|
533
|
+
height: var(--size-4);
|
|
534
|
+
cursor: pointer;
|
|
535
|
+
accent-color: var(--color-accent);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
.tool-checkbox:checked {
|
|
539
|
+
background-color: var(--color-accent);
|
|
540
|
+
border-color: var(--color-accent);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
.tool-header {
|
|
544
|
+
flex: 1;
|
|
545
|
+
display: flex;
|
|
546
|
+
justify-content: space-between;
|
|
547
|
+
align-items: center;
|
|
548
|
+
padding: var(--size-3);
|
|
549
|
+
background: var(--background-fill-primary);
|
|
550
|
+
border: none;
|
|
551
|
+
cursor: pointer;
|
|
552
|
+
text-align: left;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
.tool-header:hover {
|
|
556
|
+
background: var(--background-fill-secondary);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
.tool-name {
|
|
560
|
+
font-family: var(--font-mono);
|
|
561
|
+
font-weight: 600;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
.tool-arrow {
|
|
565
|
+
color: var(--body-text-color-subdued);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
.tool-content {
|
|
569
|
+
padding: var(--size-3);
|
|
570
|
+
background: var(--background-fill-secondary);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
.tool-description {
|
|
574
|
+
margin-bottom: var(--size-3);
|
|
575
|
+
color: var(--body-text-color);
|
|
576
|
+
}
|
|
577
|
+
.parameter {
|
|
578
|
+
margin-bottom: var(--size-2);
|
|
579
|
+
padding: var(--size-2);
|
|
580
|
+
background: var(--background-fill-primary);
|
|
581
|
+
border-radius: var(--radius-sm);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
.parameter code {
|
|
585
|
+
font-weight: 600;
|
|
586
|
+
color: var(--color-accent);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
.parameter-type {
|
|
590
|
+
color: var(--body-text-color-subdued);
|
|
591
|
+
margin-left: var(--size-1);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
.parameter-description {
|
|
595
|
+
margin-top: var(--size-1);
|
|
596
|
+
color: var(--body-text-color);
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
a {
|
|
600
|
+
text-decoration: underline;
|
|
601
|
+
}
|
|
602
|
+
</style>
|