@gradio/core 0.27.0 → 0.27.2

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.
Files changed (42) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/src/Blocks.svelte +12 -21
  3. package/dist/src/Blocks.svelte.d.ts +11 -9
  4. package/dist/src/Embed.svelte.d.ts +4 -2
  5. package/dist/src/Login.svelte.d.ts +2 -0
  6. package/dist/src/MountComponents.svelte.d.ts +3 -1
  7. package/dist/src/Render.svelte +12 -13
  8. package/dist/src/Render.svelte.d.ts +3 -1
  9. package/dist/src/RenderComponent.svelte +3 -6
  10. package/dist/src/RenderComponent.svelte.d.ts +2 -0
  11. package/dist/src/api_docs/ApiBanner.svelte.d.ts +3 -1
  12. package/dist/src/api_docs/ApiDocs.svelte +28 -18
  13. package/dist/src/api_docs/ApiDocs.svelte.d.ts +3 -1
  14. package/dist/src/api_docs/ApiRecorder.svelte.d.ts +3 -1
  15. package/dist/src/api_docs/CodeSnippet.svelte +40 -40
  16. package/dist/src/api_docs/CodeSnippet.svelte.d.ts +4 -1
  17. package/dist/src/api_docs/CopyButton.svelte.d.ts +2 -0
  18. package/dist/src/api_docs/EndpointDetail.svelte +23 -1
  19. package/dist/src/api_docs/EndpointDetail.svelte.d.ts +5 -2
  20. package/dist/src/api_docs/InputPayload.svelte.d.ts +2 -0
  21. package/dist/src/api_docs/InstallSnippet.svelte.d.ts +2 -0
  22. package/dist/src/api_docs/MCPSnippet.svelte +89 -44
  23. package/dist/src/api_docs/MCPSnippet.svelte.d.ts +7 -2
  24. package/dist/src/api_docs/NoApi.svelte.d.ts +2 -0
  25. package/dist/src/api_docs/ParametersSnippet.svelte.d.ts +2 -0
  26. package/dist/src/api_docs/RecordingSnippet.svelte.d.ts +4 -2
  27. package/dist/src/api_docs/ResponseSnippet.svelte.d.ts +2 -0
  28. package/dist/src/api_docs/Settings.svelte.d.ts +4 -2
  29. package/dist/src/api_docs/SettingsBanner.svelte.d.ts +2 -0
  30. package/dist/src/api_docs/TryButton.svelte.d.ts +2 -0
  31. package/dist/src/api_docs/img/clear.svelte.d.ts +2 -0
  32. package/dist/src/api_docs/utils.d.ts +2 -0
  33. package/dist/src/api_docs/utils.js +14 -0
  34. package/dist/src/stories/I18nMultiLanguageTestComponent.svelte.d.ts +3 -3
  35. package/dist/src/stories/I18nTestSetup.svelte +1 -2
  36. package/dist/src/stories/I18nTestSetup.svelte.d.ts +3 -1
  37. package/package.json +31 -31
  38. package/src/api_docs/ApiDocs.svelte +24 -3
  39. package/src/api_docs/CodeSnippet.svelte +38 -36
  40. package/src/api_docs/EndpointDetail.svelte +24 -1
  41. package/src/api_docs/MCPSnippet.svelte +68 -17
  42. package/src/api_docs/utils.ts +14 -0
@@ -22,6 +22,7 @@
22
22
  export let username: string | null;
23
23
  export let current_language: "python" | "javascript" | "bash";
24
24
  export let api_description: string | null = null;
25
+ export let analytics: Record<string, any>;
25
26
 
26
27
  let python_code: HTMLElement;
27
28
  let js_code: HTMLElement;
@@ -44,6 +45,7 @@
44
45
  <EndpointDetail
45
46
  api_name={dependency.api_name}
46
47
  description={api_description}
48
+ {analytics}
47
49
  />
