@gradio/client 2.5.1 → 2.7.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/dist/types.d.ts CHANGED
@@ -281,11 +281,11 @@ export interface ClientOptions {
281
281
  */
282
282
  oauth_token?: string;
283
283
  /**
284
- * Whether to save each call's inputs and outputs in this browser's local
285
- * storage, so they can be reviewed on the app's run history page. Defaults
286
- * to true, and only ever applies in a browser: in Node there is no storage
287
- * to write to and nothing is recorded. The app can turn it off for everyone
288
- * with `run_history=False` on `launch()`, which takes precedence over this.
284
+ * Whether to save each call's inputs and outputs to the history destination
285
+ * selected in this browser (local storage by default, or a connected bucket).
286
+ * Defaults to true, and only ever applies in a browser: in Node there is no
287
+ * selected destination and nothing is recorded. The app can turn it off for
288
+ * everyone with `run_history=False` on `launch()`, which takes precedence.
289
289
  */
290
290
  record_history?: boolean;
291
291
  }
@@ -1 +1 @@
1
- {"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../src/upload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,wBAAsB,MAAM,CAC3B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,QAAQ,EAAE,EACrB,QAAQ,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,EAClB,aAAa,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,CAsCrC;AAED,wBAAsB,aAAa,CAClC,KAAK,EAAE,IAAI,EAAE,EACb,SAAS,CAAC,EAAE,OAAO,GACjB,OAAO,CAAC,QAAQ,EAAE,CAAC,CAYrB;AAED,qBAAa,QAAQ;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,IAAI;;MAAgC;gBAEjC,EACX,IAAI,EACJ,GAAG,EACH,SAAS,EACT,IAAI,EACJ,IAAI,EACJ,SAAS,EACT,SAAS,EACT,QAAQ,EACR,GAAG,EACH,EAAE;QACF,IAAI,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,IAAI,CAAC;QACZ,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,GAAG,CAAC,EAAE,MAAM,CAAC;KACb;CAWD"}
1
+ {"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../src/upload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,wBAAsB,MAAM,CAC3B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,QAAQ,EAAE,EACrB,QAAQ,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,EAClB,aAAa,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,CA0CrC;AAED,wBAAsB,aAAa,CAClC,KAAK,EAAE,IAAI,EAAE,EACb,SAAS,CAAC,EAAE,OAAO,GACjB,OAAO,CAAC,QAAQ,EAAE,CAAC,CAYrB;AAED,qBAAa,QAAQ;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,IAAI;;MAAgC;gBAEjC,EACX,IAAI,EACJ,GAAG,EACH,SAAS,EACT,IAAI,EACJ,IAAI,EACJ,SAAS,EACT,SAAS,EACT,QAAQ,EACR,GAAG,EACH,EAAE;QACF,IAAI,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,IAAI,CAAC;QACZ,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,GAAG,CAAC,EAAE,MAAM,CAAC;KACb;CAWD"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Client for the durable run history in an HF Hub bucket
3
+ * (`/gradio_api/run-history/*`).
4
+ *
5
+ * Read-only by design. Records are written by the server from the run it
6
+ * actually executed — there is no push function here, and nothing in this
7
+ * module can create a record.
8
+ *
9
+ * Every call names the bucket it is talking about. The server holds no
10
+ * per-session binding, so two tabs (or two apps on one origin) cannot end up
11
+ * reading each other's history.
12
+ */
13
+ export declare function is_valid_bucket_id(id: string): boolean;
14
+ /** Mirrors `HistoryRecord` in `gradio/history.py`. */
15
+ export interface HistoryRecord {
16
+ record_id: string;
17
+ endpoint: string;
18
+ inputs: unknown;
19
+ outputs: unknown;
20
+ started_at: string;
21
+ schema_version: number;
22
+ }
23
+ export interface HistoryResult<T> {
24
+ ok: boolean;
25
+ status: number;
26
+ data: T;
27
+ detail?: string;
28
+ }
29
+ /**
30
+ * Create the bucket if it does not exist and confirm it is writable. Stores
31
+ * nothing server-side — the caller keeps its own choice and names it on every
32
+ * later request.
33
+ */
34
+ export declare function connect_bucket(root: string, bucket_id: string): Promise<HistoryResult<null>>;
35
+ export declare function list_user_buckets(root: string): Promise<HistoryResult<string[]>>;
36
+ export declare function list_bucket_records(root: string, bucket: string): Promise<HistoryResult<HistoryRecord[]>>;
37
+ export declare function asset_url(root: string, bucket: string, endpoint: string, record_id: string, filename: string): string;
38
+ //# sourceMappingURL=bucket_sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bucket_sync.d.ts","sourceRoot":"","sources":["../../src/utils/bucket_sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAKtD;AAED,sDAAsD;AACtD,MAAM,WAAW,aAAa;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa,CAAC,CAAC;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,CAAC,CAAC;IACR,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAuDD;;;;GAIG;AACH,wBAAsB,cAAc,CACnC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAmB9B;AAED,wBAAsB,iBAAiB,CACtC,IAAI,EAAE,MAAM,GACV,OAAO,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,CAIlC;AAED,wBAAsB,mBAAmB,CACxC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACZ,OAAO,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC,CAAC,CAIzC;AAED,wBAAgB,SAAS,CACxB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACd,MAAM,CAQR"}
@@ -9,6 +9,13 @@ export interface RunHistoryScope {
9
9
  /** The authenticated user, when the app uses `auth`. */
10
10
  username?: string | null;
11
11
  }
12
+ export type RunHistoryStorage = {
13
+ type: "browser";
14
+ bucket_id?: string;
15
+ } | {
16
+ type: "bucket";
17
+ bucket_id: string;
18
+ };
12
19
  export type RunStatus = "running" | "completed" | "failed";
13
20
  export interface StoredRunComponent {
14
21
  type: string;
@@ -70,6 +77,8 @@ export interface ReplayTarget {
70
77
  }[];
71
78
  }
72
79
  export declare function read_run_history(scope: RunHistoryScope | null | undefined): StoredRun[];
80
+ export declare function read_run_history_storage(scope: RunHistoryScope | null | undefined): RunHistoryStorage;
81
+ export declare function set_run_history_storage(scope: RunHistoryScope | null | undefined, storage: RunHistoryStorage): void;
73
82
  export declare function clear_run_history(scope: RunHistoryScope | null | undefined): void;
74
83
  export declare function delete_run_history(scope: RunHistoryScope | null | undefined, id: string): void;
75
84
  export declare function stage_run_history_replay(scope: RunHistoryScope | null | undefined, run: StoredRun): void;
@@ -1 +1 @@
1
- {"version":3,"file":"run_history.d.ts","sourceRoot":"","sources":["../../src/utils/run_history.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run_history.d.ts","sourceRoot":"","sources":["../../src/utils/run_history.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"submit.d.ts","sourceRoot":"","sources":["../../src/utils/submit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGX,WAAW,EAMX,cAAc,EACd,MAAM,UAAU,CAAC;AAoBlB,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAOnC,wBAAgB,MAAM,CACrB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GAAG,MAAM,EACzB,IAAI,GAAE,OAAO,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EAC9C,UAAU,CAAC,EAAE,OAAO,EACpB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,EAC1B,UAAU,CAAC,EAAE,OAAO,EACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACzC,cAAc,CAAC,WAAW,CAAC,CA8uB7B"}
1
+ {"version":3,"file":"submit.d.ts","sourceRoot":"","sources":["../../src/utils/submit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGX,WAAW,EAMX,cAAc,EACd,MAAM,UAAU,CAAC;AAyBlB,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAQnC,wBAAgB,MAAM,CACrB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GAAG,MAAM,EACzB,IAAI,GAAE,OAAO,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EAC9C,UAAU,CAAC,EAAE,OAAO,EACpB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,EAC1B,UAAU,CAAC,EAAE,OAAO,EACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACzC,cAAc,CAAC,WAAW,CAAC,CA0vB7B"}
@@ -1 +1 @@
1
- {"version":3,"file":"view_api.d.ts","sourceRoot":"","sources":["../../src/utils/view_api.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAInC,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAiDzD"}
1
+ {"version":3,"file":"view_api.d.ts","sourceRoot":"","sources":["../../src/utils/view_api.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAInC,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAoDzD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gradio/client",
3
- "version": "2.5.1",
3
+ "version": "2.7.0",
4
4
  "description": "Gradio API client",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
package/src/client.ts CHANGED
@@ -35,6 +35,7 @@ import { check_and_wake_space, check_space_status } from "./helpers/spaces";
35
35
  import { initialize_zerogpu_handshake } from "./helpers/zerogpu";
36
36
  import { open_stream, readable_stream, close_stream } from "./utils/stream";
37
37
  import { clear_run_history } from "./utils/run_history";
38
+ import { sign_config_file_urls, sign_file_urls } from "./helpers/data";
38
39
  import {
39
40
  API_INFO_ERROR_MSG,
40
41
  APP_ID_URL,
@@ -48,6 +49,7 @@ export class Client {
48
49
  app_reference: string;
49
50
  options: ClientOptions;
50
51
  deep_link: string | null = null;
52
+ page: string | null = null;
51
53
 
52
54
  config: Config | undefined;
53
55
  api_prefix = "";
@@ -199,6 +201,7 @@ export class Client {
199
201
  ) {
200
202
  this.app_reference = app_reference;
201
203
  this.deep_link = options.query_params?.deep_link || null;
204
+ this.page = options.query_params?.page ?? null;
202
205
  if (!options.events) {
203
206
  options.events = ["data"];
204
207
  }
@@ -250,25 +253,19 @@ export class Client {
250
253
  }
251
254
 
252
255
  async _resolve_heartbeat(_config: Config): Promise<void> {
253
- if (_config) {
254
- this.config = _config;
255
- this.api_prefix = _config.api_prefix || "";
256
-
257
- if (this.config && this.config.connect_heartbeat) {
258
- if (this.config.space_id && this.options.token) {
259
- this.jwt = await get_jwt(
260
- this.config.space_id,
261
- this.options.token,
262
- this.cookies
263
- );
264
- }
265
- }
266
- }
256
+ this.config = _config;
257
+ this.api_prefix = _config.api_prefix || "";
267
258
 
268
259
  if (_config.space_id && this.options.token) {
269
- this.jwt = await get_jwt(_config.space_id, this.options.token);
260
+ this.jwt = await get_jwt(
261
+ _config.space_id,
262
+ this.options.token,
263
+ this.cookies
264
+ );
270
265
  }
271
266
 
267
+ sign_config_file_urls(this.config, this.jwt);
268
+
272
269
  if (this.config && this.config.connect_heartbeat) {
273
270
  // connect to the heartbeat endpoint via GET request
274
271
  const heartbeat_url = new URL(
@@ -344,6 +341,7 @@ export class Client {
344
341
  this.config = config;
345
342
  this.api_prefix = config.api_prefix || "";
346
343
  this.api_map = map_names_to_ids(config.dependencies || []);
344
+ sign_config_file_urls(this.config, this.jwt);
347
345
  try {
348
346
  this.api_info = await this.view_api();
349
347
  } catch (e) {
@@ -545,6 +543,12 @@ export class Client {
545
543
  }
546
544
 
547
545
  const output = await response.json();
546
+ sign_file_urls(
547
+ output,
548
+ this.config.root,
549
+ this.config.api_prefix || "",
550
+ this.jwt
551
+ );
548
552
  return output;
549
553
  } catch (e) {
550
554
  console.warn(e);
@@ -224,3 +224,80 @@ export function handle_payload(
224
224
 
225
225
  return updated_payload;
226
226
  }
227
+
228
+ const FILE_ROUTE_PREFIXES = ["/file=", "/file/", "/stream/", "/proxy="];
229
+
230
+ /**
231
+ * Add the Space JWT required for browser-managed media requests.
232
+ *
233
+ * This is a bearer credential and must not be logged or persisted. Restrict it
234
+ * to Gradio routes that serve files; the user's Hugging Face token remains in
235
+ * the Authorization header used to obtain this credential.
236
+ */
237
+ export function sign_file_urls(
238
+ data: unknown,
239
+ root: string,
240
+ api_prefix: string,
241
+ jwt: string | false
242
+ ): void {
243
+ if (!jwt || data === null || typeof data !== "object") return;
244
+
245
+ const signature = jwt;
246
+ const root_url = new URL(root);
247
+ const root_path = root_url.pathname.replace(/\/+$/, "");
248
+ const normalized_api_prefix = api_prefix
249
+ ? `/${api_prefix.replace(/^\/+|\/+$/g, "")}`
250
+ : "";
251
+ const route_bases = new Set([
252
+ `${root_path}${normalized_api_prefix}`,
253
+ normalized_api_prefix
254
+ ]);
255
+ if (!normalized_api_prefix) {
256
+ route_bases.add(`${root_path}/gradio_api`);
257
+ route_bases.add("/gradio_api");
258
+ }
259
+
260
+ function visit(value: unknown): void {
261
+ if (value === null || typeof value !== "object") return;
262
+
263
+ const object = value as Record<string, unknown>;
264
+ const meta = object.meta as Record<string, unknown> | undefined;
265
+ if (meta?._type === "gradio.FileData" && typeof object.url === "string") {
266
+ const file_url = new URL(
267
+ object.url,
268
+ `${root_url.toString().replace(/\/$/, "")}/`
269
+ );
270
+ const is_file_route = [...route_bases].some((base) =>
271
+ FILE_ROUTE_PREFIXES.some((route) =>
272
+ file_url.pathname.startsWith(`${base}${route}`)
273
+ )
274
+ );
275
+ if (
276
+ (file_url.protocol === "http:" || file_url.protocol === "https:") &&
277
+ file_url.origin === root_url.origin &&
278
+ is_file_route
279
+ ) {
280
+ file_url.searchParams.set("__sign", signature);
281
+ object.url = file_url.toString();
282
+ }
283
+ }
284
+
285
+ for (const child of Object.values(object)) visit(child);
286
+ }
287
+
288
+ visit(data);
289
+ }
290
+
291
+ export function sign_config_file_urls(
292
+ config: Config,
293
+ jwt: string | false
294
+ ): void {
295
+ for (const component of config.components || []) {
296
+ sign_file_urls(
297
+ component.props?.value,
298
+ config.root,
299
+ config.api_prefix || "",
300
+ jwt
301
+ );
302
+ }
303
+ }
@@ -83,10 +83,22 @@ export function map_names_to_ids(
83
83
 
84
84
  export function resolve_config_root(
85
85
  root: string,
86
- current_location: string
86
+ current_location: string,
87
+ prioritize_current_location = false
87
88
  ): string {
88
- const root_url = new URL(root, current_location);
89
89
  const current_url = new URL(current_location);
90
+ const root_url = new URL(root, current_url);
91
+ // Modern Colab configs can omit is_colab even though the backend root still
92
+ // uses one of Colab's internal-only hostname families.
93
+ const is_colab_runtime =
94
+ root_url.hostname.endsWith(".colab-user-runtimes.internal") ||
95
+ root_url.hostname.endsWith(".codatalab-user-runtimes.internal");
96
+ if (prioritize_current_location || is_colab_runtime) {
97
+ return new URL(new URL(root, current_url).pathname, current_url)
98
+ .toString()
99
+ .replace(/\/$/, "");
100
+ }
101
+
90
102
  if (root_url.hostname !== current_url.hostname) {
91
103
  return root;
92
104
  }
@@ -117,12 +129,10 @@ export async function resolve_config(
117
129
  window.gradio_config.dev_mode ||
118
130
  (typeof window !== "undefined" && window?.BUILD_MODE === "dev")
119
131
  ) {
120
- let config_url = join_urls(
121
- endpoint,
122
- this.deep_link
123
- ? CONFIG_URL + "?deep_link=" + this.deep_link
124
- : CONFIG_URL
125
- );
132
+ let config_url = new URL(join_urls(endpoint, CONFIG_URL));
133
+ if (this.deep_link)
134
+ config_url.searchParams.set("deep_link", this.deep_link);
135
+ if (this.page !== null) config_url.searchParams.set("page", this.page);
126
136
  const response = await this.fetch(config_url, {
127
137
  headers,
128
138
  credentials: this.options.credentials ?? "same-origin"
@@ -138,15 +148,20 @@ export async function resolve_config(
138
148
  // The page was rendered by this Gradio server, so a same-host root may
139
149
  // contain an internal protocol or port supplied by a reverse proxy. Keep
140
150
  // the configured path, but use the browser-visible origin for requests
141
- // made by the client itself (queue, upload, reset, etc.).
151
+ // made by the client itself (queue, upload, reset, etc.). Colab's public
152
+ // proxy uses a different hostname, so always prefer the browser origin.
142
153
  const config = { ...window.gradio_config } as unknown as Config;
143
- config.root = resolve_config_root(config.root, location.href);
154
+ config.root = resolve_config_root(
155
+ config.root,
156
+ location.href,
157
+ config.is_colab
158
+ );
144
159
  return config;
145
160
  } else if (endpoint) {
146
- let config_url = join_urls(
147
- endpoint,
148
- this.deep_link ? CONFIG_URL + "?deep_link=" + this.deep_link : CONFIG_URL
149
- );
161
+ let config_url = new URL(join_urls(endpoint, CONFIG_URL));
162
+ if (this.deep_link)
163
+ config_url.searchParams.set("deep_link", this.deep_link);
164
+ if (this.page !== null) config_url.searchParams.set("page", this.page);
150
165
 
151
166
  const response = await this.fetch(config_url, {
152
167
  headers,
package/src/index.ts CHANGED
@@ -12,13 +12,25 @@ export {
12
12
  delete_run_history,
13
13
  on_run_history_change,
14
14
  read_run_history,
15
+ read_run_history_storage,
15
16
  run_history_url,
17
+ set_run_history_storage,
16
18
  stage_run_history_replay,
17
19
  type ReplayTarget,
20
+ type RunHistoryStorage,
18
21
  type RunHistoryScope,
19
22
  type StoredRunComponent,
20
23
  type StoredRun
21
24
  } from "./utils/run_history";
25
+ export {
26
+ asset_url,
27
+ connect_bucket,
28
+ is_valid_bucket_id,
29
+ list_bucket_records,
30
+ list_user_buckets,
31
+ type HistoryRecord,
32
+ type HistoryResult
33
+ } from "./utils/bucket_sync";
22
34
 
23
35
  export type {
24
36
  SpaceStatus,
@@ -0,0 +1,138 @@
1
+ import { describe, it, expect, vi, afterEach } from "vitest";
2
+ import {
3
+ asset_url,
4
+ connect_bucket,
5
+ is_valid_bucket_id,
6
+ list_bucket_records,
7
+ list_user_buckets
8
+ } from "../utils/bucket_sync";
9
+
10
+ describe("is_valid_bucket_id", () => {
11
+ it("accepts user/name form", () => {
12
+ expect(is_valid_bucket_id("alice/my-history")).toBe(true);
13
+ });
14
+
15
+ it("rejects missing slash", () => {
16
+ expect(is_valid_bucket_id("alice")).toBe(false);
17
+ });
18
+
19
+ it("rejects path traversal", () => {
20
+ expect(is_valid_bucket_id("alice/..")).toBe(false);
21
+ expect(is_valid_bucket_id("../etc")).toBe(false);
22
+ expect(is_valid_bucket_id("alice/./x")).toBe(false);
23
+ });
24
+
25
+ it("rejects empty segments", () => {
26
+ expect(is_valid_bucket_id("alice/")).toBe(false);
27
+ expect(is_valid_bucket_id("/name")).toBe(false);
28
+ });
29
+ });
30
+
31
+ describe("list_bucket_records", () => {
32
+ const orig = globalThis.fetch;
33
+ afterEach(() => {
34
+ globalThis.fetch = orig;
35
+ });
36
+
37
+ it("reports a failed request instead of an empty history", async () => {
38
+ globalThis.fetch = vi.fn().mockResolvedValue({
39
+ ok: false,
40
+ status: 401,
41
+ json: async () => ({ detail: "oauth session required" })
42
+ }) as any;
43
+ const res = await list_bucket_records("http://x", "alice/h");
44
+ expect(res.ok).toBe(false);
45
+ expect(res.status).toBe(401);
46
+ expect(res.data).toEqual([]);
47
+ });
48
+
49
+ it("returns records on success", async () => {
50
+ globalThis.fetch = vi.fn().mockResolvedValue({
51
+ ok: true,
52
+ status: 200,
53
+ json: async () => ({ records: [{ record_id: "r1" }] })
54
+ }) as any;
55
+ const res = await list_bucket_records("http://x", "alice/h");
56
+ expect(res.ok).toBe(true);
57
+ expect(res.data).toHaveLength(1);
58
+ });
59
+
60
+ it("names the bucket on every request rather than relying on session state", async () => {
61
+ const spy = vi.fn().mockResolvedValue({
62
+ ok: true,
63
+ status: 200,
64
+ json: async () => ({ records: [] })
65
+ });
66
+ globalThis.fetch = spy as any;
67
+ await list_bucket_records("http://x", "alice/my-history");
68
+ const called = String(spy.mock.calls[0][0]);
69
+ expect(called).toContain("bucket=alice%2Fmy-history");
70
+ expect(called).not.toContain("endpoint=");
71
+ expect(called).not.toContain("limit=");
72
+ });
73
+
74
+ it("does not emit a root-absolute URL when root is empty", async () => {
75
+ const spy = vi.fn().mockResolvedValue({
76
+ ok: true,
77
+ status: 200,
78
+ json: async () => ({ records: [] })
79
+ });
80
+ globalThis.fetch = spy as any;
81
+ await list_bucket_records("", "alice/h");
82
+ const called = String(spy.mock.calls[0][0]);
83
+ // must resolve against the document base, not "/gradio_api/..."
84
+ expect(called.startsWith("/gradio_api/")).toBe(false);
85
+ expect(called).toContain("gradio_api/run-history/records");
86
+ });
87
+ });
88
+
89
+ describe("bucket setup", () => {
90
+ const orig = globalThis.fetch;
91
+ afterEach(() => {
92
+ globalThis.fetch = orig;
93
+ });
94
+
95
+ it("ignores the connect response body", async () => {
96
+ globalThis.fetch = vi.fn().mockResolvedValue({
97
+ ok: true,
98
+ status: 200,
99
+ json: async () => ({ ok: true })
100
+ }) as any;
101
+ const result = await connect_bucket("http://x", "alice/history");
102
+ expect(result).toMatchObject({ ok: true, data: null });
103
+ });
104
+
105
+ it("returns bucket ids as strings", async () => {
106
+ globalThis.fetch = vi.fn().mockResolvedValue({
107
+ ok: true,
108
+ status: 200,
109
+ json: async () => ({ buckets: ["alice/one", "alice/two"] })
110
+ }) as any;
111
+ expect(await list_user_buckets("http://x")).toMatchObject({
112
+ ok: true,
113
+ data: ["alice/one", "alice/two"]
114
+ });
115
+ });
116
+
117
+ it("preserves authentication errors for the connect UI", async () => {
118
+ globalThis.fetch = vi.fn().mockResolvedValue({
119
+ ok: false,
120
+ status: 401,
121
+ json: async () => ({ detail: "oauth session required" })
122
+ }) as any;
123
+ expect(await list_user_buckets("http://x")).toMatchObject({
124
+ ok: false,
125
+ status: 401,
126
+ data: [],
127
+ detail: "oauth session required"
128
+ });
129
+ });
130
+ });
131
+
132
+ describe("asset_url", () => {
133
+ it("addresses an asset by bucket, endpoint and record", () => {
134
+ const url = asset_url("http://x", "alice/h", "predict", "r1", "a001.png");
135
+ expect(url).toContain("/run-history/records/predict/r1/assets/a001.png");
136
+ expect(url).toContain("bucket=alice%2Fh");
137
+ });
138
+ });
@@ -5,6 +5,7 @@ import {
5
5
  skip_queue,
6
6
  post_message,
7
7
  handle_file,
8
+ sign_file_urls,
8
9
  handle_payload
9
10
  } from "../helpers/data";
10
11
  import { config_response, endpoint_info } from "./test_data";
@@ -359,6 +360,100 @@ describe("post_message", () => {
359
360
  );
360
361
  });
361
362
 
363
+ describe("sign_file_urls", () => {
364
+ it("signs nested file and stream URLs on the private Space origin", () => {
365
+ const data = {
366
+ image: {
367
+ path: "/tmp/cat.png",
368
+ url: "gradio_api/file=/tmp/cat.png?download=true",
369
+ meta: { _type: "gradio.FileData" }
370
+ },
371
+ gallery: [
372
+ {
373
+ image: {
374
+ path: "/tmp/tone.wav",
375
+ url: "/gradio_api/stream/tone.wav",
376
+ is_stream: true,
377
+ meta: { _type: "gradio.FileData" }
378
+ }
379
+ }
380
+ ],
381
+ proxied: {
382
+ path: "https://nested-space.hf.space/gradio_api/file=/tmp/cat.png",
383
+ url: "/app/gradio_api/proxy=https://nested-space.hf.space/gradio_api/file=/tmp/cat.png",
384
+ meta: { _type: "gradio.FileData" }
385
+ }
386
+ };
387
+
388
+ sign_file_urls(
389
+ data,
390
+ "https://private-space.hf.space/app",
391
+ "/gradio_api",
392
+ "jwt_123"
393
+ );
394
+
395
+ expect(data.image.url).toBe(
396
+ "https://private-space.hf.space/app/gradio_api/file=/tmp/cat.png?download=true&__sign=jwt_123"
397
+ );
398
+ expect(data.gallery[0].image.url).toBe(
399
+ "https://private-space.hf.space/gradio_api/stream/tone.wav?__sign=jwt_123"
400
+ );
401
+ expect(data.proxied.url).toBe(
402
+ "https://private-space.hf.space/app/gradio_api/proxy=https://nested-space.hf.space/gradio_api/file=/tmp/cat.png?__sign=jwt_123"
403
+ );
404
+ });
405
+
406
+ it("does not sign external or unrelated same-origin URLs", () => {
407
+ const data = {
408
+ external: {
409
+ path: "https://cdn.example.com/cat.png",
410
+ url: "https://cdn.example.com/cat.png",
411
+ meta: { _type: "gradio.FileData" }
412
+ },
413
+ plain: {
414
+ url: "https://private-space.hf.space/gradio_api/file=/tmp/cat.png"
415
+ },
416
+ unrelated: {
417
+ path: "/tmp/cat.png",
418
+ url: "https://private-space.hf.space/api/custom-file",
419
+ meta: { _type: "gradio.FileData" }
420
+ }
421
+ };
422
+
423
+ sign_file_urls(
424
+ data,
425
+ "https://private-space.hf.space",
426
+ "/gradio_api",
427
+ "jwt_123"
428
+ );
429
+
430
+ expect(data.external.url).toBe("https://cdn.example.com/cat.png");
431
+ expect(data.plain.url).toBe(
432
+ "https://private-space.hf.space/gradio_api/file=/tmp/cat.png"
433
+ );
434
+ expect(data.unrelated.url).toBe(
435
+ "https://private-space.hf.space/api/custom-file"
436
+ );
437
+ });
438
+
439
+ it("does nothing without a Space JWT", () => {
440
+ const file = {
441
+ path: "/tmp/cat.png",
442
+ url: "https://private-space.hf.space/gradio_api/file=/tmp/cat.png",
443
+ meta: { _type: "gradio.FileData" }
444
+ };
445
+
446
+ sign_file_urls(
447
+ file,
448
+ "https://private-space.hf.space",
449
+ "/gradio_api",
450
+ false
451
+ );
452
+
453
+ expect(file.url).not.toContain("__sign");
454
+ });
455
+ });
456
+
362
457
  describe("handle_file", () => {
363
458
  it("should handle a Blob object and return the blob", () => {
364
459
  const blob = new Blob(["test data"], { type: "image/png" });