@gradio/core 1.1.3 → 1.3.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.
Files changed (52) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/dist/src/Blocks.svelte +33 -2
  3. package/dist/src/_init.js +2 -2
  4. package/dist/src/api_docs/ApiBanner.svelte +6 -2
  5. package/dist/src/api_docs/ApiBanner.svelte.d.ts +1 -1
  6. package/dist/src/api_docs/ApiDocs.svelte +41 -25
  7. package/dist/src/api_docs/CodeSnippet.svelte +67 -170
  8. package/dist/src/api_docs/CodeSnippet.svelte.d.ts +2 -6
  9. package/dist/src/api_docs/CopyMarkdown.svelte +7 -2
  10. package/dist/src/api_docs/CopyMarkdown.svelte.d.ts +1 -1
  11. package/dist/src/api_docs/InstallSnippet.svelte +6 -1
  12. package/dist/src/api_docs/InstallSnippet.svelte.d.ts +1 -1
  13. package/dist/src/api_docs/ParametersSnippet.svelte +6 -1
  14. package/dist/src/api_docs/ParametersSnippet.svelte.d.ts +1 -1
  15. package/dist/src/api_docs/RecordingSnippet.svelte +6 -1
  16. package/dist/src/api_docs/RecordingSnippet.svelte.d.ts +1 -1
  17. package/dist/src/api_docs/ResponseSnippet.svelte +6 -1
  18. package/dist/src/api_docs/ResponseSnippet.svelte.d.ts +1 -1
  19. package/dist/src/api_docs/Settings.svelte +2 -7
  20. package/dist/src/api_docs/SettingsBanner.svelte +0 -3
  21. package/dist/src/api_docs/SkillSnippet.svelte +125 -0
  22. package/dist/src/api_docs/SkillSnippet.svelte.d.ts +20 -0
  23. package/dist/src/api_docs/img/skill.svg +10 -0
  24. package/dist/src/api_docs/utils.d.ts +0 -1
  25. package/dist/src/api_docs/utils.js +0 -22
  26. package/dist/src/dependency.d.ts +3 -1
  27. package/dist/src/dependency.js +39 -1
  28. package/dist/src/gradio_helper.js +5 -13
  29. package/dist/src/i18n.d.ts +1 -3
  30. package/dist/src/i18n.js +6 -53
  31. package/dist/src/init.svelte.js +81 -82
  32. package/package.json +49 -49
  33. package/src/Blocks.svelte +33 -2
  34. package/src/_init.ts +2 -2
  35. package/src/api_docs/ApiBanner.svelte +6 -2
  36. package/src/api_docs/ApiDocs.svelte +41 -25
  37. package/src/api_docs/CodeSnippet.svelte +67 -170
  38. package/src/api_docs/CopyMarkdown.svelte +7 -2
  39. package/src/api_docs/InstallSnippet.svelte +6 -1
  40. package/src/api_docs/ParametersSnippet.svelte +6 -1
  41. package/src/api_docs/RecordingSnippet.svelte +6 -1
  42. package/src/api_docs/ResponseSnippet.svelte +6 -1
  43. package/src/api_docs/Settings.svelte +2 -7
  44. package/src/api_docs/SettingsBanner.svelte +0 -3
  45. package/src/api_docs/SkillSnippet.svelte +125 -0
  46. package/src/api_docs/img/skill.svg +10 -0
  47. package/src/api_docs/utils.ts +0 -25
  48. package/src/dependency.ts +39 -1
  49. package/src/gradio_helper.ts +5 -17
  50. package/src/i18n.test.ts +41 -9
  51. package/src/i18n.ts +9 -62
  52. package/src/init.svelte.ts +95 -99
@@ -1,5 +1,4 @@
1
1
  import { determine_interactivity, get_component, get_inputs_outputs } from "./init_utils";
2
- import { translate_if_needed } from "./i18n";
3
2
  import { tick } from "svelte";
4
3
  import { dequal } from "dequal";
5
4
  import {} from "@gradio/utils";
