@gradio/core 1.0.0-dev.3 → 1.0.1

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.
@@ -3,9 +3,11 @@
3
3
  import CopyButton from "./CopyButton.svelte";
4
4
  import { Tool, Prompt, Resource } from "@gradio/icons";
5
5
  import { format_latency, get_color_from_success_rate } from "./utils";
6
+ import PercentileChart from "./PercentileChart.svelte";
6
7
 
7
8
  export let mcp_server_active: boolean;
8
9
  export let mcp_server_url_streamable: string;
10
+ export let root: string;
9
11
  export let tools: Tool[];
10
12
  export let all_tools: Tool[] = [];
11
13
  export let selected_tools: Set<string> = new Set();
@@ -69,7 +71,7 @@
69
71
  "gradio[mcp]",
70
72
  "gradio",
71
73
  "upload-mcp",
72
- mcp_server_url_streamable,
74
+ root,
73
75
  "<UPLOAD_DIRECTORY>"
74
76
  ]
75
77
  };
@@ -218,34 +220,19 @@
218
220
  : "⚠︎ No description provided in function docstring"}
219
221
  </span>
220
222
  {#if analytics[tool.meta.endpoint_name]}
221
- <span
222
- class="tool-analytics"
223
- style="color: var(--body-text-color-subdued); margin-left: 1em;"
224
- >
225
- Total requests: {analytics[tool.meta.endpoint_name]
226
- .total_requests}
227
- <span style={color}
228
- >({Math.round(success_rate * 100)}% successful)</span
223
+ {@const endpoint_analytics = analytics[tool.meta.endpoint_name]}
224
+ {@const p50 =
225
+ endpoint_analytics.process_time_percentiles["50th"]}
226
+ <div class="tool-analytics-wrapper" style="margin-left: 1em;">
227
+ <span
228
+ class="tool-analytics"
229
+ style="color: var(--body-text-color-subdued);"
229
230
  >
230
- &nbsp;|&nbsp; p50/p90/p99:
231
- {format_latency(
232
- analytics[tool.meta.endpoint_name].process_time_percentiles[
233
- "50th"
234
- ]
235
- )}
236
- /
237
- {format_latency(
238
- analytics[tool.meta.endpoint_name].process_time_percentiles[
239
- "90th"
240
- ]
241
- )}
242
- /
243
- {format_latency(
244
- analytics[tool.meta.endpoint_name].process_time_percentiles[
245
- "99th"
246
- ]
247
- )}
248
- </span>
231
+ {endpoint_analytics.total_requests} requests ({Math.round(
232
+ success_rate * 100
233
+ )}% successful, p50: {format_latency(p50)})
234
+ </span>
235
+ </div>
249
236
  {/if}
250
237
  </span>
251
238
  <span class="tool-arrow">{tool.expanded ? "▼" : "▶"}</span>
@@ -354,10 +341,16 @@
354
341
  {/if}
355
342
 
356
343
  <style>
344
+ .tool-analytics-wrapper {
345
+ position: relative;
346
+ display: inline-block;
347
+ }
348
+
357
349
  .tool-analytics {
358
350
  font-size: 0.95em;
359
351
  color: var(--body-text-color-subdued);
360
352
  }
353
+
361
354
  .transport-selection {
362
355
  margin-bottom: var(--size-4);
363
356
  }
@@ -14,6 +14,7 @@ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> =
14
14
  declare const MCPSnippet: $$__sveltets_2_IsomorphicComponent<{
15
15
  mcp_server_active: boolean;
16
16
  mcp_server_url_streamable: string;
17
+ root: string;
17
18
  tools: {
18
19
  name: string;
19
20
  description: string;
@@ -0,0 +1,125 @@
1
+ <script lang="ts">
2
+ import { format_latency } from "./utils";
3
+
4
+ export let p50: number;
5
+ export let p90: number;
6
+ export let p99: number;
7
+
8
+ $: max_latency = Math.max(p50, p90, p99);
9
+ </script>
10
+
11
+ <div class="tooltip-chart">
12
+ <div class="tooltip-arrow"></div>
13
+ <div class="chart-bars">
14
+ <div class="chart-bar-container">
15
+ <div class="chart-bar-label">p50</div>
16
+ <div class="chart-bar-wrapper">
17
+ <div
18
+ class="chart-bar"
19
+ style="width: {(p50 / max_latency) * 100}%"
20
+ ></div>
21
+ </div>
22
+ <div class="chart-bar-value">{format_latency(p50)}</div>
23
+ </div>
24
+ <div class="chart-bar-container">
25
+ <div class="chart-bar-label">p90</div>
26
+ <div class="chart-bar-wrapper">
27
+ <div
28
+ class="chart-bar"
29
+ style="width: {(p90 / max_latency) * 100}%"
30
+ ></div>
31
+ </div>
32
+ <div class="chart-bar-value">{format_latency(p90)}</div>
33
+ </div>
34
+ <div class="chart-bar-container">
35
+ <div class="chart-bar-label">p99</div>
36
+ <div class="chart-bar-wrapper">
37
+ <div
38
+ class="chart-bar"
39
+ style="width: {(p99 / max_latency) * 100}%"
40
+ ></div>
41
+ </div>
42
+ <div class="chart-bar-value">{format_latency(p99)}</div>
43
+ </div>
44
+ </div>
45
+ </div>
46
+
47
+ <style>
48
+ .tooltip-chart {
49
+ background: var(--background-fill-primary);
50
+ border: 1px solid var(--border-color-primary);
51
+ border-radius: var(--radius-md);
52
+ padding: var(--size-3);
53
+ box-shadow: var(--shadow-drop-lg);
54
+ min-width: 200px;
55
+ position: relative;
56
+ }
57
+
58
+ .tooltip-arrow {
59
+ position: absolute;
60
+ bottom: -8px;
61
+ left: 50%;
62
+ transform: translateX(-50%);
63
+ width: 0;
64
+ height: 0;
65
+ border-left: 8px solid transparent;
66
+ border-right: 8px solid transparent;
67
+ border-top: 8px solid var(--border-color-primary);
68
+ }
69
+
70
+ .tooltip-arrow::after {
71
+ content: "";
72
+ position: absolute;
73
+ bottom: 1px;
74
+ left: 50%;
75
+ transform: translateX(-50%);
76
+ width: 0;
77
+ height: 0;
78
+ border-left: 7px solid transparent;
79
+ border-right: 7px solid transparent;
80
+ border-top: 7px solid var(--background-fill-primary);
81
+ }
82
+
83
+ .chart-bars {
84
+ display: flex;
85
+ flex-direction: column;
86
+ gap: var(--size-2);
87
+ }
88
+
89
+ .chart-bar-container {
90
+ display: flex;
91
+ align-items: center;
92
+ gap: var(--size-2);
93
+ }
94
+
95
+ .chart-bar-label {
96
+ font-size: var(--text-sm);
97
+ font-weight: var(--weight-semibold);
98
+ color: var(--body-text-color);
99
+ min-width: 30px;
100
+ }
101
+
102
+ .chart-bar-wrapper {
103
+ flex: 1;
104
+ height: 16px;
105
+ background: var(--background-fill-secondary);
106
+ border-radius: var(--radius-sm);
107
+ overflow: hidden;
108
+ position: relative;
109
+ }
110
+
111
+ .chart-bar {
112
+ height: 100%;
113
+ background: var(--color-accent);
114
+ border-radius: var(--radius-sm);
115
+ transition: width 0.3s ease;
116
+ }
117
+
118
+ .chart-bar-value {
119
+ font-size: var(--text-sm);
120
+ color: var(--body-text-color);
121
+ min-width: 50px;
122
+ text-align: right;
123
+ font-family: var(--font-mono);
124
+ }
125
+ </style>
@@ -0,0 +1,22 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: Props & {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const PercentileChart: $$__sveltets_2_IsomorphicComponent<{
15
+ p50: number;
16
+ p90: number;
17
+ p99: number;
18
+ }, {
19
+ [evt: string]: CustomEvent<any>;
20
+ }, {}, {}, string>;
21
+ type PercentileChart = InstanceType<typeof PercentileChart>;
22
+ export default PercentileChart;
@@ -2,7 +2,7 @@ import type { ComponentMeta, Dependency as IDependency, LayoutNode, Payload } fr
2
2
  import { Client, type client_return } from "@gradio/client";
3
3
  import { LoadingStatus } from "@gradio/statustracker";
4
4
  import type { ToastMessage } from "@gradio/statustracker";
5
- import type { StatusMessage } from "@gradio/client";
5
+ import type { StatusMessage, LogMessage } from "@gradio/client";
6
6
  /**
7
7
  * A dependency as used by the frontend
8
8
  * This class represents a discrete dependency that can be triggered by an event
@@ -21,6 +21,8 @@ export declare class Dependency {
21
21
  triggers: [number, "success" | "failure" | "all"][];
22
22
  original_trigger_id: number | null;
23
23
  show_progress_on: number[] | null;
24
+ component_prop_inputs: number[];
25
+ show_progress: "full" | "minimal" | "hidden";
24
26
  functions: {
25
27
  frontend?: (...args: unknown[]) => Promise<unknown[]>;
26
28
  backend: boolean;
@@ -56,6 +58,10 @@ interface DispatchEvent {
56
58
  target_id?: number;
57
59
  event_data: unknown;
58
60
  }
61
+ type UpdateStateCallback = (id: number, state: Record<string, unknown>, check_visibility?: boolean) => Promise<void>;
62
+ type GetStateCallback = (id: number) => Promise<Record<string, unknown> | null>;
63
+ type RerenderCallback = (components: ComponentMeta[], layout: LayoutNode) => void;
64
+ type LogCallback = (title: string, message: string, fn_index: number, type: ToastMessage["type"], duration?: number | null, visible?: boolean) => void;
59
65
  /**
60
66
  * Manages all dependencies for an app acting as a bridge between app state and Dependencies
61
67
  * Responsible for registering dependencies and dispatching events to them
@@ -75,13 +81,13 @@ export declare class DependencyManager {
75
81
  client: Client;
76
82
  queue: Set<number>;
77
83
  add_to_api_calls: (payload: Payload) => void;
78
- update_state_cb: (id: number, state: Record<string, unknown>, check_visibility?: boolean) => Promise<void>;
79
- get_state_cb: (id: number) => Promise<Record<string, unknown> | null>;
80
- rerender_cb: (components: ComponentMeta[], layout: LayoutNode) => void;
81
- log_cb: (title: string, message: string, fn_index: number, type: ToastMessage["type"], duration?: number | null, visible?: boolean) => void;
84
+ update_state_cb: UpdateStateCallback;
85
+ get_state_cb: GetStateCallback;
86
+ rerender_cb: RerenderCallback;
87
+ log_cb: LogCallback;
82
88
  loading_stati: LoadingStatus;
83
89
  constructor(dependencies: IDependency[], client: Client, update_state_cb: (id: number, state: Record<string, unknown>, check_visibility?: boolean) => Promise<void>, get_state_cb: (id: number) => Promise<Record<string, unknown> | null>, rerender_cb: (components: ComponentMeta[], layout: LayoutNode) => void, log_cb: (title: string, message: string, fn_index: number, type: ToastMessage["type"], duration?: number | null, visible?: boolean) => void, add_to_api_calls: (payload: Payload) => void);
84
- reload(dependencies: IDependency[], update_state: any, get_state: any, rerender: any, client: any): void;
90
+ reload(dependencies: IDependency[], update_state: UpdateStateCallback, get_state: GetStateCallback, rerender: RerenderCallback, client: Client): void;
85
91
  register_loading_stati(deps: Map<number, Dependency>): void;
86
92
  clear_loading_status(component_id: number): void;
87
93
  update_loading_stati_state(): Promise<void>;
@@ -115,9 +121,10 @@ export declare class DependencyManager {
115
121
  * Gathers the current state of the inputs
116
122
  *
117
123
  * @param ids the ids of the components to gather state from
124
+ * @param prop_indices the indices (relative to ids array) that should return all component props instead of just the value
118
125
  * @returns an array of the current state of the components, in the same order as the ids
119
126
  */
120
- gather_state(ids: number[]): Promise<(unknown | null)[]>;
127
+ gather_state(ids: number[], prop_indices?: number[]): Promise<(unknown | null)[]>;
121
128
  /** Sets the event arguments for a specific component
122
129
  *
123
130
  * @param id the id of the component to set the event arguments for
@@ -24,6 +24,8 @@ export class Dependency {
24
24
  // in the case of chained events, it would be the id of the initial trigger
25
25
  original_trigger_id = null;
26
26
  show_progress_on = null;
27
+ component_prop_inputs = [];
28
+ show_progress;
27
29
  functions;
28
30
  constructor(dep_config) {
29
31
  this.id = dep_config.id;
@@ -31,6 +33,7 @@ export class Dependency {
31
33
  this.inputs = dep_config.inputs;
32
34
  this.outputs = dep_config.outputs;
33
35
  this.connection_type = dep_config.connection;
36
+ this.show_progress = dep_config.show_progress;
34
37
  this.functions = {
35
38
  frontend: dep_config.js
36
39
  ? process_frontend_fn(dep_config.js, dep_config.backend_fn, dep_config.inputs.length, dep_config.outputs.length)
@@ -45,6 +48,7 @@ export class Dependency {
45
48
  this.cancels = dep_config.cancels;
46
49
  this.trigger_modes = dep_config.trigger_mode;
47
50
  this.show_progress_on = dep_config.show_progress_on || null;
51
+ this.component_prop_inputs = dep_config.component_prop_inputs || [];
48
52
  for (let i = 0; i < dep_config.event_specific_args?.length || 0; i++) {
49
53
  const key = dep_config.event_specific_args[i];
50
54
  this.event_args[key] = dep_config[key] ?? null;
@@ -117,31 +121,31 @@ export class DependencyManager {
117
121
  loading_stati = new LoadingStatus();
118
122
  constructor(dependencies, client, update_state_cb, get_state_cb, rerender_cb, log_cb, add_to_api_calls) {
119
123
  this.add_to_api_calls = add_to_api_calls;
120
- this.client = client;
121
124
  this.log_cb = log_cb;
122
- // this.update_state_cb = update_state_cb;
123
- // this.get_state_cb = get_state_cb;
124
- // this.rerender_cb = rerender_cb;
125
- this.reload(dependencies, update_state_cb, get_state_cb, rerender_cb);
125
+ this.update_state_cb = update_state_cb;
126
+ this.get_state_cb = get_state_cb;
127
+ this.rerender_cb = rerender_cb;
128
+ this.client = client;
129
+ this.reload(dependencies, update_state_cb, get_state_cb, rerender_cb, client);
126
130
  }
127
131
  reload(dependencies, update_state, get_state, rerender, client) {
128
132
  const { by_id, by_event } = this.create(dependencies);
129
133
  this.dependencies_by_event = by_event;
130
134
  this.dependencies_by_fn = by_id;
135
+ this.client = client;
136
+ this.update_state_cb = update_state;
137
+ this.get_state_cb = get_state;
138
+ this.rerender_cb = rerender;
131
139
  for (const [dep_id, dep] of this.dependencies_by_fn) {
132
140
  for (const [output_id] of dep.targets) {
133
141
  this.set_event_args(output_id, dep.event_args);
134
142
  }
135
143
  }
136
- this.client = client;
137
- this.update_state_cb = update_state;
138
- this.get_state_cb = get_state;
139
- this.rerender_cb = rerender;
140
144
  this.register_loading_stati(by_id);
141
145
  }
142
146
  register_loading_stati(deps) {
143
147
  for (const [_, dep] of deps) {
144
- this.loading_stati.register(dep.id, dep.show_progress_on || dep.outputs, dep.inputs);
148
+ this.loading_stati.register(dep.id, dep.show_progress_on || dep.outputs, dep.inputs, dep.show_progress);
145
149
  }
146
150
  }
147
151
  clear_loading_status(component_id) {
@@ -206,7 +210,7 @@ export class DependencyManager {
206
210
  });
207
211
  this.update_loading_stati_state();
208
212
  }
209
- const data_payload = await this.gather_state(dep.inputs);
213
+ const data_payload = await this.gather_state(dep.inputs, dep.component_prop_inputs);
210
214
  const unset_args = await Promise.all(dep.targets.map(([output_id]) => this.set_event_args(output_id, dep.event_args)));
211
215
  const { success, failure, all } = dep.get_triggers();
212
216
  try {
@@ -241,7 +245,7 @@ export class DependencyManager {
241
245
  unset_args.forEach((fn) => fn());
242
246
  }
243
247
  else if (dep_submission.type === "data") {
244
- this.handle_data(dep.outputs, dep_submission.data);
248
+ await this.handle_data(dep.outputs, dep_submission.data);
245
249
  unset_args.forEach((fn) => fn());
246
250
  }
247
251
  else {
@@ -268,7 +272,7 @@ export class DependencyManager {
268
272
  if (result === null)
269
273
  continue;
270
274
  if (result.type === "data") {
271
- this.handle_data(dep.outputs, result.data);
275
+ await this.handle_data(dep.outputs, result.data);
272
276
  }
273
277
  if (result.type === "status") {
274
278
  if (result.original_msg === "process_starts" &&
@@ -341,7 +345,9 @@ export class DependencyManager {
341
345
  return;
342
346
  }
343
347
  const _message = result?.message?.replace(MESSAGE_QUOTE_RE, (_, b) => b);
344
- this.log_cb(result._title ?? "Error", _message, fn_index, "error", status.duration, status.visible);
348
+ this.log_cb(
349
+ //@ts-ignore
350
+ result?._title ?? "Error", _message || "", fn_index, "error", status.duration, status.visible);
345
351
  throw new Error("Dependency function failed");
346
352
  }
347
353
  else {
@@ -356,6 +362,12 @@ export class DependencyManager {
356
362
  }
357
363
  }
358
364
  if (result.type === "render") {
365
+ this.loading_stati.update({
366
+ status: "complete",
367
+ fn_index: dep.id,
368
+ stream_state: null
369
+ });
370
+ this.update_loading_stati_state();
359
371
  const { layout, components, render_id, dependencies } = result.data;
360
372
  this.rerender_cb(components, layout);
361
373
  // update dependencies
@@ -470,7 +482,7 @@ export class DependencyManager {
470
482
  * @param data the data to update the components with
471
483
  * */
472
484
  async handle_data(outputs, data) {
473
- outputs.forEach(async (output_id, i) => {
485
+ await Promise.all(outputs.map(async (output_id, i) => {
474
486
  const _data = data[i] === undefined ? NOVALUE : data[i];
475
487
  if (_data === NOVALUE)
476
488
  return;
@@ -498,16 +510,20 @@ export class DependencyManager {
498
510
  else {
499
511
  await this.update_state_cb(output_id, { value: _data }, false);
500
512
  }
501
- });
513
+ }));
502
514
  }
503
515
  /**
504
516
  * Gathers the current state of the inputs
505
517
  *
506
518
  * @param ids the ids of the components to gather state from
519
+ * @param prop_indices the indices (relative to ids array) that should return all component props instead of just the value
507
520
  * @returns an array of the current state of the components, in the same order as the ids
508
521
  */
509
- async gather_state(ids) {
510
- return (await Promise.all(ids.map((id) => this.get_state_cb(id)))).map((state) => {
522
+ async gather_state(ids, prop_indices = []) {
523
+ return (await Promise.all(ids.map((id) => this.get_state_cb(id)))).map((state, index) => {
524
+ if (prop_indices.includes(index)) {
525
+ return state ?? null;
526
+ }
511
527
  return state?.value ?? null;
512
528
  });
513
529
  }
@@ -519,7 +535,9 @@ export class DependencyManager {
519
535
  */
520
536
  async set_event_args(id, args) {
521
537
  let current_args = {};
522
- const current_state = await this.get_state_cb(id);
538
+ const current_state = await this.get_state_cb?.(id);
539
+ if (!current_state)
540
+ return () => { };
523
541
  for (const [key] of Object.entries(args)) {
524
542
  current_args[key] = current_state?.[key] ?? null;
525
543
  }
@@ -27,8 +27,8 @@ export declare class AppTree {
27
27
  ready: Promise<void>;
28
28
  ready_resolve: () => void;
29
29
  resolved: boolean;
30
- constructor(components: ComponentMeta[], layout: LayoutNode, dependencies: Dependency[], config: AppConfig, app: client_return, reactive_formatter: (str: string) => string);
31
- reload(components: ComponentMeta[], layout: LayoutNode, dependencies: Dependency[], config: AppConfig): void;
30
+ constructor(components: ComponentMeta[], layout: LayoutNode, dependencies: Dependency[], config: Omit<AppConfig, "api_url">, app: client_return, reactive_formatter: (str: string) => string);
31
+ reload(components: ComponentMeta[], layout: LayoutNode, dependencies: Dependency[], config: Omit<AppConfig, "api_url">): void;
32
32
  /**
33
33
  * Registers a component with its ID and data callbacks
34
34
  * @param id the ID of the component
@@ -40,7 +40,10 @@ export class AppTree {
40
40
  this.ready_resolve = resolve;
41
41
  });
42
42
  this.reactive_formatter = reactive_formatter;
43
- this.#config = config;
43
+ this.#config = {
44
+ ...config,
45
+ api_url: new URL(config.api_prefix, config.root).toString()
46
+ };
44
47
  this.#component_payload = components;
45
48
  this.#layout_payload = layout;
46
49
  this.#dependency_payload = dependencies;
@@ -67,7 +70,10 @@ export class AppTree {
67
70
  reload(components, layout, dependencies, config) {
68
71
  this.#layout_payload = layout;
69
72
  this.#component_payload = components;
70
- this.#config = config;
73
+ this.#config = {
74
+ ...config,
75
+ api_url: new URL(config.api_prefix, config.root).toString()
76
+ };
71
77
  this.#dependency_payload = dependencies;
72
78
  this.root = this.create_node({ id: layout.id, children: [] }, new Map(), true);
73
79
  for (const comp of components) {
@@ -115,11 +121,11 @@ export class AppTree {
115
121
  process() { }
116
122
  postprocess(tree) {
117
123
  this.root = this.traverse(tree, [
118
- (node) => handle_visibility(node, this.#config.root),
119
- (node) => untrack_children_of_invisible_parents(node, this.#config.root, this.components_to_register),
120
- (node) => handle_empty_forms(node, this.#config.root, this.components_to_register),
121
- (node) => translate_props(node, this.#config.root),
122
- (node) => apply_initial_tabs(node, this.#config.root, this.initial_tabs),
124
+ (node) => handle_visibility(node, this.#config.api_url),
125
+ (node) => untrack_children_of_invisible_parents(node, this.components_to_register),
126
+ (node) => handle_empty_forms(node, this.components_to_register),
127
+ (node) => translate_props(node),
128
+ (node) => apply_initial_tabs(node, this.initial_tabs),
123
129
  (node) => this.find_attached_events(node, this.#dependency_payload)
124
130
  ]);
125
131
  }
@@ -191,7 +197,7 @@ export class AppTree {
191
197
  if (reactive_formatter) {
192
198
  component.props.i18n = reactive_formatter;
193
199
  }
194
- const processed_props = gather_props(opts.id, component.props, [this.#input_ids, this.#output_ids], this.client, { ...this.#config });
200
+ const processed_props = gather_props(opts.id, component.props, [this.#input_ids, this.#output_ids], this.client, this.#config.api_url, { ...this.#config });
195
201
  const type = type_map[component.type] || component.type;
196
202
  const node = {
197
203
  id: opts.id,
@@ -201,7 +207,7 @@ export class AppTree {
201
207
  show_progress_on: null,
202
208
  component_class_id: component.component_class_id || component.type,
203
209
  component: processed_props.shared_props.visible !== false
204
- ? get_component(component.type, component.component_class_id, this.#config.root || "")
210
+ ? get_component(component.type, component.component_class_id, this.#config.api_url || "")
205
211
  : null,
206
212
  key: component.key,
207
213
  rendered_in: component.rendered_in,
@@ -242,7 +248,7 @@ export class AppTree {
242
248
  this.root = this.traverse(this.root, [
243
249
  //@ts-ignore
244
250
  (n) => set_visibility_for_updated_node(n, id, new_state.visible),
245
- (n) => handle_visibility(n, this.#config.root)
251
+ (n) => handle_visibility(n, this.#config.api_url)
246
252
  ]);
247
253
  already_updated_visibility = true;
248
254
  }
@@ -255,7 +261,7 @@ export class AppTree {
255
261
  // need to let the UI settle before traversing again
256
262
  // otherwise there could be
257
263
  await tick();
258
- this.root = this.traverse(this.root, (n) => handle_visibility(n, this.#config.root));
264
+ this.root = this.traverse(this.root, (n) => handle_visibility(n, this.#config.api_url));
259
265
  }
260
266
  /**
261
267
  * Gets the current state of a component by its ID
@@ -304,7 +310,7 @@ export function process_server_fn(id, server_fns, app) {
304
310
  * @param additional any additional props to include
305
311
  * @returns the gathered props as an object with `shared_props` and `props` keys
306
312
  */
307
- function gather_props(id, props, dependencies, client, additional = {}) {
313
+ function gather_props(id, props, dependencies, client, api_url, additional = {}) {
308
314
  const _shared_props = {};
309
315
  const _props = {};
310
316
  for (const key in props) {
@@ -336,22 +342,22 @@ function gather_props(id, props, dependencies, client, additional = {}) {
336
342
  _shared_props.client = client;
337
343
  _shared_props.id = id;
338
344
  _shared_props.interactive = determine_interactivity(id, _shared_props.interactive, _props.value, dependencies);
339
- _shared_props.load_component = (name, variant) => get_component(name, "", _shared_props.root || "", variant);
345
+ _shared_props.load_component = (name, variant) => get_component(name, "", api_url, variant);
340
346
  _shared_props.visible =
341
347
  _shared_props.visible === undefined ? true : _shared_props.visible;
342
348
  _shared_props.loading_status = {};
343
349
  return { shared_props: _shared_props, props: _props };
344
350
  }
345
- function handle_visibility(node, root) {
351
+ function handle_visibility(node, api_url) {
346
352
  // Check if the node is visible
347
353
  if (node.props.shared_props.visible && !node.component) {
348
354
  const result = {
349
355
  ...node,
350
- component: get_component(node.type, node.component_class_id, root),
356
+ component: get_component(node.type, node.component_class_id, api_url),
351
357
  children: []
352
358
  };
353
359
  if (node.children) {
354
- result.children = node.children.map((child) => handle_visibility(child, root));
360
+ result.children = node.children.map((child) => handle_visibility(child, api_url));
355
361
  }
356
362
  return result;
357
363
  }
@@ -372,14 +378,14 @@ function _untrack(node, components_to_register) {
372
378
  }
373
379
  return;
374
380
  }
375
- function untrack_children_of_invisible_parents(node, root, components_to_register) {
381
+ function untrack_children_of_invisible_parents(node, components_to_register) {
376
382
  // Check if the node is visible
377
383
  if (node.props.shared_props.visible !== true) {
378
384
  _untrack(node, components_to_register);
379
385
  }
380
386
  return node;
381
387
  }
382
- function handle_empty_forms(node, root, components_to_register) {
388
+ function handle_empty_forms(node, components_to_register) {
383
389
  // Check if the node is visible
384
390
  if (node.type === "form") {
385
391
  const all_children_invisible = node.children.every((child) => child.props.shared_props.visible === false);
@@ -391,7 +397,7 @@ function handle_empty_forms(node, root, components_to_register) {
391
397
  }
392
398
  return node;
393
399
  }
394
- function translate_props(node, root) {
400
+ function translate_props(node) {
395
401
  const supported_props = [
396
402
  "description",
397
403
  "info",
@@ -413,7 +419,7 @@ function translate_props(node, root) {
413
419
  }
414
420
  return node;
415
421
  }
416
- function apply_initial_tabs(node, root, initial_tabs) {
422
+ function apply_initial_tabs(node, initial_tabs) {
417
423
  if (node.type === "tabs" && node.id in initial_tabs) {
418
424
  const tabs = initial_tabs[node.id].sort((a, b) => a.order - b.order);
419
425
  node.props.props.initial_tabs = tabs;
@@ -71,6 +71,7 @@ export interface Dependency {
71
71
  like_user_message: boolean;
72
72
  event_specific_args: ("time_limit" | "stream_every" | "like_user_message")[];
73
73
  js_implementation: string | null;
74
+ component_prop_inputs: number[];
74
75
  }
75
76
  interface TypeDescription {
76
77
  input_payload?: string;
@@ -106,5 +107,6 @@ export interface AppConfig {
106
107
  max_file_size?: number;
107
108
  autoscroll: boolean;
108
109
  api_prefix: string;
110
+ api_url: string;
109
111
  }
110
112
  export {};