48
50
  {#if current_language === "python"}
49
51
  <Block>
@@ -56,13 +58,13 @@
56
58
  class="highlight">import</span
57
59
  > Client{#if has_file_path}, handle_file{/if}
58
60
 
59
- client = Client(<span class="token string">"{space_id || root}"</span
61
+ client = Client(<span class="token string">"{space_id || root}"</span
60
62
  >{#if username !== null}, auth=("{username}", **password**){/if})
61
- result = client.<span class="highlight">predict</span
63
+ result = client.<span class="highlight">predict</span
62
64
  >(<!--
63
- -->{#each endpoint_parameters as { python_type, example_input, parameter_name, parameter_has_default, parameter_default }, i}<!--
64
- -->
65
- {parameter_name
65
+ -->{#each endpoint_parameters as { python_type, example_input, parameter_name, parameter_has_default, parameter_default }, i}<!--
66
+ -->
67
+ {parameter_name
66
68
  ? parameter_name + "="
67
69
  : ""}<span
68
70
  >{represent_value(
@@ -72,11 +74,11 @@ result = client.<span class="highlight">predict</span
72
74
  )}</span
73
75
  >,{/each}<!--
74
76
 
75
- -->
76
- api_name=<span class="api-name">"/{dependency.api_name}"</span><!--
77
- -->
78
- )
79
- <span class="highlight">print</span>(result)</pre>
77
+ -->
78
+ api_name=<span class="api-name">"/{dependency.api_name}"</span><!--
79
+ -->
80
+ )
81
+ <span class="highlight">print</span>(result)</pre>
80
82
  </div>
81
83
  </code>
82
84
  </Block>
@@ -88,44 +90,44 @@ result = client.<span class="highlight">predict</span
88
90
  </div>
89
91
  <div bind:this={js_code}>
90
92
  <pre>import &lbrace; Client &rbrace; from "@gradio/client";
91
- {#each blob_examples as { component, example_input }, i}<!--
92
- -->
93
- const response_{i} = await fetch("{example_input.url}");
94
- const example{component} = await response_{i}.blob();
93
+ {#each blob_examples as { component, example_input }, i}<!--
94
+ -->
95
+ const response_{i} = await fetch("{example_input.url}");
96
+ const example{component} = await response_{i}.blob();
95
97
  {/each}<!--
96
- -->
97
- const client = await Client.connect(<span class="token string"
98
+ -->
99
+ const client = await Client.connect(<span class="token string"
98
100
  >"{space_id || root}"</span
99
101
  >{#if username !== null}, &lbrace;auth: ["{username}", **password**]&rbrace;{/if});
100
- const result = await client.predict(<span class="api-name"
102
+ const result = await client.predict(<span class="api-name"
101
103
  >"/{dependency.api_name}"</span
102
104
  >, &lbrace; <!--
103
- -->{#each endpoint_parameters as { label, parameter_name, type, python_type, component, example_input, serializer }, i}<!--
104
- -->{#if blob_components.includes(component)}<!--
105
- -->
106
- <span
105
+ -->{#each endpoint_parameters as { label, parameter_name, type, python_type, component, example_input, serializer }, i}<!--
106
+ -->{#if blob_components.includes(component)}<!--
107
+ -->
108
+ <span
107
109
  class="example-inputs"
108
110
  >{parameter_name}: example{component}</span
109
111
  >, <!--
110
- --><span class="desc"><!--
111
- --></span
112
+ --><span class="desc"><!--
113
+ --></span
112
114
  ><!--
113
- -->{:else}<!--
114
- -->
115
- <span class="example-inputs"
115
+ -->{:else}<!--
116
+ -->
117
+ <span class="example-inputs"
116
118
  >{parameter_name}: {represent_value(
117
119
  example_input,
118
120
  python_type.type,
119
121
  "js"
120
122
  )}</span
121
123
  >, <!--
122
- --><!--
123
- -->{/if}
124
+ --><!--
125
+ -->{/if}
124
126
  {/each}
125
- &rbrace;);
127
+ &rbrace;);
126
128
 
127
- console.log(result.data);
128
- </pre>
129
+ console.log(result.data);
130
+ </pre>
129
131
  </div>
130
132
  </code>
131
133
  </Block>
@@ -138,18 +140,18 @@ console.log(result.data);
138
140
 
139
141
  <div bind:this={bash_post_code}>
140
142
  <pre>curl -X POST {normalised_root}{normalised_api_prefix}/call/{dependency.api_name} -s -H "Content-Type: application/json" -d '{"{"}
141
- "data": [{#each endpoint_parameters as { label, parameter_name, type, python_type, component, example_input, serializer }, i}
143
+ "data": [{#each endpoint_parameters as { label, parameter_name, type, python_type, component, example_input, serializer }, i}
142
144
  <!--
143
- -->{represent_value(
145
+ -->{represent_value(
144
146
  example_input,
145
147
  python_type.type,
146
148
  "bash"
147
149
  )}{#if i < endpoint_parameters.length - 1},
148
150
  {/if}
149
151
  {/each}
150
- ]{"}"}' \
151
- | awk -F'"' '{"{"} print $4{"}"}' \
152
- | read EVENT_ID; curl -N {normalised_root}{normalised_api_prefix}/call/{dependency.api_name}/$EVENT_ID</pre>
152
+ ]{"}"}' \
153
+ | awk -F'"' '{"{"} print $4{"}"}' \
154
+ | read EVENT_ID; curl -N {normalised_root}{normalised_api_prefix}/call/{dependency.api_name}/$EVENT_ID</pre>
153
155
  </div>
154
156
  </code>
155
157
  </Block>
@@ -1,12 +1,30 @@
1
1
  <script lang="ts">
2
2
  export let api_name: string | null = null;
3
3
  export let description: string | null = null;
4
+ export let analytics: Record<string, any>;
5
+ import { format_latency, get_color_from_success_rate } from "./utils";
6
+
7
+ const success_rate = api_name ? analytics[api_name]?.success_rate : 0;
8
+ const color = get_color_from_success_rate(success_rate);
4
9
  </script>
5
10
 
6
11
  <h3>
7
12
  API name:
8
13
  <span class="post">{"/" + api_name}</span>
9
14
  <span class="desc">{description}</span>
15
+ {#if analytics && api_name && analytics[api_name]}
16
+ <span class="analytics">
17
+ Total requests: {analytics[api_name].total_requests} (<span style={color}
18
+ >{Math.round(success_rate * 100)}%</span
19
+ >
20
+ successful) &nbsp;|&nbsp; p50/p90/p99:
21
+ {format_latency(analytics[api_name].process_time_percentiles["50th"])}
22
+ /
23
+ {format_latency(analytics[api_name].process_time_percentiles["90th"])}
24
+ /
25
+ {format_latency(analytics[api_name].process_time_percentiles["99th"])}
26
+ </span>
27
+ {/if}
10
28
  </h3>
11
29
 
12
30
  <style>
@@ -28,8 +46,13 @@
28
46
  font-weight: var(--weight-semibold);
29
47
  }
30
48
 
31
- .desc {
49
+ .analytics {
32
50
  color: var(--body-text-color-subdued);
51
+ margin-top: var(--size-1);
52
+ }
53
+
54
+ .desc {
55
+ color: var(--body-text-color);
33
56
  font-size: var(--text-lg);
34
57
  margin-top: var(--size-1);
35
58
  }
@@ -1,6 +1,8 @@
1
1
  <script lang="ts">
2
2
  import { Block } from "@gradio/atoms";
3
3
  import CopyButton from "./CopyButton.svelte";
4
+ import { Tool, Prompt, Resource } from "@gradio/icons";
5
+ import { format_latency, get_color_from_success_rate } from "./utils";
4
6
 
5
7
  export let mcp_server_active: boolean;
6
8
  export let mcp_server_url: string;
@@ -12,6 +14,7 @@
12
14
  export let mcp_json_stdio: any;
13
15
  export let file_data_present: boolean;
14
16
  export let mcp_docs: string;
17
+ export let analytics: Record<string, any>;
15
18
 
16
19
  interface ToolParameter {
17
20
  title?: string;
@@ -29,6 +32,7 @@
29
32
  meta: {
30
33
  mcp_type: "tool" | "resource" | "prompt";
31
34
  file_data_present: boolean;
35
+ endpoint_name: string;
32
36
  };
33
37
  }
34
38
 
@@ -42,10 +46,10 @@
42
46
  ["stdio", "STDIO"]
43
47
  ] as const;
44
48
 
45
- const tool_type_emojis = {
46
- tool: "🔧",
47
- resource: "📕",
48
- prompt: "💬"
49
+ const tool_type_icons: Record<Tool["meta"]["mcp_type"], typeof Tool> = {
50
+ tool: Tool,
51
+ resource: Resource,
52
+ prompt: Prompt
49
53
  };
50
54
 
51
55
  $: display_url =
@@ -145,11 +149,15 @@
145
149
  {/if}
146
150
 
147
151
  <div class="tool-selection">
148
- <strong
149
- >{all_tools.length > 0 ? all_tools.length : tools.length} Available MCP Tools
150
- ({tool_type_emojis.tool}), Resources ({tool_type_emojis.resource}), and
151
- Prompts ({tool_type_emojis.prompt})</strong
152
- >
152
+ <strong>
153
+ {all_tools.length > 0 ? all_tools.length : tools.length} Available MCP Tools
154
+ (<span style="display: inline-block; vertical-align: sub;"><Tool /></span
155
+ >), Resources (<span style="display: inline-block; vertical-align: sub;"
156
+ ><Resource /></span
157
+ >), and Prompts (<span style="display: inline-block; vertical-align: sub;"
158
+ ><Prompt /></span
159
+ >)
160
+ </strong>
153
161
  {#if all_tools.length > 0}
154
162
  <div class="tool-selection-controls">
155
163
  <button
@@ -173,6 +181,9 @@
173
181
  </div>
174
182
  <div class="mcp-tools">
175
183
  {#each all_tools.length > 0 ? all_tools : tools as tool}
184
+ {@const success_rate =
185
+ analytics[tool.meta.endpoint_name]?.success_rate || 0}
186
+ {@const color = get_color_from_success_rate(success_rate)}
176
187
  <div class="tool-item">
177
188
  <div class="tool-header-wrapper">
178
189
  {#if all_tools.length > 0}
@@ -199,17 +210,53 @@
199
210
  class="tool-header"
200
211
  on:click={() => (tool.expanded = !tool.expanded)}
201
212
  >
202
- <span
203
- ><span class="tool-name"
204
- >{tool_type_emojis[tool.meta.mcp_type]} {tool.name}</span
213
+ <span style="display: inline-block">
214
+ <span
215
+ style="display: inline-block; padding-right: 6px; vertical-align: sub"
205
216
  >
217
+ {#if tool_type_icons[tool.meta.mcp_type]}
218
+ {@const Icon = tool_type_icons[tool.meta.mcp_type]}
219
+ <Icon />
220
+ {/if}
221
+ </span>
222
+ <span class="tool-name">{tool.name}</span>
206
223
  &nbsp;
207
- <span class="tool-description"
208
- >{tool.description
224
+ <span class="tool-description">
225
+ {tool.description
209
226
  ? tool.description
210
- : "⚠︎ No description provided in function docstring"}</span
211
- ></span
212
- >
227
+ : "⚠︎ No description provided in function docstring"}
228
+ </span>
229
+ {#if analytics[tool.meta.endpoint_name]}
230
+ <span
231
+ class="tool-analytics"
232
+ style="color: var(--body-text-color-subdued); margin-left: 1em;"
233
+ >
234
+ Total requests: {analytics[tool.meta.endpoint_name]
235
+ .total_requests}
236
+ <span style={color}
237
+ >({Math.round(success_rate * 100)}% successful)</span
238
+ >
239
+ &nbsp;|&nbsp; p50/p90/p99:
240
+ {format_latency(
241
+ analytics[tool.meta.endpoint_name].process_time_percentiles[
242
+ "50th"
243
+ ]
244
+ )}
245
+ /
246
+ {format_latency(
247
+ analytics[tool.meta.endpoint_name].process_time_percentiles[
248
+ "90th"
249
+ ]
250
+ )}
251
+ /
252
+ {format_latency(
253
+ analytics[tool.meta.endpoint_name].process_time_percentiles[
254
+ "99th"
255
+ ]
256
+ )}
257
+ </span>
258
+ {/if}
259
+ </span>
213
260
  <span class="tool-arrow">{tool.expanded ? "▼" : "▶"}</span>
214
261
  </button>
215
262
  </div>
@@ -333,6 +380,10 @@
333
380
  {/if}
334
381
 
335
382
  <style>
383
+ .tool-analytics {
384
+ font-size: 0.95em;
385
+ color: var(--body-text-color-subdued);
386
+ }
336
387
  .transport-selection {
337
388
  margin-bottom: var(--size-4);
338
389
  }
@@ -141,3 +141,17 @@ function stringify_except_file_function(obj: any): string {
141
141
  const regexNone = /"UNQUOTEDNone"/g;
142
142
  return jsonString.replace(regexNone, "None");
143
143
  }
144
+
145
+ export function format_latency(val: number): string {
146
+ if (val < 1) return `${Math.round(val * 1000)} ms`;
147
+ return `${val.toFixed(2)} s`;
148
+ }
149
+
150
+ export function get_color_from_success_rate(success_rate: number): string {
151
+ if (success_rate > 0.9) {
152
+ return "color: green;";
153
+ } else if (success_rate > 0.1) {
154
+ return "color: orange;";
155
+ }
156
+ return "color: red;";
157
+ }