@@ -32,6 +31,7 @@ export class AppTree {
32
31
  #pending_components = [];
33
32
  #get_callbacks = new Map();
34
33
  #set_callbacks = new Map();
34
+ #pending_updates = new Map();
35
35
  #event_dispatcher;
36
36
  component_ids;
37
37
  initial_tabs = {};
@@ -111,6 +111,20 @@ export class AppTree {
111
111
  this.#set_callbacks.set(id, _set_data);
112
112
  this.#get_callbacks.set(id, _get_data);
113
113
  this.components_to_register.delete(id);
114
+ // Apply any pending updates that were stored while the component
115
+ // was not yet mounted (e.g. hidden in an inactive tab).
116
+ // We must apply AFTER tick() so that the Gradio class's $effect
117
+ // (which syncs from node props) has already run. Otherwise the
118
+ // $effect would overwrite the values we set here.
119
+ const pending = this.#pending_updates.get(id);
120
+ if (pending) {
121
+ this.#pending_updates.delete(id);
122
+ tick().then(() => {
123
+ const _set = this.#set_callbacks.get(id);
124
+ if (_set)
125
+ _set(pending);
126
+ });
127
+ }
114
128
  if (this.components_to_register.size === 0 && !this.resolved) {
115
129
  this.resolved = true;
116
130
  this.ready_resolve();
@@ -130,8 +144,6 @@ export class AppTree {
130
144
  this.root = this.traverse(tree, [
131
145
  (node) => handle_visibility(node, this.#config.api_url),
132
146
  (node) => untrack_children_of_invisible_parents(node, this.components_to_register),
133
- (node) => handle_empty_forms(node, this.components_to_register),
134
- (node) => translate_props(node),
135
147
  (node) => apply_initial_tabs(node, this.initial_tabs),
136
148
  (node) => this.find_attached_events(node, this.#dependency_payload),
137
149
  (node) => untrack_children_of_closed_accordions_or_inactive_tabs(node, this.components_to_register, this.#hidden_on_startup)
@@ -269,7 +281,6 @@ export class AppTree {
269
281
  //@ts-ignore
270
282
  (n) => set_visibility_for_updated_node(n, id, new_state.visible),
271
283
  //@ts-ignore
272
- (n) => update_parent_visibility(n, id, new_state.visible),
273
284
  (n) => handle_visibility(n, this.#config.api_url)
274
285
  ]);
275
286
  await tick();
@@ -280,11 +291,22 @@ export class AppTree {
280
291
  const old_value = node?.props.props.value;
281
292
  // @ts-ignore
282
293
  const new_props = create_props_shared_props(new_state);
283
- node.props.shared_props = {
284
- ...node?.props.shared_props,
285
- ...new_props.shared_props
286
- };
287
- node.props.props = { ...node?.props.props, ...new_props.props };
294
+ // Modify props in-place instead of replacing the entire object.
295
+ // Replacing with a new object via spread can cause Svelte 5's
296
+ // deep $state proxy to lose track of the values during async
297
+ // component mounting/revival.
298
+ for (const key in new_props.shared_props) {
299
+ // @ts-ignore
300
+ node.props.shared_props[key] = new_props.shared_props[key];
301
+ }
302
+ for (const key in new_props.props) {
303
+ // @ts-ignore
304
+ node.props.props[key] = new_props.props[key];
305
+ }
306
+ // Also store as pending so the value can be applied via _set_data
307
+ // when the component eventually mounts and registers
308
+ const existing = this.#pending_updates.get(id) || {};
309
+ this.#pending_updates.set(id, { ...existing, ...new_state });
288
310
  if ("value" in new_state && !dequal(old_value, new_state.value)) {
289
311
  this.#event_dispatcher(id, "change", null);
290
312
  }
@@ -302,10 +324,6 @@ export class AppTree {
302
324
  // any values currently in the UI.
303
325
  // @ts-ignore
304
326
  await this.update_visibility(node, new_state);
305
- const parent_node = find_parent(this.root, id);
306
- if (parent_node)
307
- // @ts-ignore
308
- update_parent_visibility(parent_node, id, new_state.visible);
309
327
  }
310
328
  /**
311
329
  * Gets the current state of a component by its ID
@@ -324,24 +342,58 @@ export class AppTree {
324
342
  return null;
325
343
  }
326
344
  async render_previously_invisible_children(id) {
327
- this.root = this.traverse(this.root, [
328
- (node) => {
329
- if (node.id === id) {
330
- make_visible_if_not_rendered(node, this.#hidden_on_startup);
331
- }
332
- return node;
333
- },
334
- (node) => handle_visibility(node, this.#config.api_url)
335
- ]);
345
+ const node = find_node_by_id(this.root, id);
346
+ if (!node)
347
+ return;
348
+ // Check if this node or any of its descendants need to be made visible.
349
+ // If not, skip entirely to avoid unnecessary reactive updates
350
+ // from mutating the tree through the $state proxy.
351
+ if (!this.#hidden_on_startup.has(node.id) &&
352
+ !has_hidden_descendants(node, this.#hidden_on_startup)) {
353
+ return;
354
+ }
355
+ make_visible_if_not_rendered(node, this.#hidden_on_startup, true);
356
+ load_components(node, this.#config.api_url);
336
357
  }
337
358
  }
338
- function make_visible_if_not_rendered(node, hidden_on_startup) {
359
+ function make_visible_if_not_rendered(node, hidden_on_startup, is_target_node = false) {
339
360
  node.props.shared_props.visible = hidden_on_startup.has(node.id)
340
361
  ? true
341
362
  : node.props.shared_props.visible;
342
- node.children.forEach((child) => {
343
- make_visible_if_not_rendered(child, hidden_on_startup);
344
- });
363
+ if (node.type === "tabs") {
364
+ const selectedId = node.props.props.selected ?? node.props.props.initial_tabs?.[0]?.id;
365
+ node.children.forEach((child) => {
366
+ if (child.type === "tabitem" &&
367
+ (child.props.props.id === selectedId || child.id === selectedId)) {
368
+ make_visible_if_not_rendered(child, hidden_on_startup, false);
369
+ }
370
+ });
371
+ }
372
+ else if (node.type === "accordion" &&
373
+ node.props.props.open === false &&
374
+ !is_target_node) {
375
+ // Don't recurse into closed accordion content
376
+ }
377
+ else {
378
+ node.children.forEach((child) => {
379
+ make_visible_if_not_rendered(child, hidden_on_startup, false);
380
+ });
381
+ }
382
+ }
383
+ function has_hidden_descendants(node, hidden_on_startup) {
384
+ for (const child of node.children) {
385
+ if (hidden_on_startup.has(child.id))
386
+ return true;
387
+ if (has_hidden_descendants(child, hidden_on_startup))
388
+ return true;
389
+ }
390
+ return false;
391
+ }
392
+ function load_components(node, api_url) {
393
+ if (node.props.shared_props.visible && !node.component) {
394
+ node.component = get_component(node.type, node.component_class_id, api_url);
395
+ }
396
+ node.children.forEach((child) => load_components(child, api_url));
345
397
  }
346
398
  /**
347
399
  * Process the server function names and return a dictionary of functions
@@ -482,61 +534,6 @@ function untrack_children_of_closed_accordions_or_inactive_tabs(node, components
482
534
  }
483
535
  return node;
484
536
  }
485
- function handle_empty_forms(node, components_to_register) {
486
- // Check if the node is visible
487
- if (node.type === "form") {
488
- const all_children_invisible = node.children.every((child) => child.props.shared_props.visible === false);
489
- if (all_children_invisible) {
490
- node.props.shared_props.visible = false;
491
- components_to_register.delete(node.id);
492
- return node;
493
- }
494
- }
495
- return node;
496
- }
497
- function update_parent_visibility(node, child_made_visible, visibility_state) {
498
- // This function was added to address a tricky situation:
499
- // Form components are wrapped in a Form component automatically.
500
- // If all the children of the Form are invisible, the Form itself is marked invisible.
501
- // in AppTree.postprocess -> handle_empty_forms
502
- // This is to avoid rendering empty forms in the UI. They look ugly.
503
- // So what happens when a child inside the Form is made visible again?
504
- // The Form needs to become visible again too.
505
- // If the child is made invisible, the form should be too if all other children are invisible.
506
- // However, we are not doing this now since what we want to do is fetch the latest visibility of all
507
- // the children from the UI. However, get_data only returns the props, not the shared props.
508
- if (node.type === "form" &&
509
- node.children.length &&
510
- node.children.some((child) => child.id === child_made_visible)) {
511
- if (visibility_state === true)
512
- node.props.shared_props.visible = true;
513
- else if (!visibility_state && node.children.length === 1)
514
- node.props.shared_props.visible = "hidden";
515
- }
516
- return node;
517
- }
518
- function translate_props(node) {
519
- const supported_props = [
520
- "description",
521
- "info",
522
- "title",
523
- "placeholder",
524
- "value",
525
- "label"
526
- ];
527
- for (const attr of Object.keys(node.props.shared_props)) {
528
- if (supported_props.includes(attr)) {
529
- // @ts-ignore
530
- node.props.shared_props[attr] = translate_if_needed(node.props.shared_props[attr]);
531
- }
532
- }
533
- for (const attr of Object.keys(node.props.props)) {
534
- if (supported_props.includes(attr)) {
535
- node.props.props[attr] = translate_if_needed(node.props.props[attr]);
536
- }
537
- }
538
- return node;
539
- }
540
537
  function apply_initial_tabs(node, initial_tabs) {
541
538
  if (node.type === "tabs" && node.id in initial_tabs) {
542
539
  const tabs = initial_tabs[node.id].sort((a, b) => a.order - b.order);
@@ -555,8 +552,10 @@ function _gather_initial_tabs(node, initial_tabs, parent_tab_id, order) {
555
552
  if (!("id" in node.props.props)) {
556
553
  node.props.props.id = node.id;
557
554
  }
555
+ const i18n = node.props.props.i18n;
556
+ const raw_label = node.props.shared_props.label;
558
557
  initial_tabs[parent_tab_id].push({
559
- label: node.props.shared_props.label,
558
+ label: i18n ? i18n(raw_label) : raw_label,
560
559
  id: node.props.props.id,
561
560
  elem_id: node.props.shared_props.elem_id,
562
561
  visible: node.props.shared_props.visible,
package/package.json CHANGED
@@ -1,67 +1,67 @@
1
1
  {
2
2
  "name": "@gradio/core",
3
- "version": "1.1.3",
3
+ "version": "1.3.0",
4
4
  "type": "module",
5
5
  "devDependencies": {
6
- "@gradio/atoms": "^0.21.0",
7
- "@gradio/annotatedimage": "^0.11.2",
8
- "@gradio/audio": "^0.22.2",
9
- "@gradio/box": "^0.2.29",
10
- "@gradio/accordion": "^0.5.30",
6
+ "@gradio/annotatedimage": "^0.11.3",
7
+ "@gradio/accordion": "^0.5.31",
8
+ "@gradio/audio": "^0.22.3",
9
+ "@gradio/atoms": "^0.22.0",
10
+ "@gradio/box": "^0.2.30",
11
11
  "@gradio/browserstate": "^0.3.6",
12
- "@gradio/button": "^0.6.3",
13
- "@gradio/checkbox": "^0.6.2",
14
- "@gradio/checkboxgroup": "^0.9.2",
15
- "@gradio/code": "^0.17.2",
16
- "@gradio/colorpicker": "^0.5.5",
17
- "@gradio/client": "^2.0.4",
12
+ "@gradio/button": "^0.6.4",
13
+ "@gradio/chatbot": "^0.29.4",
14
+ "@gradio/checkbox": "^0.6.3",
15
+ "@gradio/checkboxgroup": "^0.9.3",
16
+ "@gradio/client": "^2.1.0",
17
+ "@gradio/colorpicker": "^0.5.6",
18
18
  "@gradio/column": "^0.3.2",
19
- "@gradio/chatbot": "^0.29.3",
20
- "@gradio/dataframe": "^0.21.4",
21
- "@gradio/datetime": "^0.4.2",
22
- "@gradio/dataset": "^0.5.3",
19
+ "@gradio/datetime": "^0.4.3",
20
+ "@gradio/code": "^0.17.3",
23
21
  "@gradio/downloadbutton": "^0.4.17",
24
- "@gradio/dropdown": "^0.11.3",
25
- "@gradio/fallback": "^0.4.33",
26
- "@gradio/fileexplorer": "^0.6.2",
27
- "@gradio/form": "^0.2.30",
28
- "@gradio/file": "^0.14.2",
29
- "@gradio/gallery": "^0.17.0",
22
+ "@gradio/dropdown": "^0.11.4",
23
+ "@gradio/dataset": "^0.5.4",
24
+ "@gradio/fallback": "^0.4.34",
25
+ "@gradio/file": "^0.14.3",
26
+ "@gradio/fileexplorer": "^0.6.3",
27
+ "@gradio/dataframe": "^0.21.6",
28
+ "@gradio/form": "^0.3.0",
30
29
  "@gradio/group": "^0.3.2",
31
- "@gradio/highlightedtext": "^0.11.1",
32
- "@gradio/html": "^0.9.2",
30
+ "@gradio/gallery": "^0.17.1",
31
+ "@gradio/highlightedtext": "^0.11.2",
32
+ "@gradio/html": "^0.10.0",
33
33
  "@gradio/icons": "^0.15.1",
34
- "@gradio/image": "^0.25.2",
35
- "@gradio/imageeditor": "^0.18.5",
36
- "@gradio/imageslider": "^0.4.2",
37
- "@gradio/json": "^0.7.1",
38
- "@gradio/markdown": "^0.13.27",
39
- "@gradio/label": "^0.6.2",
40
- "@gradio/model3d": "^0.16.3",
41
- "@gradio/multimodaltextbox": "^0.11.5",
42
- "@gradio/nativeplot": "^0.10.1",
43
- "@gradio/number": "^0.8.2",
44
- "@gradio/paramviewer": "^0.9.3",
45
- "@gradio/radio": "^0.9.2",
46
- "@gradio/plot": "^0.10.3",
47
- "@gradio/simpledropdown": "^0.3.33",
48
- "@gradio/sidebar": "^0.2.2",
34
+ "@gradio/image": "^0.25.3",
35
+ "@gradio/imageeditor": "^0.18.6",
36
+ "@gradio/label": "^0.6.3",
37
+ "@gradio/json": "^0.7.2",
38
+ "@gradio/markdown": "^0.13.28",
39
+ "@gradio/imageslider": "^0.4.3",
40
+ "@gradio/model3d": "^0.16.4",
41
+ "@gradio/multimodaltextbox": "^0.11.6",
42
+ "@gradio/nativeplot": "^0.10.2",
43
+ "@gradio/number": "^0.8.3",
44
+ "@gradio/paramviewer": "^0.9.4",
45
+ "@gradio/plot": "^0.10.4",
49
46
  "@gradio/row": "^0.3.1",
50
- "@gradio/simpleimage": "^0.9.4",
51
- "@gradio/simpletextbox": "^0.3.35",
52
- "@gradio/slider": "^0.7.4",
47
+ "@gradio/sidebar": "^0.2.3",
48
+ "@gradio/simpledropdown": "^0.3.34",
49
+ "@gradio/simpleimage": "^0.9.5",
50
+ "@gradio/slider": "^0.7.6",
51
+ "@gradio/simpletextbox": "^0.3.36",
52
+ "@gradio/radio": "^0.9.3",
53
53
  "@gradio/state": "^0.2.2",
54
- "@gradio/statustracker": "^0.12.3",
54
+ "@gradio/statustracker": "^0.12.4",
55
55
  "@gradio/tabitem": "^0.6.5",
56
- "@gradio/tabs": "^0.5.5",
57
- "@gradio/textbox": "^0.13.3",
56
+ "@gradio/tabs": "^0.5.7",
57
+ "@gradio/textbox": "^0.13.4",
58
58
  "@gradio/theme": "^0.6.1",
59
- "@gradio/upload": "^0.17.5",
60
59
  "@gradio/timer": "^0.4.8",
61
- "@gradio/utils": "^0.11.2",
60
+ "@gradio/upload": "^0.17.6",
62
61
  "@gradio/uploadbutton": "^0.9.17",
63
- "@gradio/vibeeditor": "^0.3.4",
64
- "@gradio/video": "^0.20.2"
62
+ "@gradio/utils": "^0.11.3",
63
+ "@gradio/video": "^0.20.3",
64
+ "@gradio/vibeeditor": "^0.3.5"
65
65
  },
66
66
  "msw": {
67
67
  "workerDirectory": "public"
package/src/Blocks.svelte CHANGED
@@ -12,7 +12,6 @@
12
12
  LayoutNode
13
13
  } from "./types";
14
14
  // import type { UpdateTransaction } from "./_init";
15
- import { setupi18n } from "./i18n";
16
15
  import type { ThemeMode, Payload } from "./types";
17
16
  import { Toast } from "@gradio/statustracker";
18
17
  import type { ToastMessage } from "@gradio/statustracker";
@@ -105,6 +104,7 @@
105
104
  });
106
105
 
107
106
  let messages: (ToastMessage & { fn_index: number })[] = $state([]);
107
+ let reconnect_interval: ReturnType<typeof setInterval> | null = null;
108
108
 
109
109
  function gradio_event_dispatcher(
110
110
  id: number,
@@ -207,6 +207,35 @@
207
207
  api_calls = [...api_calls, last_api_call];
208
208
  };
209
209
 
210
+ function handle_connection_lost(): void {
211
+ messages = messages.filter((m) => m.type !== "error");
212
+
213
+ ++_error_id;
214
+ messages.push({
215
+ title: "Connection Lost",
216
+ message: LOST_CONNECTION_MESSAGE,
217
+ fn_index: -1,
218
+ type: "error",
219
+ id: _error_id,
220
+ duration: null,
221
+ visible: true
222
+ });
223
+
224
+ reconnect_interval = setInterval(async () => {
225
+ try {
226
+ const status = await app.reconnect();
227
+ if (status === "connected" || status === "changed") {
228
+ clearInterval(reconnect_interval!);
229
+ reconnect_interval = null;
230
+ window.location.reload();
231
+ }
232
+ } catch (e) {
233
+ // server still unreachable
234
+ console.debug(e);
235
+ }
236
+ }, 2000);
237
+ }
238
+
210
239
  let dep_manager = new DependencyManager(
211
240
  dependencies,
212
241
  app,
@@ -214,7 +243,8 @@
214
243
  app_tree.get_state.bind(app_tree),
215
244
  app_tree.rerender.bind(app_tree),
216
245
  new_message,
217
- add_to_api_calls
246
+ add_to_api_calls,
247
+ handle_connection_lost
218
248
  );
219
249
 
220
250
  $effect(() => {
@@ -427,6 +457,7 @@
427
457
  return () => {
428
458
  mut.disconnect();
429
459
  res.disconnect();
460
+ if (reconnect_interval) clearInterval(reconnect_interval);
430
461
  };
431
462
  });
432
463
 
package/src/_init.ts CHANGED
@@ -12,8 +12,8 @@ import { load_component } from "virtual:component-loader";
12
12
  import type { client_return } from "@gradio/client";
13
13
  import { create_loading_status_store } from "./stores";
14
14
  import { _ } from "svelte-i18n";
15
- import { i18n_marker } from "./i18n";
16
15
  import type { SharedProps } from "@gradio/utils";
16
+ import { has_i18n_marker } from "@gradio/utils";
17
17
 
18
18
  export interface UpdateTransaction {
19
19
  id: number;
@@ -423,7 +423,7 @@ export function create_components(
423
423
  );
424
424
 
425
425
  instance.props.initial_tabs = child_tab_items?.map((child) => ({
426
- label: child.props.label.includes(i18n_marker) ? "" : child.props.label,
426
+ label: has_i18n_marker(child.props.label) ? "" : child.props.label,
427
427
  id: child.props.id,
428
428
  visible:
429
429
  typeof child.props.visible === "boolean" ||
@@ -6,8 +6,12 @@
6
6
 
7
7
  export let root: string;
8
8
  export let api_count: number;
9
- export let current_language: "python" | "javascript" | "bash" | "mcp" =
10
- "python";
9
+ export let current_language:
10
+ | "python"
11
+ | "javascript"
12
+ | "bash"
13
+ | "skill"
14
+ | "mcp" = "python";
11
15
 
12
16
  const dispatch = createEventDispatcher();
13
17
  </script>
@@ -19,6 +19,8 @@
19
19
  import javascript from "./img/javascript.svg";
20
20
  import bash from "./img/bash.svg";
21
21
  import ResponseSnippet from "./ResponseSnippet.svelte";
22
+ import skill from "./img/skill.svg";
23
+ import SkillSnippet from "./SkillSnippet.svelte";
22
24
  import mcp from "./img/mcp.svg";
23
25
  import MCPSnippet from "./MCPSnippet.svelte";
24
26
  import CopyMarkdown from "./CopyMarkdown.svelte";
@@ -53,7 +55,8 @@
53
55
  }
54
56
 
55
57
  export let api_calls: Payload[] = [];
56
- let current_language: "python" | "javascript" | "bash" | "mcp" = "python";
58
+ let current_language: "python" | "javascript" | "bash" | "skill" | "mcp" =
59
+ "python";
57
60
 
58
61
  $: sorted_dependencies = (() => {
59
62
  const valid = dependencies.filter(
@@ -81,13 +84,16 @@
81
84
  }
82
85
 
83
86
  function is_valid_language(lang: string | null): boolean {
84
- return ["python", "javascript", "bash", "mcp"].includes(lang ?? "");
87
+ return ["python", "javascript", "bash", "skill", "mcp"].includes(
88
+ lang ?? ""
89
+ );
85
90
  }
86
91
 
87
- const langs = [
92
+ $: langs = [
88
93
  ["python", "Python", python],
89
94
  ["javascript", "JavaScript", javascript],
90
95
  ["bash", "cURL", bash],
96
+ ...(space_id ? [["skill", "Skill", skill] as const] : []),
91
97
  ["mcp", "MCP", mcp]
92
98
  ] as const;
93
99
 
@@ -277,7 +283,12 @@
277
283
 
278
284
  const lang_param = get_query_param("lang");
279
285
  if (is_valid_language(lang_param)) {
280
- current_language = lang_param as "python" | "javascript" | "bash" | "mcp";
286
+ current_language = lang_param as
287
+ | "python"
288
+ | "javascript"
289
+ | "bash"
290
+ | "skill"
291
+ | "mcp";
281
292
  }
282
293
 
283
294
  const mcp_schema_url = `${root}gradio_api/mcp/schema`;
@@ -398,18 +409,25 @@
398
409
  API Documentation
399
410
  </p>
400
411
  {:else}
401
- <p class="padded">
402
- {#if current_language == "python" || current_language == "javascript"}
403
- 1. Install the
404
- <span style="text-transform:capitalize">{current_language}</span>
405
- client (<a
406
- href={current_language == "python" ? py_docs : js_docs}
407
- target="_blank">docs</a
408
- >) if you don't already have it installed.
409
- {:else if current_language == "bash"}
410
- 1. Confirm that you have cURL installed on your system.
411
- {/if}
412
- </p>
412
+ {#if current_language !== "skill"}
413
+ <p class="padded">
414
+ {#if current_language == "python" || current_language == "javascript"}
415
+ 1. Install the
416
+ <span style="text-transform:capitalize">{current_language}</span
417
+ >
418
+ client (<a
419
+ href={current_language == "python" ? py_docs : js_docs}
420
+ target="_blank">docs</a
421
+ >) if you don't already have it installed.
422
+ {:else if current_language == "bash"}
423
+ 1. Confirm that you have cURL installed on your system.
424
+ {/if}
425
+ </p>
426
+ {/if}
427
+
428
+ <div class:hidden={current_language !== "skill"}>
429
+ <SkillSnippet {space_id} />
430
+ </div>
413
431
 
414
432
  <div class:hidden={current_language !== "mcp"}>
415
433
  <MCPSnippet
@@ -427,7 +445,7 @@
427
445
  />
428
446
  </div>
429
447
 
430
- {#if current_language !== "mcp"}
448
+ {#if current_language !== "mcp" && current_language !== "skill"}
431
449
  <InstallSnippet {current_language} />
432
450
 
433
451
  <p class="padded">
@@ -480,25 +498,23 @@
480
498
  {/if}
481
499
  {/if}
482
500
 
483
- <div class:hidden={current_language === "mcp"}>
501
+ <div
502
+ class:hidden={current_language === "mcp" ||
503
+ current_language === "skill"}
504
+ >
484
505
  {#each sorted_dependencies as dependency}
485
506
  {#if info.named_endpoints["/" + dependency.api_name]}
486
507
  <div class="endpoint-container">
487
508
  <CodeSnippet
488
- endpoint_parameters={info.named_endpoints[
489
- "/" + dependency.api_name
490
- ].parameters}
491
509
  {dependency}
492
510
  {current_language}
493
- {root}
494
- {space_id}
495
- {username}
496
- api_prefix={app.api_prefix}
497
511
  api_description={info.named_endpoints[
498
512
  "/" + dependency.api_name
499
513
  ].description}
500
514
  {analytics}
501
515
  {last_api_call}
516
+ code_snippets={info.named_endpoints["/" + dependency.api_name]
517
+ .code_snippets}
502
518
  bind:markdown_code_snippets
503
519
  />
504
520