nspasojevic commited on
Commit
84275c4
·
verified ·
1 Parent(s): a8ebc42

Explorer slim-ui-9d95b298 (download selection carried to the Space's own tab, clearer folder hint) + caches for the 100-user target (indexing #80 at 6adbe77)

Browse files

Dist 9d95b298 = 7b12d13c (#83) + 9d95b298. #80: verdict L2 4M (config.py), Redis --maxmemory 6gb volatile-lru, /llm_parse nginx cache per day, parse LRU off, /metrics + pipeline/cache_metrics.py. Runtime files on prod's rails (nginx -t on 1.22/1.24; supervisor 4.2.5 parse + sh -n on every program). Rollback: ~/dev/hf-space-work/batch-1015/rollback-a8ebc429.

docker/hf-space/nginx.conf.template CHANGED
@@ -34,9 +34,61 @@
34
  # nothing in this image pre-creates a parent — /tmp/nginx-cache/slim-stats fails `nginx -t`. The
35
  # `levels=` subdirectories are different: nginx creates those itself on the first write.
36
  proxy_cache_path /tmp/slim-stats-cache levels=1 keys_zone=slim_stats_cache:2m max_size=256m inactive=1h use_temp_path=off;
37
- # Thumbnails (/images): ~1,500 JPEGs of 27-52 KB (~75 MB) fit well inside 1g. Lives in the container's
38
- # /tmp, so every deploy, restart or sleep starts it cold.
39
- proxy_cache_path /tmp/slim-images-cache levels=1:2 keys_zone=slim_images_cache:10m max_size=1g inactive=7d use_temp_path=off;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  # Library media (/library_media/ below): a file asked for under its ?v= (its content hash) never changes; the
41
  # manifest (no ?v=) revalidates, so a new fetch at the next container start shows at once.
42
  map $arg_v $slim_library_cache {
@@ -148,12 +200,17 @@ server {
148
  # UI/ReDoc can request sub-resources under their own path.
149
  location = /health { proxy_pass http://127.0.0.1:8000; }
150
  location = /openapi.json { proxy_pass http://127.0.0.1:8000; }
151
- # Prometheus /metrics stays private to the container (127.0.0.1:8000
152
- # directly): an explicit JSON 404 rather than no location, which would
153
- # fall through to the SPA's index.html with a 200.
 
154
  location = /metrics {
 
 
 
 
155
  default_type application/json;
156
- return 404 '{"detail":"Not Found"}';
157
  }
158
  location /docs { proxy_pass http://127.0.0.1:8000; }
159
  location /redoc { proxy_pass http://127.0.0.1:8000; }
@@ -178,6 +235,10 @@ server {
178
  # add_header inside one of our locations replaces his server-level headers for THOSE responses
179
  # — /images and the stats cache re-declare his three CORS lines, /config.js and /index.html
180
  # (same-origin UI files) do not. Applied by slim/devspace/deploy.sh.
 
 
 
 
181
  client_max_body_size 32m; # query-image searches POST a base64 JPEG (nginx default 1 MB)
182
  gzip_types text/css application/javascript application/json image/svg+xml; # stock gzip covers text/html only
183
 
@@ -280,6 +341,83 @@ server {
280
  add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
281
  add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
282
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
283
  # Our 404s are JSON like the API's own (a bare `return 404;` would be nginx's text/html error
284
  # page): reachable only from the locations below, so nothing of his changes.
285
  location @slim_not_found {
 
34
  # nothing in this image pre-creates a parent — /tmp/nginx-cache/slim-stats fails `nginx -t`. The
35
  # `levels=` subdirectories are different: nginx creates those itself on the first write.
36
  proxy_cache_path /tmp/slim-stats-cache levels=1 keys_zone=slim_stats_cache:2m max_size=256m inactive=1h use_temp_path=off;
37
+ # Thumbnails (/images): ~1,500 JPEGs of 27-52 KB (~75 MB) per view set; 5g leaves room for every view and size
38
+ # the Explorer asks for. Lives in the container's /tmp, so every deploy, restart or sleep starts it cold.
39
+ proxy_cache_path /tmp/slim-images-cache levels=1:2 keys_zone=slim_images_cache:10m max_size=5g inactive=7d use_temp_path=off;
40
+ # Query parses (/llm_parse/query, below): one entry per day and request body, kept 24 h. The day is in the key
41
+ # because the parser's prompt carries today's date: "made last week" parses differently tomorrow. Sized for a day at
42
+ # 100 users (~186k new keys: 1 MB of zone holds ~8k keys; each entry takes at least one 4 KB block on disk).
43
+ proxy_cache_path /tmp/slim-parse-cache levels=1:2 keys_zone=slim_parse_cache:24m max_size=1g inactive=24h use_temp_path=off;
44
+ # The Explorer's background count probes (/search_hybrid, below) for 30 min. A user's search is never cached: every
45
+ # one reaches deepsearch-api, whose usage telemetry must see it (owner, 2026-10-15).
46
+ # All the caches' caps add up to ~6.3 GB of the container's disk (the Space's storage limit counts it).
47
+ proxy_cache_path /tmp/slim-count-cache levels=1:2 keys_zone=slim_count_cache:2m max_size=64m inactive=30m use_temp_path=off;
48
+ # Today's date for the parse key, in nginx's time zone, which is the parser's (date.today()): the container sets no
49
+ # TZ, so both read UTC.
50
+ map $time_iso8601 $slim_today {
51
+ default "";
52
+ "~^(\d{4}-\d{2}-\d{2})" $1;
53
+ }
54
+ # proxy_cache_methods POST ADDS POST (nginx caches GET and HEAD anyway): anything but a POST bypasses those caches
55
+ # and is never stored.
56
+ map $request_method $slim_not_post {
57
+ default 1;
58
+ POST "";
59
+ }
60
+ # A count probe is the Explorer's (utils/backendCounts.js): x-simready-cache-intent: 1, its service-account Basic user
61
+ # simready-central-svc-user, and no x-api-key. deepsearch-api's search telemetry (search_query_total) records the
62
+ # query's username from exactly these headers: the API key's "admin_access" first, else the Basic user. So a cached
63
+ # probe hides only service-account events, never a user's search. Anything else (a user's search, the header alone,
64
+ # another user) reaches the API. Case-sensitive, as the telemetry's username is.
65
+ map "$http_x_simready_cache_intent|$remote_user|$http_x_api_key" $slim_count_probe {
66
+ default "";
67
+ "~^1\|simready-central-svc-user\|$" 1;
68
+ }
69
+ # Never cached, even for a probe: a body with a cursor or a non-zero offset (a later page), or with an image to
70
+ # search by (an image vector query, image_similarity_search), or one that asks the API to validate its results
71
+ # (validate_results: missing verdicts would stick). JSON escapes a quote inside a string, so the words in a query
72
+ # cannot match these.
73
+ map $request_body $slim_probe_skip {
74
+ default "";
75
+ "~\"cursor\"\s*:\s*(?!null\b)" 1;
76
+ "~\"offset\"\s*:\s*0*[1-9]" 1;
77
+ "~\"query_type\"\s*:\s*\"image\"" 1;
78
+ "~\"image_similarity_search\"\s*:\s*(?!null\b)" 1;
79
+ "~\"validate_results\"\s*:\s*true" 1;
80
+ }
81
+ # /metrics' nginx counts (pipeline/cache_metrics.py): one syslog datagram per request of a cached route, carrying
82
+ # the cache and $upstream_cache_status; nothing of the request itself. The source is $slim_count_probe ("" or 1)
83
+ # then the URI: /search_hybrid counts only as a probe, so a user's search sends nothing.
84
+ map "$slim_count_probe$request_uri" $slim_cache_route {
85
+ default "";
86
+ "~^1?/llm_parse/query(\?|$)" parse;
87
+ "~^1/search_hybrid(\?|$)" count;
88
+ "~^1?/images(\?|$)" images;
89
+ "~^1?/search/stats/usd_properties(\?|$)" stats;
90
+ }
91
+ log_format slim_cache_status '$slim_cache_route $upstream_cache_status';
92
  # Library media (/library_media/ below): a file asked for under its ?v= (its content hash) never changes; the
93
  # manifest (no ?v=) revalidates, so a new fetch at the next container start shows at once.
94
  map $arg_v $slim_library_cache {
 
200
  # UI/ReDoc can request sub-resources under their own path.
201
  location = /health { proxy_pass http://127.0.0.1:8000; }
202
  location = /openapi.json { proxy_pass http://127.0.0.1:8000; }
203
+ # /metrics is NOT deepsearch-api's (127.0.0.1:8000/metrics stays private to
204
+ # the container): it is pipeline/cache_metrics.py's page, an allow-list of
205
+ # cache hit/miss counters (supervisord program cache-metrics). Not up yet:
206
+ # a JSON 503, never the SPA's index.html.
207
  location = /metrics {
208
+ proxy_pass http://127.0.0.1:8030/metrics;
209
+ error_page 502 504 = @slim_metrics_unavailable;
210
+ }
211
+ location @slim_metrics_unavailable {
212
  default_type application/json;
213
+ return 503 '{"detail":"cache metrics are not running"}';
214
  }
215
  location /docs { proxy_pass http://127.0.0.1:8000; }
216
  location /redoc { proxy_pass http://127.0.0.1:8000; }
 
235
  # add_header inside one of our locations replaces his server-level headers for THOSE responses
236
  # — /images and the stats cache re-declare his three CORS lines, /config.js and /index.html
237
  # (same-origin UI files) do not. Applied by slim/devspace/deploy.sh.
238
+ # Also here (2026-10-15, for 100 users): the parse cache `= /llm_parse/query` and the count-probe cache, which
239
+ # `= /search_hybrid` routes probes to (each takes his prefix's requests like `= /images`; a user's search keeps
240
+ # his rewrite + proxy_pass, uncached), and a server-level access_log that feeds the /metrics page in place of the
241
+ # stock file log (his `= /metrics` 404 now serves it; deepsearch-api's own metrics stay private).
242
  client_max_body_size 32m; # query-image searches POST a base64 JPEG (nginx default 1 MB)
243
  gzip_types text/css application/javascript application/json image/svg+xml; # stock gzip covers text/html only
244
 
 
341
  add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
342
  add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
343
  }
344
+ # The two POST caches below (parses, count probes) share these rules, ported from SimReady Central's gateway: the
345
+ # key holds the raw request body; POST only ($slim_not_post); 200s only (the API answers a failed parse or search
346
+ # with an error status); the API's no-store is ignored for the cache and still reaches the browser. SHARED by
347
+ # every member, keyed on the body alone: valid ONLY while the image runs with ENABLE_ACCESS_VERIFICATION=False,
348
+ # STORAGE_REQUIRE_AUTH=False and verify_access=false (every member sees the same results;
349
+ # tests/test_hf_space_caches.py checks both Dockerfiles). A body past client_body_buffer_size spills to disk and
350
+ # leaves $request_body empty: $request_body_file (set only then) keeps it out, else all such bodies would share
351
+ # one key. proxy_buffer_size must hold the cache file's header with its key, or nginx stores entries it never
352
+ # reads back. proxy_cache_lock: concurrent identical requests wait up to 15 s for the first one (lock_age too: a
353
+ # parse can outlast nginx's default 5 s) instead of all reaching the API.
354
+ #
355
+ # Query parsing: his /llm_parse/ rewrite + proxy_pass (this exact match wins over his prefix) plus the cache.
356
+ # A parse costs 0.5-9 s on the endpoint and depends only on the body and the day (the prompt's $today): the
357
+ # key is day + URI + body, kept 24 h. A prompt or model change is a restart, which empties /tmp.
358
+ location = /llm_parse/query {
359
+ if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
360
+ rewrite ^/llm_parse/(.*)$ /v3/deepsearch/llm_parse/$1 break;
361
+ proxy_pass http://127.0.0.1:8000;
362
+ proxy_cache slim_parse_cache;
363
+ proxy_cache_key "$slim_today|$request_uri|$request_body";
364
+ proxy_cache_bypass $slim_not_post $request_body_file;
365
+ proxy_no_cache $slim_not_post $request_body_file;
366
+ proxy_cache_valid 200 24h;
367
+ proxy_cache_methods POST;
368
+ proxy_ignore_headers Cache-Control Expires;
369
+ proxy_cache_lock on;
370
+ proxy_cache_lock_timeout 15s;
371
+ proxy_cache_lock_age 15s;
372
+ client_body_buffer_size 32k;
373
+ proxy_buffer_size 60k;
374
+ proxy_buffers 16 8k;
375
+ proxy_hide_header X-Cache-Status;
376
+ add_header X-Cache-Status $upstream_cache_status always;
377
+ add_header Access-Control-Allow-Origin "*" always;
378
+ add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
379
+ add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
380
+ }
381
+ # Searches: NEVER cached (owner, 2026-10-15). Every search a user sends takes his /search_hybrid rewrite +
382
+ # proxy_pass, unchanged, and reaches deepsearch-api, whose usage telemetry (search_query_total) must see each
383
+ # one. This exact match exists only to send the Explorer's count probes ($slim_count_probe) to their cache.
384
+ location = /search_hybrid {
385
+ if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
386
+ if ($slim_count_probe) { rewrite ^ /_slim_count_probe last; }
387
+ rewrite ^/search_hybrid(.*)$ /v3/deepsearch/search$1 break;
388
+ proxy_pass http://127.0.0.1:8000;
389
+ }
390
+ # The Explorer's background count probes (limit-1 and file-name searches for its totals; SimReady Central's
391
+ # gateway caches them the same way): their own zone, 30 min, stale while one request refreshes an entry. Never a
392
+ # later page, an image search or validate_results ($slim_probe_skip).
393
+ location = /_slim_count_probe {
394
+ internal;
395
+ rewrite ^ /v3/deepsearch/search break;
396
+ proxy_pass http://127.0.0.1:8000;
397
+ proxy_cache slim_count_cache;
398
+ proxy_cache_key "$request_uri|$request_body";
399
+ proxy_cache_bypass $slim_not_post $request_body_file $slim_probe_skip;
400
+ proxy_no_cache $slim_not_post $request_body_file $slim_probe_skip;
401
+ proxy_cache_valid 200 30m;
402
+ proxy_cache_use_stale updating;
403
+ proxy_cache_methods POST;
404
+ proxy_ignore_headers Cache-Control Expires;
405
+ proxy_cache_lock on;
406
+ proxy_cache_lock_timeout 15s;
407
+ proxy_cache_lock_age 15s;
408
+ client_body_buffer_size 32k;
409
+ proxy_buffer_size 60k;
410
+ proxy_buffers 16 8k;
411
+ proxy_hide_header X-Cache-Status;
412
+ add_header X-Cache-Status $upstream_cache_status always;
413
+ add_header Access-Control-Allow-Origin "*" always;
414
+ add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
415
+ add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
416
+ }
417
+ # A cached route's request goes to /metrics' counts (see $slim_cache_route). This server-level access_log
418
+ # replaces nginx.conf's file log (/var/log/nginx/access.log): nothing rotated it and nobody can read it in a
419
+ # Space, yet every request grew it on the container's disk.
420
+ access_log syslog:server=127.0.0.1:8031,tag=slimcache,nohostname slim_cache_status if=$slim_cache_route;
421
  # Our 404s are JSON like the API's own (a bare `return 404;` would be nginx's text/html error
422
  # page): reachable only from the locations below, so nothing of his changes.
423
  location @slim_not_found {
docker/hf-space/supervisord-gpu.conf CHANGED
@@ -27,7 +27,12 @@ stderr_logfile=/dev/stderr
27
  stderr_logfile_maxbytes=0
28
 
29
  [program:redis]
30
- command=/usr/bin/redis-server --port 6379 --databases 32 --save "" --stop-writes-on-bgsave-error no --dir /tmp
 
 
 
 
 
31
  user=1000
32
  autorestart=true
33
  startsecs=3
@@ -160,7 +165,13 @@ stderr_logfile_maxbytes=0
160
  ; pipeline/hf_space_seed.py, same "don't exec uvicorn until every backend
161
  ; this process depends on is actually ready" rule the cpu-basic/NVCF
162
  ; variant already follows for OpenSearch.
163
- command=/usr/bin/env -u PYTHONPATH /bin/sh -c "until curl -sf http://localhost:8003/v2/health/ready >/dev/null 2>&1; do sleep 2; done; cd /app/hf-space-pipeline && /app/.venv/bin/python -m pipeline.hf_space_seed && cd /app && exec /app/.venv/bin/python -m uvicorn deepsearch_api.main:app --host 127.0.0.1 --port 8000 --workers \"${DEEPSEARCH_API_WORKERS:-1}\""
 
 
 
 
 
 
164
  directory=/app
165
  user=1000
166
  autorestart=true
@@ -170,6 +181,24 @@ stdout_logfile_maxbytes=0
170
  stderr_logfile=/dev/stderr
171
  stderr_logfile_maxbytes=0
172
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  [program:nginx]
174
  ; See docker/hf-space/supervisord.conf's own copy (identical command). Never put
175
  ; a space before a ";" or "#" in a command: supervisord reads it as an inline
 
27
  stderr_logfile_maxbytes=0
28
 
29
  [program:redis]
30
+ ; Holds only deepsearch-api's caches, all in DB 0 by key prefix: the VLM verdicts (usdsearch:vlmval:v1, no TTL,
31
+ ; capped at USDSEARCH_VISION_VALIDATION_CACHE_MAX_ENTRIES by the app's own LRU), the RRF page rankings behind
32
+ ; search cursors (usdsearch:rrfpage:v1, 15-min TTL) and the image-id resolutions (TTL). No indexing streams run
33
+ ; here. --maxmemory 6gb is a guard above the 4M verdicts (~1.8 GB); volatile-lru evicts only keys with a TTL,
34
+ ; the two caches a miss recomputes, never a verdict or an LRU index. Nothing is saved: a restart starts cold.
35
+ command=/usr/bin/redis-server --port 6379 --databases 32 --save "" --stop-writes-on-bgsave-error no --dir /tmp --maxmemory 6gb --maxmemory-policy volatile-lru
36
  user=1000
37
  autorestart=true
38
  startsecs=3
 
165
  ; pipeline/hf_space_seed.py, same "don't exec uvicorn until every backend
166
  ; this process depends on is actually ready" rule the cpu-basic/NVCF
167
  ; variant already follows for OpenSearch.
168
+ ; PROMETHEUS_MULTIPROC_DIR (emptied at every start): the workers share their
169
+ ; metrics through files there, so a counter is the sum over all workers;
170
+ ; [program:cache-metrics] reads its cache counters from them.
171
+ ; USDSEARCH_LLM_PARSING_CACHE_SIZE 0 (a Space variable overrides it): no
172
+ ; per-worker parse LRU. Its key has no date, so after midnight it answered
173
+ ; "made last week" with yesterday's parse; nginx caches parses per day instead.
174
+ command=/usr/bin/env -u PYTHONPATH /bin/sh -c "until curl -sf http://localhost:8003/v2/health/ready >/dev/null 2>&1; do sleep 2; done; cd /app/hf-space-pipeline && /app/.venv/bin/python -m pipeline.hf_space_seed && cd /app && rm -rf /tmp/deepsearch-api-prometheus && mkdir -p /tmp/deepsearch-api-prometheus && exec env PROMETHEUS_MULTIPROC_DIR=/tmp/deepsearch-api-prometheus USDSEARCH_LLM_PARSING_CACHE_SIZE=\"${USDSEARCH_LLM_PARSING_CACHE_SIZE:-0}\" /app/.venv/bin/python -m uvicorn deepsearch_api.main:app --host 127.0.0.1 --port 8000 --workers \"${DEEPSEARCH_API_WORKERS:-1}\""
175
  directory=/app
176
  user=1000
177
  autorestart=true
 
181
  stderr_logfile=/dev/stderr
182
  stderr_logfile_maxbytes=0
183
 
184
+ [program:cache-metrics]
185
+ ; The cache hit/miss counters Space members read at /metrics (nginx proxies it
186
+ ; to 127.0.0.1:8030): deepsearch-api's cache counters summed over its workers
187
+ ; (verdicts, rankings, image resolutions) and nginx's proxy-cache outcomes per
188
+ ; cache, which nginx sends here as one syslog datagram per request
189
+ ; (127.0.0.1:8031). Nothing else; a summary line goes to the log every 5 min.
190
+ ; See pipeline/cache_metrics.py.
191
+ ; env -u PYTHONPATH: the Triton base image's DALI wheel dir shadows the venv's typing_extensions.
192
+ command=/usr/bin/env -u PYTHONPATH /bin/sh -c "cd /app/hf-space-pipeline && exec /app/.venv/bin/python -m pipeline.cache_metrics"
193
+ directory=/app
194
+ user=1000
195
+ autorestart=true
196
+ startsecs=2
197
+ stdout_logfile=/dev/stdout
198
+ stdout_logfile_maxbytes=0
199
+ stderr_logfile=/dev/stderr
200
+ stderr_logfile_maxbytes=0
201
+
202
  [program:nginx]
203
  ; See docker/hf-space/supervisord.conf's own copy (identical command). Never put
204
  ; a space before a ";" or "#" in a command: supervisord reads it as an inline
docker/hf-space/supervisord.conf CHANGED
@@ -30,7 +30,12 @@ stderr_logfile=/dev/stderr
30
  stderr_logfile_maxbytes=0
31
 
32
  [program:redis]
33
- command=/usr/bin/redis-server --port 6379 --databases 32 --save "" --stop-writes-on-bgsave-error no --dir /tmp
 
 
 
 
 
34
  user=1000
35
  autorestart=true
36
  startsecs=3
@@ -178,7 +183,14 @@ stderr_logfile_maxbytes=0
178
  ; time. A seeding failure (e.g. no published run yet, or bad AWS creds)
179
  ; correctly counts as this program failing to start, same as any other
180
  ; startup error here.
181
- command=/bin/sh -c "cd /app/hf-space-pipeline && /app/.venv/bin/python -m pipeline.hf_space_seed && cd /app && exec /app/.venv/bin/python -m uvicorn deepsearch_api.main:app --host 127.0.0.1 --port 8000 --workers \"${DEEPSEARCH_API_WORKERS:-1}\""
 
 
 
 
 
 
 
182
  directory=/app
183
  user=1000
184
  autorestart=true
@@ -188,6 +200,23 @@ stdout_logfile_maxbytes=0
188
  stderr_logfile=/dev/stderr
189
  stderr_logfile_maxbytes=0
190
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
  [program:nginx]
192
  ; nginx is the *only* process bound to the externally-proxied port, and
193
  ; Hugging Face's own Space "ready" detection is just "does something answer
 
30
  stderr_logfile_maxbytes=0
31
 
32
  [program:redis]
33
+ ; Holds only deepsearch-api's caches, all in DB 0 by key prefix: the VLM verdicts (usdsearch:vlmval:v1, no TTL,
34
+ ; capped at USDSEARCH_VISION_VALIDATION_CACHE_MAX_ENTRIES by the app's own LRU), the RRF page rankings behind
35
+ ; search cursors (usdsearch:rrfpage:v1, 15-min TTL) and the image-id resolutions (TTL). No indexing streams run
36
+ ; here. --maxmemory 6gb is a guard above the 4M verdicts (~1.8 GB); volatile-lru evicts only keys with a TTL,
37
+ ; the two caches a miss recomputes, never a verdict or an LRU index. Nothing is saved: a restart starts cold.
38
+ command=/usr/bin/redis-server --port 6379 --databases 32 --save "" --stop-writes-on-bgsave-error no --dir /tmp --maxmemory 6gb --maxmemory-policy volatile-lru
39
  user=1000
40
  autorestart=true
41
  startsecs=3
 
183
  ; time. A seeding failure (e.g. no published run yet, or bad AWS creds)
184
  ; correctly counts as this program failing to start, same as any other
185
  ; startup error here.
186
+ ;
187
+ ; PROMETHEUS_MULTIPROC_DIR (emptied at every start): the workers share their
188
+ ; metrics through files there, so a counter is the sum over all workers;
189
+ ; [program:cache-metrics] reads its cache counters from them.
190
+ ; USDSEARCH_LLM_PARSING_CACHE_SIZE 0 (a Space variable overrides it): no
191
+ ; per-worker parse LRU. Its key has no date, so after midnight it answered
192
+ ; "made last week" with yesterday's parse; nginx caches parses per day instead.
193
+ command=/bin/sh -c "cd /app/hf-space-pipeline && /app/.venv/bin/python -m pipeline.hf_space_seed && cd /app && rm -rf /tmp/deepsearch-api-prometheus && mkdir -p /tmp/deepsearch-api-prometheus && exec env PROMETHEUS_MULTIPROC_DIR=/tmp/deepsearch-api-prometheus USDSEARCH_LLM_PARSING_CACHE_SIZE=\"${USDSEARCH_LLM_PARSING_CACHE_SIZE:-0}\" /app/.venv/bin/python -m uvicorn deepsearch_api.main:app --host 127.0.0.1 --port 8000 --workers \"${DEEPSEARCH_API_WORKERS:-1}\""
194
  directory=/app
195
  user=1000
196
  autorestart=true
 
200
  stderr_logfile=/dev/stderr
201
  stderr_logfile_maxbytes=0
202
 
203
+ [program:cache-metrics]
204
+ ; The cache hit/miss counters Space members read at /metrics (nginx proxies it
205
+ ; to 127.0.0.1:8030): deepsearch-api's cache counters summed over its workers
206
+ ; (verdicts, rankings, image resolutions) and nginx's proxy-cache outcomes per
207
+ ; cache, which nginx sends here as one syslog datagram per request
208
+ ; (127.0.0.1:8031). Nothing else; a summary line goes to the log every 5 min.
209
+ ; See pipeline/cache_metrics.py.
210
+ command=/bin/sh -c "cd /app/hf-space-pipeline && exec /app/.venv/bin/python -m pipeline.cache_metrics"
211
+ directory=/app
212
+ user=1000
213
+ autorestart=true
214
+ startsecs=2
215
+ stdout_logfile=/dev/stdout
216
+ stdout_logfile_maxbytes=0
217
+ stderr_logfile=/dev/stderr
218
+ stderr_logfile_maxbytes=0
219
+
220
  [program:nginx]
221
  ; nginx is the *only* process bound to the externally-proxied port, and
222
  ; Hugging Face's own Space "ready" detection is just "does something answer
pipeline/cache_metrics.py ADDED
@@ -0,0 +1,260 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Cache hit/miss counters for the Space's members, at /metrics.
2
+
3
+ The Space's caches are sized from a model (docs/hf-space-deployment.md, "Caches"); this program makes the hit rates
4
+ readable so the model can be checked. It runs under supervisord (program ``cache-metrics``) and serves ONE page,
5
+ ``GET http://127.0.0.1:8030/metrics``, which nginx proxies at ``/metrics`` (docker/hf-space/nginx.conf.template).
6
+ The page holds only these counters, in Prometheus' text format:
7
+
8
+ - deepsearch-api's cache counters, summed over its uvicorn workers. The deepsearch-api program runs with
9
+ ``PROMETHEUS_MULTIPROC_DIR=/tmp/deepsearch-api-prometheus`` (emptied at every start), so each worker writes its
10
+ metrics to files there; this reads the allow-listed families from them (``ALLOWED``): the VLM verdict cache's
11
+ lookups by outcome (``l1_hit`` in the worker, ``l2_hit`` in Redis, ``miss``) and its size, the rankings the API
12
+ keeps in Redis behind result cursors (every search still reaches the API), and the thumbnail id resolutions.
13
+ deepsearch-api's own /metrics (request paths, latencies, process data) stays private to the container.
14
+ - nginx's proxy-cache outcomes per cache (``slim_nginx_cache_requests_total{cache, status}``; status as nginx's
15
+ ``$upstream_cache_status``: HIT, MISS, EXPIRED, BYPASS, UPDATING, STALE, REVALIDATED). The caches are parses,
16
+ the Explorer's count probes, thumbnails and property stats; a user's search is never cached and never counted
17
+ here. nginx sends one syslog datagram per request of a cached route to 127.0.0.1:8031 carrying just
18
+ ``<cache> <status>``; no URL, query, body or header ever reaches this process.
19
+
20
+ Every ``CACHE_METRICS_LOG_SECONDS`` (300) it also prints one summary line to the log when anything changed. Nothing
21
+ is kept: a restart starts the counts at zero, as it does the caches. Standard library only, except the reader of
22
+ deepsearch-api's files (prometheus_client, from the Space venv): without it the page still carries nginx's counts
23
+ and says ``slim_deepsearch_metrics_available 0``.
24
+
25
+ It must not stay down: while nothing listens on the UDP port, nginx writes one "send() failed ... while logging to
26
+ syslog" line per cached request to /var/log/nginx/error.log. So it never exits on its own (a port it cannot bind is
27
+ retried every 5 s) and supervisord restarts it if it dies.
28
+ """
29
+
30
+ import os
31
+ import re
32
+ import socket
33
+ import threading
34
+ import time
35
+ from collections import defaultdict
36
+ from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
37
+ from typing import Dict, Iterable, List, Optional, Tuple
38
+
39
+ HOST = "127.0.0.1"
40
+ HTTP_PORT = int(os.environ.get("CACHE_METRICS_PORT", "8030"))
41
+ SYSLOG_PORT = int(os.environ.get("CACHE_METRICS_SYSLOG_PORT", "8031"))
42
+ PROM_DIR = os.environ.get("CACHE_METRICS_PROM_DIR", "/tmp/deepsearch-api-prometheus")
43
+ LOG_SECONDS = float(os.environ.get("CACHE_METRICS_LOG_SECONDS", "300"))
44
+
45
+ # deepsearch-api's metric families served here (multiprocess family names: a counter's without "_total"). All are
46
+ # labelled by `outcome` only; anything else in the files never leaves the container.
47
+ ALLOWED = {
48
+ "vlm_validation_cache_events": "counter",
49
+ "vlm_validation_cache_entries": "gauge",
50
+ "search_ranking_cache_events": "counter",
51
+ "image_resolution_cache_events": "counter",
52
+ }
53
+ # The caches nginx logs (nginx.conf.template's $slim_cache_route) and the statuses $upstream_cache_status takes.
54
+ ROUTES = ("parse", "count", "images", "stats")
55
+ STATUSES = ("HIT", "MISS", "EXPIRED", "STALE", "UPDATING", "REVALIDATED", "BYPASS")
56
+ _LINE = re.compile(r"slimcache: (\w+) ([A-Z]+|-)\s*$")
57
+
58
+
59
+ def parse_datagram(data: bytes) -> Optional[Tuple[str, str]]:
60
+ """``(cache, status)`` from one nginx syslog datagram, else None.
61
+
62
+ nginx sends ``<PRI>Mmm dd hh:mm:ss slimcache: <cache> <status>`` (``nohostname``). A request no cache saw
63
+ (status ``-``: a CORS preflight) and anything unexpected are dropped.
64
+ """
65
+ match = _LINE.search(data.decode("utf-8", "replace"))
66
+ if not match:
67
+ return None
68
+ route, status = match.groups()
69
+ if route not in ROUTES or status not in STATUSES:
70
+ return None
71
+ return route, status
72
+
73
+
74
+ class NginxCounts:
75
+ """Thread-safe ``{(cache, status): count}``."""
76
+
77
+ def __init__(self) -> None:
78
+ self._lock = threading.Lock()
79
+ self._counts: Dict[Tuple[str, str], int] = defaultdict(int)
80
+
81
+ def add(self, cache: str, status: str) -> None:
82
+ with self._lock:
83
+ self._counts[(cache, status)] += 1
84
+
85
+ def snapshot(self) -> Dict[Tuple[str, str], int]:
86
+ with self._lock:
87
+ return dict(self._counts)
88
+
89
+
90
+ def deepsearch_families(path: str) -> Optional[Dict[str, Dict[Tuple[Tuple[str, str], ...], float]]]:
91
+ """``{family: {labels: value}}`` for the ALLOWED families in deepsearch-api's multiprocess files, or None when
92
+ they cannot be read (no prometheus_client, no directory yet). Counters are summed over the workers (the
93
+ collector does it); the gauge is the same Redis count in every worker, so its per-process copies collapse to
94
+ their maximum."""
95
+ if not os.path.isdir(path):
96
+ return None
97
+ try:
98
+ from prometheus_client.multiprocess import MultiProcessCollector
99
+ except ImportError:
100
+ return None
101
+ out: Dict[str, Dict[Tuple[Tuple[str, str], ...], float]] = {}
102
+ try: # the constructor checks the directory again: deepsearch-api's restart may have just emptied it
103
+ metrics = list(MultiProcessCollector(None, path=path).collect())
104
+ except Exception as exc: # noqa: BLE001 - a worker mid-write or a removed file: say "unavailable", never crash
105
+ print(f"==> cache metrics: cannot read {path} ({type(exc).__name__}: {str(exc)[:200]})", flush=True)
106
+ return None
107
+ for metric in metrics:
108
+ kind = ALLOWED.get(metric.name)
109
+ if kind is None:
110
+ continue
111
+ values = out.setdefault(metric.name, {})
112
+ for sample in metric.samples:
113
+ if kind == "counter" and not sample.name.endswith("_total"):
114
+ continue # no _created in multiprocess mode; skip anything else a newer client might add
115
+ labels = tuple(sorted((k, v) for k, v in sample.labels.items() if k != "pid"))
116
+ if kind == "gauge":
117
+ values[labels] = max(values.get(labels, float("-inf")), sample.value)
118
+ else:
119
+ values[labels] = values.get(labels, 0.0) + sample.value
120
+ return out
121
+
122
+
123
+ def _labels(pairs: Iterable[Tuple[str, str]]) -> str:
124
+ body = ",".join(f'{k}="{_escape(v)}"' for k, v in pairs)
125
+ return "{" + body + "}" if body else ""
126
+
127
+
128
+ def _escape(value: str) -> str:
129
+ return value.replace("\\", "\\\\").replace("\n", "\\n").replace('"', '\\"')
130
+
131
+
132
+ def _number(value: float) -> str:
133
+ return str(int(value)) if float(value).is_integer() else repr(float(value))
134
+
135
+
136
+ def render(nginx: Dict[Tuple[str, str], int], families) -> str:
137
+ """The /metrics page (Prometheus text format 0.0.4)."""
138
+ lines: List[str] = [
139
+ "# HELP slim_nginx_cache_requests_total Requests to the Space's nginx proxy caches by cache and "
140
+ "$upstream_cache_status, since this process started.",
141
+ "# TYPE slim_nginx_cache_requests_total counter",
142
+ ]
143
+ for (cache, status), count in sorted(nginx.items()):
144
+ lines.append(f"slim_nginx_cache_requests_total{_labels([('cache', cache), ('status', status)])} {count}")
145
+ lines += [
146
+ "# HELP slim_deepsearch_metrics_available 1 when deepsearch-api's cache counters below were readable.",
147
+ "# TYPE slim_deepsearch_metrics_available gauge",
148
+ f"slim_deepsearch_metrics_available {0 if families is None else 1}",
149
+ ]
150
+ for name in sorted(families or {}):
151
+ kind = ALLOWED[name]
152
+ sample = f"{name}_total" if kind == "counter" else name
153
+ lines.append(f"# TYPE {sample} {kind}")
154
+ for labels, value in sorted(families[name].items()):
155
+ lines.append(f"{sample}{_labels(labels)} {_number(value)}")
156
+ return "\n".join(lines) + "\n"
157
+
158
+
159
+ def summary(nginx: Dict[Tuple[str, str], int], families) -> str:
160
+ """One log line: verdict outcomes and each nginx cache's statuses."""
161
+ parts = []
162
+ verdicts = (families or {}).get("vlm_validation_cache_events", {})
163
+ if verdicts:
164
+ by = {dict(labels).get("outcome", ""): value for labels, value in verdicts.items()}
165
+ total = sum(by.values())
166
+ hits = by.get("l1_hit", 0) + by.get("l2_hit", 0)
167
+ parts.append("verdicts " + " ".join(f"{k}={_number(v)}" for k, v in sorted(by.items()))
168
+ + (f" (hit {100 * hits / total:.1f}%)" if total else ""))
169
+ ranking = (families or {}).get("search_ranking_cache_events", {})
170
+ if ranking:
171
+ parts.append("rankings " + " ".join(f"{dict(k).get('outcome', '')}={_number(v)}"
172
+ for k, v in sorted(ranking.items())))
173
+ for cache in ROUTES:
174
+ counts = {status: n for (c, status), n in nginx.items() if c == cache}
175
+ if counts:
176
+ total = sum(counts.values())
177
+ parts.append(f"nginx {cache} " + " ".join(f"{s}={n}" for s, n in sorted(counts.items()))
178
+ + f" (hit {100 * counts.get('HIT', 0) / total:.1f}%)")
179
+ if not parts:
180
+ return ""
181
+ if families is None:
182
+ parts.append("deepsearch-api counters unavailable")
183
+ return "==> cache metrics: " + " | ".join(parts)
184
+
185
+
186
+ def serve_syslog(counts: NginxCounts, sock: socket.socket) -> None:
187
+ while True:
188
+ data, _ = sock.recvfrom(4096)
189
+ parsed = parse_datagram(data)
190
+ if parsed:
191
+ counts.add(*parsed)
192
+
193
+
194
+ def make_handler(counts: NginxCounts, prom_dir: str):
195
+ class Handler(BaseHTTPRequestHandler):
196
+ def do_GET(self) -> None: # noqa: N802 - http.server's name
197
+ if self.path.split("?", 1)[0] != "/metrics":
198
+ self.send_error(404)
199
+ return
200
+ body = render(counts.snapshot(), deepsearch_families(prom_dir)).encode()
201
+ self.send_response(200)
202
+ self.send_header("Content-Type", "text/plain; version=0.0.4; charset=utf-8")
203
+ self.send_header("Content-Length", str(len(body)))
204
+ self.send_header("Cache-Control", "no-store")
205
+ self.end_headers()
206
+ self.wfile.write(body)
207
+
208
+ def log_message(self, *args) -> None: # one line per scrape would drown the Space log
209
+ pass
210
+
211
+ return Handler
212
+
213
+
214
+ def log_loop(counts: NginxCounts, prom_dir: str, every: float) -> None:
215
+ last = None
216
+ while True:
217
+ time.sleep(every)
218
+ nginx, families = counts.snapshot(), deepsearch_families(prom_dir)
219
+ state = (sorted(nginx.items()), repr(families))
220
+ line = summary(nginx, families)
221
+ if line and state != last:
222
+ print(line, flush=True)
223
+ last = state
224
+
225
+
226
+ def bind(make, what: str):
227
+ """``make()``, retried every 5 s while the port is taken: exiting would leave nginx logging errors."""
228
+ while True:
229
+ try:
230
+ return make()
231
+ except OSError as exc:
232
+ print(f"==> cache metrics: cannot bind {what} ({exc}), trying again in 5 s", flush=True)
233
+ time.sleep(5)
234
+
235
+
236
+ def udp_socket() -> socket.socket:
237
+ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
238
+ try:
239
+ sock.bind((HOST, SYSLOG_PORT))
240
+ except OSError:
241
+ sock.close()
242
+ raise
243
+ return sock
244
+
245
+
246
+ def main() -> None:
247
+ counts = NginxCounts()
248
+ udp = bind(udp_socket, f"udp {HOST}:{SYSLOG_PORT}")
249
+ server = bind(lambda: ThreadingHTTPServer((HOST, HTTP_PORT), make_handler(counts, PROM_DIR)),
250
+ f"http {HOST}:{HTTP_PORT}")
251
+ threading.Thread(target=serve_syslog, args=(counts, udp), daemon=True).start()
252
+ if LOG_SECONDS > 0:
253
+ threading.Thread(target=log_loop, args=(counts, PROM_DIR, LOG_SECONDS), daemon=True).start()
254
+ print(f"==> cache metrics: http://{HOST}:{HTTP_PORT}/metrics, nginx syslog on udp {HOST}:{SYSLOG_PORT}, "
255
+ f"deepsearch-api files in {PROM_DIR}", flush=True)
256
+ server.serve_forever()
257
+
258
+
259
+ if __name__ == "__main__":
260
+ main()
pipeline/config.py CHANGED
@@ -400,9 +400,10 @@ class Config:
400
  "USDSEARCH_VISION_VALIDATION_LOGPROB_ASSET_FACTS": json.dumps(["path", "vlm_metadata_caption"]),
401
  "USDSEARCH_VISION_VALIDATION_LOGPROB_ASSET_PATH_ROOTS": json.dumps(VALIDATION_ASSET_PATH_ROOTS),
402
  "USDSEARCH_VISION_VALIDATION_LOGPROB_IMAGE_TEXT_QUERY": "true",
403
- # The Redis verdict cache (on: REDIS_URL is set) holds 250k verdicts (~0.5 GB); the Space's Redis
404
- # has no maxmemory.
405
- "USDSEARCH_VISION_VALIDATION_CACHE_MAX_ENTRIES": "250000",
 
406
  }
407
 
408
  # ── VLM metadata extraction from thumbnails (indexing-time plugin) ──────
 
400
  "USDSEARCH_VISION_VALIDATION_LOGPROB_ASSET_FACTS": json.dumps(["path", "vlm_metadata_caption"]),
401
  "USDSEARCH_VISION_VALIDATION_LOGPROB_ASSET_PATH_ROOTS": json.dumps(VALIDATION_ASSET_PATH_ROOTS),
402
  "USDSEARCH_VISION_VALIDATION_LOGPROB_IMAGE_TEXT_QUERY": "true",
403
+ # The Redis verdict cache (on: REDIS_URL is set) holds 4M verdicts: ~1.8 GB at the measured 463 B
404
+ # each, and 2-3 h of history at 100 users (250k held ~9 min). The Space's Redis caps itself at
405
+ # 6 GB (--maxmemory, volatile-lru: verdicts carry no TTL, so Redis never evicts them).
406
+ "USDSEARCH_VISION_VALIDATION_CACHE_MAX_ENTRIES": "4000000",
407
  }
408
 
409
  # ── VLM metadata extraction from thumbnails (indexing-time plugin) ──────
services/explorer/dist/build-info.json CHANGED
@@ -1,7 +1,7 @@
1
  {
2
  "product": "simready-central-slim-explorer",
3
- "version": "slim-ui-35349654",
4
- "bundle_id": "main.bba919cb.js",
5
- "built_at": "2026-10-15T15:34:28Z",
6
  "flags": {"public_mode": true, "email_auth": false, "create_ui": false, "hierarchy_editor": false, "create_search": false, "auth_ui": false, "credentials_ui": false, "index_management": false, "inference_backend": "hub", "vlm_asset_refs": false, "validation_image_max_px": 448, "validation_max_retries": 0, "validation_max_concurrent": 32, "validation_tail_concurrent": 8, "validation_eager_count": 50, "validation_batch_stream": true, "library_idle_prefetch": false, "validation_score_scale": "percent", "parse_gate_fields": true, "parse_fast_path": true, "featured_landing": true, "hf_download_commands": true, "dependency_views": true, "model_viewer": false, "library_viewer": true, "library_media": "runtime", "spell_correction": false, "downloads": "runtime", "submit_content": "runtime", "third_party_notices": "runtime"}
7
  }
 
1
  {
2
  "product": "simready-central-slim-explorer",
3
+ "version": "slim-ui-9d95b298",
4
+ "bundle_id": "main.846b9fc7.js",
5
+ "built_at": "2026-10-15T18:17:42Z",
6
  "flags": {"public_mode": true, "email_auth": false, "create_ui": false, "hierarchy_editor": false, "create_search": false, "auth_ui": false, "credentials_ui": false, "index_management": false, "inference_backend": "hub", "vlm_asset_refs": false, "validation_image_max_px": 448, "validation_max_retries": 0, "validation_max_concurrent": 32, "validation_tail_concurrent": 8, "validation_eager_count": 50, "validation_batch_stream": true, "library_idle_prefetch": false, "validation_score_scale": "percent", "parse_gate_fields": true, "parse_fast_path": true, "featured_landing": true, "hf_download_commands": true, "dependency_views": true, "model_viewer": false, "library_viewer": true, "library_media": "runtime", "spell_correction": false, "downloads": "runtime", "submit_content": "runtime", "third_party_notices": "runtime"}
7
  }
services/explorer/dist/index.html CHANGED
@@ -1 +1 @@
1
- <!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/ds.png"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="SimReady Central — SimReady asset search"/><meta name="ui-version" content="slim-ui-35349654"><script src="/config.js"></script><title>SimReady Central</title><script defer="defer" src="/static/js/main.bba919cb.js"></script><link href="/static/css/main.01671ca7.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
 
1
+ <!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/ds.png"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="SimReady Central — SimReady asset search"/><meta name="ui-version" content="slim-ui-9d95b298"><script src="/config.js"></script><title>SimReady Central</title><script defer="defer" src="/static/js/main.846b9fc7.js"></script><link href="/static/css/main.01671ca7.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
services/explorer/dist/static/js/298.4bcf08c3.chunk.js ADDED
@@ -0,0 +1 @@
 
 
1
+ "use strict";(self.webpackChunkdeepsearch_ui=self.webpackChunkdeepsearch_ui||[]).push([[298],{298(e,t,o){o.r(t),o.d(t,{COLLIDERS_LAYER:()=>_,HD_LAYER:()=>A,LOCAL:()=>k,NORMAL_MODES:()=>ie,OPENPBR_CORE_MAPS:()=>J,OPENPBR_EXT_MAPS:()=>Y,READER_TEXTURES:()=>P,RECYCLE_BYTES:()=>U,ROOT_KEY:()=>x,ROOT_LAYER:()=>S,SLOTS:()=>G,WARM_KEY:()=>L,WebUsdError:()=>R,_readerState:()=>De,_resetWebUsdReader:()=>ze,colorSpaceOf:()=>X,compactRecord:()=>Z,compactThickness:()=>ae,expected:()=>We,fallbackWarning:()=>ve,fileKey:()=>N,flipV:()=>$,geometryArrays:()=>le,isWebUsdError:()=>O,loadWebUsd:()=>Fe,lowBitLog2:()=>ee,mapUrl:()=>z,materialGaps:()=>ge,materialParams:()=>ye,openpbrOnly:()=>fe,physicsResult:()=>Te,pieceOf:()=>W,planHints:()=>D,quantizeLattice:()=>se,roleOf:()=>K,rootLayerText:()=>j,setWebUsdReader:()=>_e,siblingUrl:()=>F,snormNormals:()=>re,tierLayers:()=>T,uvDequant:()=>ne,uvMatrix:()=>de,warmWebUsdReader:()=>Ce,webUsdReaderFailure:()=>C,webUsdReaderSet:()=>xe});var s=o(986),r=o(379),n=o(1);const a="/Asset",i="".concat(a,"/Bodies"),l="".concat(a,"/Joints"),c=["simready"],u={version:1,frame:"gltf",units:{length:"m",angle:"deg",mass:"kg"}},d={kind:["simready:kind",!1],sequence:["simready:sequence",!1],order:["simready:order",!1],fixed_base:["simready:fixedBase",!1],static_reason:["simready:staticReason",!1],poses:["simready:poses",!0],pose_problems:["simready:poseProblems",!0],physics_variants:["simready:physicsVariants",!0],selftest:["simready:selftest",!0]},p={PhysicsRevoluteJoint:"revolute",PhysicsPrismaticJoint:"prismatic",PhysicsFixedJoint:"fixed"},m=new Set(["revolute","prismatic"]),h=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),f=e=>String(e).split("/").pop(),y=e=>String(e).slice(0,String(e).lastIndexOf("/"));function v(e){const[t,o,s,r]=e.map(Number);return[1-2*(s*s+r*r),2*(o*s+t*r),2*(o*r-t*s)]}function g(e,t){if(!e)throw new Error("webUsdPhysics: ".concat(t))}function b(e){const t=(0,r.A)({},(null===e||void 0===e?void 0:e.attributes)||{});for(const[o,s]of Object.entries((null===e||void 0===e?void 0:e.unreadable)||{}))g("string[]"===s,"".concat(e.path,".").concat(o,": the reader could not read it (").concat(s||"no type",")")),t[o]=[];return t}function w(e,t){const o=p[e.type];g(o,"".concat(e.path,": not a joint of the profile (").concat(e.type,")"));const s=b(e),r=e.relationships||{},n=new Set(e.apiSchemas||[]),a={};for(const[p,m]of Object.entries(s))!p.startsWith("physics:")&&!p.startsWith("simready:")||p.startsWith("physics:body")||p.startsWith("drive:")||(a[p]=m);const i={};for(const[p,m]of Object.entries(r))p.startsWith("simready:")&&(i[p]=m.map(f));const l=e=>r[e]&&r[e].length?f(r[e][0]):null;let c=null;for(const p of["angular","linear"]){var u,d;if(!n.has("PhysicsDriveAPI:".concat(p)))continue;const e=e=>s["drive:".concat(p,":physics:").concat(e)],t="drive:".concat(p,":physics:maxForce");c={stiffness:null!==(u=e("stiffness"))&&void 0!==u?u:0,damping:null!==(d=e("damping"))&&void 0!==d?d:0,maxForce:h(s,t)?s[t]:null}}const y={id:f(e.path),type:o,body0:l("physics:body0"),body1:l("physics:body1"),label:h(a,"simready:label")?a["simready:label"]:null};t&&h(a,"simready:name")&&(y.name=a["simready:name"]),h(a,"simready:lockedFrom")&&(y.locked_from=a["simready:lockedFrom"]);const w=e=>h(a,e)?a[e]:null;if(m.has(o)){const t=h(a,"simready:rest")?a["simready:rest"]:0;g(Array.isArray(a["physics:localRot0"]),"".concat(e.path,": no physics:localRot0")),g(Array.isArray(a["physics:localPos0"]),"".concat(e.path,": no physics:localPos0"));const o=e=>"number"===typeof a[e]?a[e]+t:null;if(Object.assign(y,{axis:v(a["physics:localRot0"]),pivot:[...a["physics:localPos0"]],unit:w("simready:unit"),lower:o("physics:lowerLimit"),upper:o("physics:upperLimit"),rest:w("simready:rest"),home:w("simready:home"),far:w("simready:far"),partial:w("simready:partial"),drive:null}),c){const e=c.stiffness||0,t=c.damping||0,o=c.maxForce;y.drive={type:e>0?"position":t>0?"velocity":"none",stiffness:e,damping:t,max_force:"number"===typeof o&&Number.isFinite(o)?o:null}}h(a,"simready:range")&&(y.range=[...a["simready:range"]]);for(const e of["mimic","coupled"])h(i,"simready:".concat(e,"Of"))&&(y[e]={of:i["simready:".concat(e,"Of")][0],gearing:a["simready:".concat(e,"Gearing")],offset:a["simready:".concat(e,"Offset")]},"coupled"===e&&(y[e].source=w("simready:coupledSource")));h(a,"simready:loop")&&(y.loop=JSON.parse(a["simready:loop"])),a["physics:excludeFromArticulation"]&&(y.closes=!0)}let M=null;if(h(a,"simready:tree")){const t=i["simready:treeParent"]&&i["simready:treeParent"].length?i["simready:treeParent"]:[null];g(i["simready:treeChild"]&&i["simready:treeChild"].length,"".concat(e.path,": no simready:treeChild")),M=[a["simready:tree"],{joint:y.id,parent:t[0],child:i["simready:treeChild"][0],inverse:!!a["simready:treeInverse"]}]}return{row:y,tree:M}}const M=["warnings"],S="asset.usdc",A="hd.usdc",_="colliders.usdc",x="simready-web.usda",L="simready-warm.usda",k="local:///",U=268435456,P="none";class R extends Error{constructor(e,t){let{cause:o,url:s,status:r,fatal:n}=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};super(t),this.name="WebUsdError",this.code=e,void 0!==o&&(this.cause=o),void 0!==s&&(this.url=s),void 0!==r&&(this.status=r),n&&(this.fatal=!0)}}const O=e=>e instanceof R;let B=null;function E(e,t){let o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return B=new R(e,t,(0,r.A)((0,r.A)({},o),{},{fatal:!0})),B}const C=()=>B,I=/\/Bodies\/(b\d+)\/(?:lo|hd)\/(m\d+)$/;function W(e){const t=I.exec(e||"");return t?{body:t[1],name:t[1]+t[2]}:null}function j(){const e=2===(arguments.length>0&&void 0!==arguments[0]?arguments[0]:1)?"full":"preview";return["#usda 1.0","(",' defaultPrim = "Asset"'," metersPerUnit = 1",' upAxis = "Y"'," subLayers = ["," @./".concat(S,"@")," ]",")","",'over "Asset" ('," variants = {",' string lod = "'.concat(e,'"'),' string textures = "web"'," }",")","{","}",""].join("\n")}const T=function(){return 2===(arguments.length>0&&void 0!==arguments[0]?arguments[0]:1)?[S,A]:[S]},N=e=>String(e).split(/[?#]/)[0];function F(e,t){const o=new URL(e,t);return o.search||(o.search=new URL(t).search),o.href}function z(e,t){return String(e).startsWith(k)?F(String(e).slice(k.length).replace(/^\/+/,""),t):new URL(e,t).href}function D(e,t){const o=new Map;for(const s of e||[]){if("string"!==typeof s||!s.trim())continue;const e=F(s.trim(),t),r=N(e);o.has(r)||o.set(r,e)}return o}const G={diffuseColor:"map",emissiveColor:"emissiveMap",roughness:"roughnessMap",metallic:"metalnessMap",occlusion:"aoMap",opacity:"alphaMap",normal:"normalMap"},q={map:"rgb",emissiveMap:"rgb",roughnessMap:"g",metalnessMap:"b",aoMap:"r",alphaMap:"g",normalMap:"rgb",transmissionMap:"r",clearcoatMap:"r",clearcoatRoughnessMap:"g",clearcoatNormalMap:"rgb",specularIntensityMap:"a",specularColorMap:"rgb",sheenColorMap:"rgb",sheenRoughnessMap:"a"},J={base_color:"map",base_metalness:"metalnessMap",specular_roughness:"roughnessMap",geometry_normal:"normalMap",emission_color:"emissiveMap",geometry_opacity:"alphaMap"},Y={transmission_weight:"transmissionMap",coat_weight:"clearcoatMap",coat_roughness:"clearcoatRoughnessMap",geometry_coat_normal:"clearcoatNormalMap",specular_weight:"specularIntensityMap",specular_color:"specularColorMap",fuzz_color:"sheenColorMap",fuzz_roughness:"sheenRoughnessMap"},H=new Set(["map","emissiveMap","sheenColorMap","specularColorMap"]),K=e=>H.has(e)?"color":"data",X=e=>"color"===e?"srgb":"",V=(e,t)=>Math.abs(e-t)<1e-6,Q={r:0,g:1,b:2,a:3};function $(e){for(let t=1;t<e.length;t+=2)e[t]=1-e[t];return e}function Z(e,t){var o,s;if(!0===e)return!0;if(Array.isArray(e))return 3===e.length&&e.every(e=>Number.isInteger(e)&&e>0);if(e&&"object"===typeof e)return!!e.bits||Number.isInteger(e.points_log2);let r=null===t||void 0===t||null===(o=t.customLayerData)||void 0===o||null===(s=o.simready)||void 0===s?void 0:s.tiers;if("string"===typeof r)try{r=JSON.parse(r)}catch(n){r=null}return!(!r||"object"!==typeof r||!r.compact)}function ee(e){const t=new Uint32Array(e.buffer,e.byteOffset,e.length);let o=1/0;for(let s=0;s<t.length;s+=1){const e=t[s];if(0===(2147483647&e)){if(0!==e)return null;continue}const r=e>>>23&255;if(255===r)return null;const n=r?8388607&e|8388608:8388607&e,a=(r||1)-150+(31-Math.clz32(n&-n));a<o&&(o=a)}return o===1/0?0:o}const te=[-32768,32767],oe=[0,65535];function se(e,t){let o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t;const s=e.length/t;if(!(s>0)||!Number.isInteger(s))return null;const r=ee(e);if(null===r)return null;const n=2**-r,a=new Array(t).fill(1/0),i=new Array(t).fill(-1/0);for(let m=0,h=0;m<s;m+=1)for(let o=0;o<t;o+=1,h+=1){const t=e[h]*n;t<a[o]&&(a[o]=t),t>i[o]&&(i[o]=t)}const l=Math.min(...a),c=Math.max(...i);let u=null,d=new Array(t).fill(0);if(l>=te[0]&&c<=te[1])u=Int16Array;else if(l>=oe[0]&&c<=oe[1])u=Uint16Array;else{if(!a.every((e,t)=>i[t]-e<=oe[1]))return null;u=Uint16Array,d=a.slice()}const p=new u(s*o);for(let m=0,h=0;m<s;m+=1)for(let s=0;s<t;s+=1,h+=1)p[m*o+s]=e[h]*n-d[s];return{array:p,k:r,offset:d,min:a.map((e,t)=>e-d[t]),max:i.map((e,t)=>e-d[t])}}function re(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:8;const o=16===t?Int16Array:Int8Array,s=16===t?32767:127,r=e.length/3,n=new o(4*r);for(let a=0;a<r;a+=1)for(let t=0;t<3;t+=1){const o=Math.max(-1,Math.min(1,e[3*a+t]||0));n[4*a+t]=Math.sign(o)*Math.floor(Math.abs(o)*s+.5)}return n}const ne=e=>{let{k:t,offset:o}=e;const s=2**t;return[s,0,o[0]*s,0,s,o[1]*s,0,0,1].map(e=>e+0)},ae=(e,t)=>e/2**t,ie={int8:8,int16:16,float:0};function le(e,t){let o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"int8";const s=(e.uvs||[]).map($),r=e=>e?(e.array||e).byteLength:0,n=r(e.positions)+r(e.normals)+s.reduce((e,t)=>e+t.byteLength,0),a={position:e.positions,normal:e.normals,uvs:s.slice(),positionLattice:null,uvLattice:null};if(t){var i;a.positionLattice=se(e.positions,3,4),a.positionLattice&&(a.position=a.positionLattice);const t=null!==(i=ie[o])&&void 0!==i?i:8;t&&e.normals&&(a.normal={array:re(e.normals,t),bits:t}),s[0]&&(a.uvLattice=se(s[0],2,2),a.uvLattice&&(a.uvs[0]=a.uvLattice))}return a.bytes={float:n,upload:r(a.position)+r(a.normal)+a.uvs.reduce((e,t)=>e+r(t),0)},a}const ce=(e,t)=>[0,1,2].flatMap(o=>[0,1,2].map(s=>e[3*o]*t[s]+e[3*o+1]*t[3+s]+e[3*o+2]*t[6+s])),ue=[1,0,0,0,-1,1,0,0,1];function de(e){const[t,o]=(null===e||void 0===e?void 0:e.uvScale)||[1,1],[s,r]=(null===e||void 0===e?void 0:e.uvTranslation)||[0,0],n=((null===e||void 0===e?void 0:e.uvRotation)||0)*Math.PI/180;if(1===t&&1===o&&0===s&&0===r&&0===n)return null;const a=Math.cos(n),i=Math.sin(n);return ce(ce(ue,[a*t,-i*o,s,i*t,a*o,r,0,0,1]),ue).map(e=>e+0)}const pe={mirror:"mirror",clamp:"clamp",black:"clamp"},me={specular_weight:"specularIntensity",specular_color:"specularColor",specular_ior:"ior",transmission_weight:"transmission",transmission_color:"attenuationColor",transmission_depth:"attenuationDistance",coat_weight:"clearcoat",coat_roughness:"clearcoatRoughness",fuzz_color:"sheenColor",fuzz_roughness:"sheenRoughness",specular_roughness_anisotropy:"anisotropy"},he={base_weight:1,base_color:[.8,.8,.8],base_metalness:0,specular_roughness:.3,geometry_opacity:1,emission_color:[1,1,1]},fe=e=>"fallback"===(null===e||void 0===e?void 0:e.kind)&&!(null===e||void 0===e||!e.openpbr);function ye(e){var t,o,s,r;const n=e&&e.openpbr||{},a=e&&e.simready||{},i=e&&e.maps||{},l={name:(null===e||void 0===e?void 0:e.path)||"",color:[...(null===e||void 0===e?void 0:e.color)||[1,1,1]],opacity:null!==(t=null===e||void 0===e?void 0:e.opacity)&&void 0!==t?t:1,roughness:null!==(o=null===e||void 0===e?void 0:e.roughness)&&void 0!==o?o:1,metalness:null!==(s=null===e||void 0===e?void 0:e.metallic)&&void 0!==s?s:1,emissive:[...(null===e||void 0===e?void 0:e.emissive)||[0,0,0]],emissiveIntensity:1,alphaMode:"OPAQUE",alphaTest:0,transparent:!1,depthWrite:!0,doubleSided:null,normalScale:1,aoMapIntensity:1,physical:{},maps:{},gaps:[]},c=(e,t)=>{l.maps[e]={path:t.path,role:K(e),wrap:[pe[t.wrapS]||"repeat",pe[t.wrapT]||"repeat"],matrix:de(t)};const o=q[e];o&&t.channel!==o&&l.gaps.push("".concat(e," reads ").concat(t.channel,", three samples ").concat(o))},u=e=>e.channel in Q?e.scale[Q[e.channel]]:e.scale[0],d=i.diffuseColor;let p=!1;for(const[b,w]of Object.entries(i)){const t=G[b];t&&w&&w.path?(w.uvSet&&"st"!==w.uvSet&&l.gaps.push("".concat(b," samples primvar ").concat(w.uvSet,", not st")),"diffuseColor"===b?(l.color=[0,1,2].map(t=>{var o,s;return(null!==(o=null===(s=e.color)||void 0===s?void 0:s[t])&&void 0!==o?o:1)*w.scale[t]}),c(t,w)):"emissiveColor"===b?(l.emissive=[0,1,2].map(e=>w.scale[e]),c(t,w)):"roughness"===b?(l.roughness=u(w),c(t,w)):"metallic"===b?(l.metalness=u(w),c(t,w)):"occlusion"===b?(l.aoMapIntensity=u(w),c(t,w)):"normal"===b?(V(w.scale[0],2)&&V(w.bias[0],-1)||l.gaps.push("normal map not at scale 2 / bias -1"),c(t,w)):"opacity"===b&&(p=!0,l.opacity=u(w),d&&d.path===w.path&&"a"===w.channel||c(t,w)),"normal"!==b&&"occlusion"!==b&&w.bias&&w.bias.some(e=>!V(e,0))&&l.gaps.push("".concat(b," has a bias"))):l.gaps.push("".concat(b,": no three.js map"))}const m=fe(e),h=new Set(e&&e.openpbrTextured||[]),f=e&&e.openpbrMaps||{},y=new Set,v=(e,t)=>{var o;const s=f[e];s&&s.path&&(s.uvSet&&"st"!==s.uvSet&&l.gaps.push("".concat(e," samples ").concat(s.uvSet,", not st")),s.unsupported&&l.gaps.push("".concat(e,": ").concat(s.unsupported)),y.add(e),"alphaMap"===t&&"a"===s.channel&&(null===(o=f.base_color)||void 0===o?void 0:o.path)===s.path||c(t,s))};if(m){const t=(e,t)=>t(n[e])?n[e]:he[e],o=e=>"number"===typeof e,s=e=>Array.isArray(e)&&3===e.length,r=t("base_weight",o);l.color=t("base_color",s).map(e=>e*r),l.metalness=t("base_metalness",o),l.roughness=t("specular_roughness",o),l.opacity=t("geometry_opacity",o);const a=void 0!==n.emission_color||n.emission_luminance>0;l.emissive=a?[...t("emission_color",s)]:[0,0,0],p=h.has("geometry_opacity");for(const[e,n]of Object.entries(J))v(e,n);for(const e of h)Object.hasOwn(he,e)&&!y.has(e)&&l.gaps.push("".concat(e,": its map is not read (factor only)"));"number"!==typeof e.normalScale||y.has("geometry_normal")||l.gaps.push("geometry_normal: its map is not read")}for(const[b,w]of Object.entries(Y))v(b,w);l.alphaMode=a.alphaMode||((null===e||void 0===e?void 0:e.opacityThreshold)>0?"MASK":p||l.opacity<1?"BLEND":"OPAQUE"),"MASK"===l.alphaMode&&(l.alphaTest=null!==(r=a.alphaCutoff)&&void 0!==r?r:(null===e||void 0===e?void 0:e.opacityThreshold)>0?e.opacityThreshold:.5),"BLEND"===l.alphaMode&&(l.transparent=!0,l.depthWrite=!1),"boolean"===typeof a.doubleSided&&(l.doubleSided=a.doubleSided),"number"===typeof(null===e||void 0===e?void 0:e.normalScale)&&(l.normalScale=e.normalScale),"number"===typeof a.occlusionStrength&&(l.aoMapIntensity=a.occlusionStrength);for(const[b,w]of Object.entries(me))void 0!==n[b]&&(l.physical[w]=n[b]);for(const b of h)me[b]&&!y.has(b)&&l.gaps.push("".concat(b,": its map is not read (factor only)"));n.fuzz_weight>0&&(l.physical.sheen=1),"number"===typeof a.thickness&&(l.physical.thickness=a.thickness),n.geometry_thin_walled&&(l.physical.thickness=0),"number"===typeof a.anisotropyRotation&&(l.physical.anisotropyRotation=a.anisotropyRotation);const g=n.emission_luminance;return"number"===typeof g&&g>0&&(l.emissiveIntensity=g,m||(l.emissive=l.emissive.map(e=>e/g))),l}function ve(e){const t=(e||[]).filter(e=>"fallback"===(null===e||void 0===e?void 0:e.kind)&&e.path&&!fe(e));return t.length?{code:"material-fallback",path:t[0].path,message:"".concat(t.length," material(s) have no ")+"UsdPreviewSurface, OpenPBR surface or supported MDL material and show as grey"}:null}function ge(e){var t;const o=[];return null!==e&&void 0!==e&&e.openpbr||o.push("openpbr: specular weight/colour, ior, transmission, coat, fuzz, anisotropy, emission luminance"),null!==e&&void 0!==e&&e.simready||o.push("simready: alphaMode, alphaCutoff, doubleSided, occlusionStrength, thickness, anisotropyRotation"),"number"!==typeof(null===e||void 0===e?void 0:e.normalScale)&&null!==e&&void 0!==e&&null!==(t=e.maps)&&void 0!==t&&t.normal&&o.push("normal scale"),o}let be=null,we=null,Me=null,Se=null,Ae=0;function _e(e){Se&&Pe(Se),Se=null,we=null,Me=null,be=e||null}const xe=()=>!!be,Le=function(e,t){let o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return new R("fetch","webUsdLoader: the reader's WASM did not load: ".concat(t),(0,r.A)({url:String(e)},o))};function ke(){if(!be)return Promise.reject(new R("reader","webUsdLoader: no reader set"));if(!we){const e=performance.now(),t=be,o=Promise.resolve().then(()=>t.compile?t.compile():async function(e){let t;try{const o=await fetch(e);if(!o.ok)throw Le(e,"HTTP ".concat(o.status),{status:o.status});t=await o.arrayBuffer()}catch(o){throw O(o)?o:Le(e,(null===o||void 0===o?void 0:o.message)||String(o),{cause:o})}if(!(0,n.Hr)(t))throw new Error("not WebAssembly (a page served in its place?)");return WebAssembly.compile(t)}(t.wasmUrl)).then(t=>(Me=performance.now()-e,t)).catch(e=>{if(O(e)&&"fetch"===e.code)throw e;throw E("reader","webUsdLoader: could not compile the reader's WASM: ".concat((null===e||void 0===e?void 0:e.message)||e),{cause:e,url:t.wasmUrl&&String(t.wasmUrl)})});o.catch(()=>{we===o&&(we=null)}),we=o}return we}function Ue(){let e;try{e=be.createWorker?be.createWorker():new Worker(be.workerUrl,{type:"module"})}catch(t){throw E("reader","webUsdLoader: could not start the reader's worker: ".concat((null===t||void 0===t?void 0:t.message)||t),{cause:t})}return Ae+=1,{worker:e,dead:!1,ready:Promise.resolve(!0)}}function Pe(e){e&&!e.dead&&(e.dead=!0,e.worker.onmessage=null,e.worker.onerror=null,e.worker.terminate())}const Re={fetch:"fetch",compose:"compose",aborted:"aborted",worker:"reader"};function Oe(e,t,o,s){let r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{};return new Promise((n,a)=>{const{worker:i}=e;let l=0,c=!1;r.posted=!1;const u=t=>{c||(c=!0,null===s||void 0===s||s.removeEventListener("abort",d),i.onmessage=null,i.onerror=null,t?(r.posted&&Pe(e),a(t)):n(l))};function d(){u(new R("aborted","webUsdLoader: the load was aborted",{url:t.url}))}if(null!==s&&void 0!==s&&s.aborted)d();else{null===s||void 0===s||s.addEventListener("abort",d,{once:!0}),i.onmessage=e=>{var t,s,r;let{data:n}=e;if(!c&&n)if("texture"===n.type&&(null===(t=n.bitmap)||void 0===t||null===(s=t.close)||void 0===s||s.call(t)),"scene"===n.type&&(l=(null===(r=n.stats)||void 0===r?void 0:r.wasmMemoryBytes)||0),"done"!==n.type)if("error"!==n.type)try{o(n)}catch(a){u(O(a)?a:new R("compose","webUsdLoader: could not build the scene: ".concat((null===a||void 0===a?void 0:a.message)||a),{cause:a}))}else u(new R(Re[n.code]||"compose","webUsdLoader: ".concat(n.message),{url:n.url,status:n.status}));else u(null)},i.onerror=e=>{var o;null===e||void 0===e||null===(o=e.preventDefault)||void 0===o||o.call(e),(e=>!(!e||!(e.message||e.filename||e.error)))(e)?u(E("reader","webUsdLoader: the reader's worker failed: ".concat((null===e||void 0===e?void 0:e.message)||"error"))):u(new R("fetch","webUsdLoader: the reader's worker did not load its script",{url:t.url}))};try{i.postMessage(t),r.posted=!0}catch(p){u(new R("reader","webUsdLoader: could not post to the reader's worker: ".concat((null===p||void 0===p?void 0:p.message)||p),{cause:p}))}}})}function Be(e,t){e.dead||(Se||t>U?Pe(e):Se=e)}let Ee=null;function Ce(){if(!be)return Promise.resolve(!1);if(Se){const e=Se;return e.ready.then(t=>t&&!e.dead)}if(Ee)return Ee;const e=ke().then(e=>{if(Se)return Se.ready;const t=Ue();return t.ready=Oe(t,(e=>({url:k+L,wasmModule:e,textures:P,files:new Map([[L,new Blob(['#usda 1.0\n(\n defaultPrim = "Asset"\n)\n\ndef Xform "Asset"\n{\n}\n'],{type:"text/plain"})]])}))(e),()=>{}).then(()=>!0,()=>(Se===t&&(Se=null),Pe(t),!1)),Se=t,t.ready}).catch(()=>!1).finally(()=>{Ee===e&&(Ee=null)});return Ee=e,e}function Ie(e){let{ktx2:t,fetchFn:o,headers:s,signal:r,t0:n}=e;const a=new Map;let i=null;const l=(e,l)=>{const c=N(e);if(a.has(c))return a.get(c);const u={url:e,hinted:l,used:!1,startMs:performance.now()-n,readyMs:null,texture:null,error:null,derived:new Map};return u.promise=Promise.all([(i||(i=Promise.resolve("function"===typeof t?t():t).then(e=>{if(!e)throw new R("textures","webUsdLoader: maps need the page's KTX2 loader");return e})),i),Promise.resolve(o(e,{signal:r,headers:s,credentials:"same-origin"})).then(t=>{if(!t.ok)throw new R("textures","webUsdLoader: map ".concat(e,": HTTP ").concat(t.status),{url:e,status:t.status});return t.arrayBuffer()})]).then(e=>{let[t,o]=e;return((e,t)=>new Promise((o,s)=>e.parse(t,o,s)))(t,o)}).then(e=>(u.texture=e,u.readyMs=performance.now()-n,e)).catch(t=>{throw u.error=O(t)?t:new R(null!==r&&void 0!==r&&r.aborted?"aborted":"textures","webUsdLoader: map ".concat(e,": ").concat((null===t||void 0===t?void 0:t.message)||t),{cause:t,url:e}),u.error}),u.promise.catch(()=>{}),a.set(c,u),u};return{files:a,start:l,use(e){const t=l(e,!1);return t.used=!0,t},settle:()=>Promise.all([...a.values()].filter(e=>e.used).map(e=>e.promise)),texture(e,t,o,s,r){const n=a.get(N(t)),i=n.texture,l="color"===o?e.SRGBColorSpace:e.NoColorSpace,c=t=>"mirror"===t?e.MirroredRepeatWrapping:"clamp"===t?e.ClampToEdgeWrapping:e.RepeatWrapping,u="".concat(l,"|").concat(s.join(","),"|").concat(r?r.join(","):"");if(n.derived.size||(i.flipY=!1,i.colorSpace=l,i.magFilter=e.LinearFilter,i.minFilter=e.LinearMipmapLinearFilter,i.wrapS=c(s[0]),i.wrapT=c(s[1]),r&&(i.matrixAutoUpdate=!1,i.matrix.set(...r)),i.needsUpdate=!0,n.derived.set(u,i)),!n.derived.has(u)){const e=i.clone();e.colorSpace=l,e.wrapS=c(s[0]),e.wrapT=c(s[1]),e.matrixAutoUpdate=!r,r?e.matrix.set(...r):e.matrix.identity(),e.needsUpdate=!0,n.derived.set(u,e)}return n.derived.get(u)},all:()=>[...a.values()].flatMap(e=>[...e.derived.values()]),unused:()=>[...a.values()].filter(e=>!e.used&&e.texture).map(e=>e.texture)}}const We=e=>"".concat((null===e||void 0===e?void 0:e.path)||""," ").concat((null===e||void 0===e?void 0:e.message)||"").includes(_);function je(e,t){let{maps:o,base:r,tier:n,compact:a=null,normals:i="int8"}=t;const l=new e.Group;l.name="usd";const c=new Map,u=[],d=new Map,p=[],m=[];let h=null,f=[],y=new Map,v=!1;const g={meshes:0,triangles:0,loose:0},b={compact:!1,geometries:0,position:0,normal:0,uv:0,floatBytes:0,uploadBytes:0,ms:0},w=t=>{if(!c.has(t)){const o=new e.Group;o.name=t,c.set(t,o),l.add(o)}return c.get(t)},S=function(t,o,s){let n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,a=arguments.length>4&&void 0!==arguments[4]?arguments[4]:null;const i=f[t],l=n&&Object.keys(i.maps).length?n.join(","):"",c=null!==a&&i.physical.thickness>0?a:"",u="".concat(t,"|").concat(o,"|").concat(s,"|").concat(l,"|").concat(c);if(!d.has(u)){const t=function(e,t,o){var s;let r=!(arguments.length>3&&void 0!==arguments[3])||arguments[3];const n=new e.MeshPhysicalMaterial;n.name=t.name,n.color.setRGB(t.color[0],t.color[1],t.color[2],e.LinearSRGBColorSpace),n.opacity=t.opacity,n.roughness=t.roughness,n.metalness=t.metalness,n.emissive.setRGB(t.emissive[0],t.emissive[1],t.emissive[2],e.LinearSRGBColorSpace),n.emissiveIntensity=t.emissiveIntensity,n.transparent=t.transparent,n.depthWrite=t.depthWrite,n.alphaTest=t.alphaTest,n.side=(null!==(s=t.doubleSided)&&void 0!==s?s:o)?e.DoubleSide:e.FrontSide,n.normalScale.set(t.normalScale,r?-t.normalScale:t.normalScale),r&&(n.clearcoatNormalScale.y*=-1),n.aoMapIntensity=t.aoMapIntensity;for(const[i,l]of Object.entries(t.physical)){var a;null!==(a=n[i])&&void 0!==a&&a.isColor&&Array.isArray(l)?n[i].setRGB(l[0],l[1],l[2],e.LinearSRGBColorSpace):"number"===typeof l&&(n[i]=l)}return n}(e,i,o,s);""!==c&&(t.thickness=ae(i.physical.thickness,a));for(const[e,o]of Object.entries(i.maps)){const s=l?o.matrix?ce(o.matrix,n).map(e=>e+0):n:o.matrix;p.push([t,e,z(o.path,r),o.role,o.wrap,s])}d.set(u,t)}return d.get(u)};let A=null;const _=[];return{root:l,bodies:c,geometries:u,materials:d,warnings:m,receive:t=>{if("meta"===t.type)(e=>{h=e.meta,v=Z(a,h),b.compact=v,f=(h.materials||[]).map(ye);for(const t of f){for(const e of t.gaps)m.push({code:"material",message:"".concat(t.name,": ").concat(e)});for(const e of Object.values(t.maps))o.use(z(e.path,r))}y=new Map;for(const t of h.instances||[]){const e=W(t.path);e&&w(e.body),y.has(t.geometry)||y.set(t.geometry,[]),y.get(t.geometry).push(t)}for(const t of h.warnings||[])if("material-fallback"===t.code){const e=ve(h.materials);e&&m.push(e)}else We(t)||m.push(t)})(t);else if("geometry"===t.type)(t=>{var o;let{index:s,meta:r,arrays:n}=t;if(!r)return;if(!n)throw new Error("a geometry without its arrays");const a=new e.BufferGeometry,c=performance.now(),d=le(n,v,i);b.ms+=performance.now()-c;const p=d.positionLattice;let h=null;if(p){a.setAttribute("position",new e.InterleavedBufferAttribute(new e.InterleavedBuffer(p.array,4),3,0,!1));const t=2**p.k;h=(new e.Matrix4).makeScale(t,t,t).setPosition(p.offset[0]*t,p.offset[1]*t,p.offset[2]*t),a.boundingBox=new e.Box3(new e.Vector3(...p.min),new e.Vector3(...p.max))}else a.setAttribute("position",new e.BufferAttribute(d.position,3)),a.boundingBox=(new e.Box3).setFromArray(r.bounds);null!==(o=d.normal)&&void 0!==o&&o.bits?a.setAttribute("normal",new e.InterleavedBufferAttribute(new e.InterleavedBuffer(d.normal.array,4),3,0,!0)):d.normal&&a.setAttribute("normal",new e.BufferAttribute(d.normal,3)),d.uvs.forEach((t,o)=>a.setAttribute(o?"uv".concat(o):"uv",new e.BufferAttribute(t.array||t,2,!1)));const f=d.uvLattice?ne(d.uvLattice):null;var M;a.setIndex(new e.BufferAttribute(n.indices,1)),a.boundingSphere=a.boundingBox.getBoundingSphere(new e.Sphere),v&&(b.geometries+=1,b.position+=p?1:0,b.normal+=null!==(M=d.normal)&&void 0!==M&&M.bits?1:0,b.uv+=f?1:0),b.floatBytes+=d.bytes.float,b.uploadBytes+=d.bytes.upload,r.groups.length>1&&r.groups.forEach((e,t)=>{let[o,s]=e;return a.addGroup(o,s,t)}),r.hasColors&&m.push({code:"vertex-colors",message:"geometry ".concat(s,": vertex colours ignored")}),u.push(a);const A=r.groups.reduce((e,t)=>{let[,o]=t;return e+o/3},0),_=void 0===a.attributes.tangent;for(const i of y.get(s)||[]){const t=r.groups.map(e=>{let[,,t]=e;return S(void 0!==t&&Object.hasOwn(i.subsets||{},t)?i.subsets[t]:i.material,!!i.doubleSided,_,f,p?p.k:null)}),o=new e.Mesh(a,t.length>1?t:t[0]),s=W(i.path);o.name=s?s.name:i.path.split("/").pop(),o.matrix.fromArray(i.matrix),h&&o.matrix.multiply(h),o.matrix.decompose(o.position,o.quaternion,o.scale),s?w(s.body).add(o):(g.loose+=1,l.add(o)),g.meshes+=1,g.triangles+=A}})(t);else if("collider"===t.type){var n,c;_.push({meta:t.meta,points:(null===(n=t.arrays)||void 0===n?void 0:n.points)||null,indices:(null===(c=t.arrays)||void 0===c?void 0:c.indices)||null})}else if("scene"===t.type){const e=t.stats||{},{warnings:o}=e,r=(0,s.A)(e,M);A=r;for(const t of o||[])We(t)||m.push(t)}},attachMaps:()=>{for(const[t,s,r,n,a,i]of p)t[s]=o.texture(e,r,n,a,i);for(const e of d.values())e.needsUpdate=!0},counts:g,attrs:b,colliders:_,stats:()=>A,meta:()=>h,tier:n}}function Te(e,t,o){let s=arguments.length>3&&void 0!==arguments[3]?arguments[3]:[];const r={asked:!!e,read:!1,colliders:(null===o||void 0===o?void 0:o.length)||0,problems:[]};if(!e)return{articulation:null,info:r};if(null===t||void 0===t||!t.physics)return r.problems.push("the reader reports no physics (a reader without UsdPhysics)"),{articulation:null,info:r};r.read=!0;let n=null;try{n=function(e){var t,o;let s=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];g(e&&Array.isArray(e.prims),"no physics in the reader's meta"),g(!e.root||e.root.path===a,"the default prim is ".concat(null===(t=e.root)||void 0===t?void 0:t.path,", not ").concat(a));const r=b(new Map(e.prims.map(e=>[e.path,e])).get(a)),n=JSON.parse(JSON.stringify(u)),c={};for(const[a,[i,l]]of Object.entries(d))h(r,i)&&(c[a]=l?JSON.parse(r[i]):r[i]);const p=null===(o=e.root)||void 0===o?void 0:o.extentsHint;Array.isArray(p)&&p.length>=2&&(n.bbox=[[...p[0]],[...p[1]]]),h(c,"kind")&&(n.kind=c.kind,delete c.kind);const m="robot"===n.kind,v=[],M=new Set;for(const a of e.prims){const e=f(a.path);if(y(a.path)!==i||!e.startsWith("b")||"Xform"!==a.type)continue;const t=b(a),o=new Set(a.apiSchemas||[]);g(h(t,"simready:role")&&h(t,"simready:colliders"),"".concat(a.path,": no simready:role / simready:colliders")),v.push({id:e,role:t["simready:role"],rigid:o.has("PhysicsRigidBodyAPI"),mass_kg:o.has("PhysicsMassAPI")&&h(t,"physics:mass")?t["physics:mass"]:null,colliders:Math.trunc(Number(t["simready:colliders"]))}),M.add(e)}const S=[];for(const a of s){var A;const e=(null===a||void 0===a||null===(A=a.meta)||void 0===A?void 0:A.path)||"",t=e.split("/");if(6!==t.length||y(y(y(e)))!==i||"collision"!==t[4])continue;if(!M.has(t[3]))continue;const o=a.points||new Float32Array(0),s=a.indices||new Uint32Array(0),r=[];for(let a=0;a+2<o.length;a+=3)r.push([o[a],o[a+1],o[a+2]]);const n=[];for(let a=0;a<s.length;a+=3)n.push(Array.from(s.subarray(a,Math.min(a+3,s.length))));S.push([t[5],{body:t[3],points:r,faces:n}])}S.sort((e,t)=>e[0]<t[0]?-1:e[0]>t[0]?1:0);const _=[],x=[];for(const a of e.prims){if(y(a.path)!==l)continue;const{row:e,tree:t}=w(a,m);_.push(e),t&&x.push(t)}return x.sort((e,t)=>e[0]-t[0]),n.sequence=h(c,"sequence")?c.sequence:null,n.order=h(c,"order")?c.order:[],delete c.sequence,delete c.order,n.bodies=v,n.joints=_,n.tree=x.map(e=>{let[,t]=e;return t}),n.colliders=S.map(e=>{let[,t]=e;return t}),n.selftest=h(c,"selftest")?c.selftest:[],delete c.selftest,Object.assign(n,c),n}(t.physics,o||[]),r.problems.push(...function(e){const t=((null===e||void 0===e?void 0:e.bodies)||[]).reduce((e,t)=>e+(Number(t.colliders)||0),0),o=((null===e||void 0===e?void 0:e.colliders)||[]).length;return t===o?[]:["".concat(t," colliders declared, ").concat(o," read")]}(n))}catch(c){r.problems.push((null===c||void 0===c?void 0:c.message)||String(c))}return r.problems.length&&(n=null,s.push({code:"physics",message:"articulation not read from the USD: ".concat(r.problems.join("; "))})),{articulation:n,info:r}}async function Ne(e,t,o){let s,{signal:r,headers:n}=o;try{s=await e(t,{signal:r,headers:n,credentials:"same-origin"})}catch(a){throw new R(null!==r&&void 0!==r&&r.aborted?"aborted":"fetch","webUsdLoader: ".concat(t,": ").concat((null===a||void 0===a?void 0:a.message)||a),{cause:a,url:t})}if(!s.ok)throw new R("fetch","webUsdLoader: ".concat(t,": HTTP ").concat(s.status),{url:t,status:s.status});return s.blob()}async function Fe(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const{tier:s=1,ktx2:n=null,ktx2Hint:a=null,signal:i=null,headers:l,onStage:u=null,compact:d=null,normals:p="int8",physics:m=!1,colliders:h=!0}=t,f=!!m&&1===s,y=t.fetchFn||function(){return fetch(...arguments)},v=performance.now(),g={},b=e=>{g[e]=Math.round(10*(performance.now()-v))/10,null===u||void 0===u||u(e,g[e])};if(!be)throw new R("reader","webUsdLoader: no reader set");if(null!==i&&void 0!==i&&i.aborted)throw new R("aborted","webUsdLoader: the load was aborted",{url:e});const w=new URL(e,"undefined"===typeof window?void 0:window.location.href).href,M=new AbortController,A=()=>M.abort(i.reason);null===i||void 0===i||i.addEventListener("abort",A,{once:!0});const L=Ie({ktx2:n,fetchFn:y,headers:l,signal:M.signal,t0:v});for(const o of D(a,w).values())L.start(o,!0);a&&b("hintStarted");const U=T(s),B=Promise.all(U.map(e=>Ne(y,e===S?w:F(e,w),{signal:M.signal,headers:l})));B.catch(()=>{});const E=f&&h?Ne(y,F(_,w),{signal:M.signal,headers:l}).catch(()=>null):Promise.resolve(null),C=Promise.all([o.e(435),o.e(408)]).then(o.bind(o,408)),I=null===Me,W=async function(){const e=await ke(),t=Se;return Se=null,t&&(await t.ready,!t.dead)?{slot:t,module:e}:{slot:Ue(),module:e}}();W.catch(()=>{});let N=null,z=!1;const G={posted:!1};let q=null;const J=()=>{if(M.signal.aborted)throw new R("aborted","webUsdLoader: the load was aborted",{url:e})};try{const[{slot:t,module:o},n,a,i]=await Promise.all([W,B,C,E]);N=t,z=!0,I&&null!==Me&&(g.wasmCompile=Math.round(10*Me)/10),b("ready"),J(),q=je(a,{maps:L,base:w,tier:s,compact:d,normals:p});const l=new Map([[x,new Blob([j(s)],{type:"text/plain"})]]);U.forEach((e,t)=>l.set(e,n[t])),i&&l.set(_,i);const u={url:k+x,wasmModule:o,textures:P,files:l};f&&(u.physics={namespaces:c});if(Be(N,await Oe(N,u,q.receive,M.signal,G)),N=null,b("geometry"),J(),!q.bodies.size)throw new R("shape","webUsdLoader: no piece under /Asset/Bodies",{url:e});const m=Te(f,q.meta(),q.colliders,q.warnings);f&&b("physics"),await L.settle(),J(),b("textures"),J(),q.attachMaps();for(const e of L.unused())e.dispose();b("total"),J();const h=q.stats()||{},y=L.all(),v=[...L.files.values()],S=()=>{q.geometries.forEach(e=>e.dispose());for(const e of q.materials.values())e.dispose();y.forEach(e=>e.dispose())};return{scene:q.root,bodies:q.bodies,materials:[...q.materials.values()],textures:y,articulation:m.articulation,info:{tier:s,meshes:q.counts.meshes,triangles:q.counts.triangles,loose:q.counts.loose,bodies:q.bodies.size,geometries:q.geometries.length,materials:q.materials.size,maps:v.filter(e=>e.used).length,hinted:v.filter(e=>e.hinted).length,hintMissed:v.filter(e=>e.used&&!e.hinted).length,hintUnused:v.filter(e=>!e.used).length,mapFiles:v.map(e=>({url:e.url,hinted:e.hinted,used:e.used,startMs:Math.round(e.startMs),readyMs:null===e.readyMs?null:Math.round(e.readyMs)})),reader:h,warnings:q.warnings,attributes:(0,r.A)((0,r.A)({},q.attrs),{},{ms:Math.round(10*q.attrs.ms)/10}),physics:m.info},timings:g,dispose:S}}catch(Y){if(M.abort(),N?G.posted?Pe(N):Be(N,0):z||W.then(e=>Be(e.slot,0),()=>{}),q){q.geometries.forEach(e=>e.dispose());for(const e of q.materials.values())e.dispose()}const t=new Set(L.all());if(L.files.forEach(e=>{e.texture?t.add(e.texture):e.promise.then(e=>e.dispose(),()=>{})}),t.forEach(e=>e.dispose()),O(Y))throw Y;throw new R(null!==i&&void 0!==i&&i.aborted?"aborted":"compose","webUsdLoader: ".concat((null===Y||void 0===Y?void 0:Y.message)||Y),{cause:Y,url:e})}finally{null===i||void 0===i||i.removeEventListener("abort",A)}}function ze(){_e(null),Ee=null,Ae=0,B=null}const De=()=>({spawned:Ae,kept:!!Se,compiled:!!we})}}]);
services/explorer/dist/static/js/hash-wasm.d37b139f.chunk.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ /*! For license information please see hash-wasm.d37b139f.chunk.js.LICENSE.txt */
2
+ "use strict";(self.webpackChunkdeepsearch_ui=self.webpackChunkdeepsearch_ui||[]).push([[324],{441(A,I,g){g.d(I,{createSHA1:()=>R,createSHA256:()=>J});var B;function Q(A,I,g,B){return new(g||(g=Promise))(function(Q,E){function i(A){try{d(B.next(A))}catch(I){E(I)}}function c(A){try{d(B.throw(A))}catch(I){E(I)}}function d(A){var I;A.done?Q(A.value):(I=A.value,I instanceof g?I:new g(function(A){A(I)})).then(i,c)}d((B=B.apply(A,I||[])).next())})}"function"===typeof SuppressedError&&SuppressedError;class E{constructor(){this.mutex=Promise.resolve()}lock(){let A=()=>{};return this.mutex=this.mutex.then(()=>new Promise(A)),new Promise(I=>{A=I})}dispatch(A){return Q(this,void 0,void 0,function*(){const I=yield this.lock();try{return yield Promise.resolve(A())}finally{I()}})}}const i="undefined"!==typeof globalThis?globalThis:"undefined"!==typeof self?self:"undefined"!==typeof window?window:g.g,c=null!==(B=i.Buffer)&&void 0!==B?B:null,d=i.TextEncoder?new i.TextEncoder:null;function n(A,I){return(15&A)+(A>>6|A>>3&8)<<4|(15&I)+(I>>6|I>>3&8)}function a(A,I){const g=I.length>>1;for(let B=0;B<g;B++){const g=B<<1;A[B]=n(I.charCodeAt(g),I.charCodeAt(g+1))}}const o="a".charCodeAt(0)-10,y="0".charCodeAt(0);function C(A,I,g){let B=0;for(let Q=0;Q<g;Q++){let g=I[Q]>>>4;A[B++]=g>9?g+o:g+y,g=15&I[Q],A[B++]=g>9?g+o:g+y}return String.fromCharCode.apply(null,A)}const N=null!==c?A=>{if("string"===typeof A){const I=c.from(A,"utf8");return new Uint8Array(I.buffer,I.byteOffset,I.length)}if(c.isBuffer(A))return new Uint8Array(A.buffer,A.byteOffset,A.length);if(ArrayBuffer.isView(A))return new Uint8Array(A.buffer,A.byteOffset,A.byteLength);throw new Error("Invalid data type!")}:A=>{if("string"===typeof A)return d.encode(A);if(ArrayBuffer.isView(A))return new Uint8Array(A.buffer,A.byteOffset,A.byteLength);throw new Error("Invalid data type!")},e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",D=new Uint8Array(256);for(let k=0;k<64;k++)D[e.charCodeAt(k)]=k;function F(A){let I=Math.floor(.75*A.length);const g=A.length;return"="===A[g-1]&&(I-=1,"="===A[g-2]&&(I-=1)),I}function q(A){const I=F(A),g=A.length,B=new Uint8Array(I);let Q=0;for(let E=0;E<g;E+=4){const I=D[A.charCodeAt(E)],g=D[A.charCodeAt(E+1)],i=D[A.charCodeAt(E+2)],c=D[A.charCodeAt(E+3)];B[Q]=I<<2|g>>4,Q+=1,B[Q]=(15&g)<<4|i>>2,Q+=1,B[Q]=(3&i)<<6|63&c,Q+=1}return B}const z=16384,t=new E,H=new Map;function h(A,I){return Q(this,void 0,void 0,function*(){let g=null,B=null,E=!1;if("undefined"===typeof WebAssembly)throw new Error("WebAssembly is not supported in this environment!");const i=()=>new DataView(g.exports.memory.buffer).getUint32(g.exports.STATE_SIZE,!0),c=t.dispatch(()=>Q(this,void 0,void 0,function*(){if(!H.has(A.name)){const I=q(A.data),g=WebAssembly.compile(I);H.set(A.name,g)}const I=yield H.get(A.name);g=yield WebAssembly.instantiate(I,{})})),d=function(){let A=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;E=!0,g.exports.Hash_Init(A)},o=A=>{if(!E)throw new Error("update() called before init()");(A=>{let I=0;for(;I<A.length;){const Q=A.subarray(I,I+z);I+=Q.length,B.set(Q),g.exports.Hash_Update(Q.length)}})(N(A))},y=new Uint8Array(2*I),e=function(A){let Q=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;if(!E)throw new Error("digest() called before init()");return E=!1,g.exports.Hash_Final(Q),"binary"===A?B.slice(0,I):C(y,B,I)},D=A=>"string"===typeof A?A.length<4096:A.byteLength<z;let F=D;switch(A.name){case"argon2":case"scrypt":F=()=>!0;break;case"blake2b":case"blake2s":F=(A,I)=>I<=512&&D(A);break;case"blake3":F=(A,I)=>0===I&&D(A);break;case"xxhash64":case"xxhash3":case"xxhash128":case"crc64":F=()=>!1}return yield(()=>Q(this,void 0,void 0,function*(){g||(yield c);const A=g.exports.Hash_GetBuffer(),I=g.exports.memory.buffer;B=new Uint8Array(I,A,z)}))(),{getMemory:()=>B,writeMemory:function(A){let I=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;B.set(A,I)},getExports:()=>g.exports,setMemorySize:A=>{g.exports.Hash_SetMemorySize(A);const I=g.exports.Hash_GetBuffer(),Q=g.exports.memory.buffer;B=new Uint8Array(Q,I,A)},init:d,update:o,digest:e,save:()=>{if(!E)throw new Error("save() can only be called after init() and before digest()");const I=g.exports.Hash_GetState(),B=i(),Q=g.exports.memory.buffer,c=new Uint8Array(Q,I,B),d=new Uint8Array(4+B);return a(d,A.hash),d.set(c,4),d},load:I=>{if(!(I instanceof Uint8Array))throw new Error("load() expects an Uint8Array generated by save()");const B=g.exports.Hash_GetState(),Q=i(),c=4+Q,d=g.exports.memory.buffer;if(I.length!==c)throw new Error("Bad state length (expected ".concat(c," bytes, got ").concat(I.length,")"));if(!function(A,I){if(A.length!==2*I.length)return!1;for(let g=0;g<I.length;g++){const B=g<<1;if(I[g]!==n(A.charCodeAt(B),A.charCodeAt(B+1)))return!1}return!0}(A.hash,I.subarray(0,4)))throw new Error("This state was written by an incompatible hash implementation");const a=I.subarray(4);new Uint8Array(d,B,Q).set(a),E=!0},calculate:function(A){let Q=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,E=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;if(!F(A,Q))return d(Q),o(A),e("hex",E);const i=N(A);return B.set(i),g.exports.Hash_Calculate(i.length,Q,E),C(y,B,I)},hashLength:I}})}new E;new E;new DataView(new ArrayBuffer(4));new E;new E;new E;new E;new Uint8Array(8);new E;new E;var M={name:"sha1",data:"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",hash:"6b530c24"};new E;function R(){return h(M,20).then(A=>{A.init();const I={init:()=>(A.init(),I),update:g=>(A.update(g),I),digest:I=>A.digest(I),save:()=>A.save(),load:g=>(A.load(g),I),blockSize:64,digestSize:20};return I})}new E;new E;var G={name:"sha256",data:"AGFzbQEAAAABEQRgAAF/YAF/AGAAAGACf38AAwgHAAEBAQIAAwUEAQECAgYOAn8BQfCJBQt/AEGACAsHcAgGbWVtb3J5AgAOSGFzaF9HZXRCdWZmZXIAAAlIYXNoX0luaXQAAQtIYXNoX1VwZGF0ZQACCkhhc2hfRmluYWwABA1IYXNoX0dldFN0YXRlAAUOSGFzaF9DYWxjdWxhdGUABgpTVEFURV9TSVpFAwEKnEoHBQBBgAkLnQEAQQBCADcDwIkBQQBBHEEgIABB4AFGIgAbNgLoiQFBAEKnn+anxvST/b5/Qquzj/yRo7Pw2wAgABs3A+CJAUEAQrGWgP6fooWs6ABC/6S5iMWR2oKbfyAAGzcD2IkBQQBCl7rDg5Onlod3QvLmu+Ojp/2npX8gABs3A9CJAUEAQti9loj8oLW+NkLnzKfQ1tDrs7t/IAAbNwPIiQEL7wICAX4Gf0EAQQApA8CJASIBIACtfDcDwIkBAkACQAJAIAGnQT9xIgINAEGACSEDDAELAkBBwAAgAmsiBCAAIAQgAEkbIgNFDQAgA0EDcSEFIAJBgIkBaiEGQQAhAgJAIANBBEkNACADQfwAcSEHQQAhAgNAIAYgAmoiAyACQYAJai0AADoAACADQQFqIAJBgQlqLQAAOgAAIANBAmogAkGCCWotAAA6AAAgA0EDaiACQYMJai0AADoAACAHIAJBBGoiAkcNAAsLIAVFDQADQCAGIAJqIAJBgAlqLQAAOgAAIAJBAWohAiAFQX9qIgUNAAsLIAAgBEkNAUGAiQEQAyAAIARrIQAgBEGACWohAwsCQCAAQcAASQ0AA0AgAxADIANBwABqIQMgAEFAaiIAQT9LDQALCyAARQ0AQQAhAkEAIQUDQCACQYCJAWogAyACai0AADoAACACQQFqIQIgACAFQQFqIgVB/wFxSw0ACwsLoz4BRX9BACAAKAI8IgFBGHQgAUGA/gNxQQh0ciABQQh2QYD+A3EgAUEYdnJyIgFBGXcgAUEOd3MgAUEDdnMgACgCOCICQRh0IAJBgP4DcUEIdHIgAkEIdkGA/gNxIAJBGHZyciICaiAAKAIgIgNBGHQgA0GA/gNxQQh0ciADQQh2QYD+A3EgA0EYdnJyIgRBGXcgBEEOd3MgBEEDdnMgACgCHCIDQRh0IANBgP4DcUEIdHIgA0EIdkGA/gNxIANBGHZyciIFaiAAKAIEIgNBGHQgA0GA/gNxQQh0ciADQQh2QYD+A3EgA0EYdnJyIgZBGXcgBkEOd3MgBkEDdnMgACgCACIDQRh0IANBgP4DcUEIdHIgA0EIdkGA/gNxIANBGHZyciIHaiAAKAIkIgNBGHQgA0GA/gNxQQh0ciADQQh2QYD+A3EgA0EYdnJyIghqIAJBD3cgAkENd3MgAkEKdnNqIgNqIAAoAhgiCUEYdCAJQYD+A3FBCHRyIAlBCHZBgP4DcSAJQRh2cnIiCkEZdyAKQQ53cyAKQQN2cyAAKAIUIglBGHQgCUGA/gNxQQh0ciAJQQh2QYD+A3EgCUEYdnJyIgtqIAJqIAAoAhAiCUEYdCAJQYD+A3FBCHRyIAlBCHZBgP4DcSAJQRh2cnIiDEEZdyAMQQ53cyAMQQN2cyAAKAIMIglBGHQgCUGA/gNxQQh0ciAJQQh2QYD+A3EgCUEYdnJyIg1qIAAoAjAiCUEYdCAJQYD+A3FBCHRyIAlBCHZBgP4DcSAJQRh2cnIiDmogACgCCCIJQRh0IAlBgP4DcUEIdHIgCUEIdkGA/gNxIAlBGHZyciIPQRl3IA9BDndzIA9BA3ZzIAZqIAAoAigiCUEYdCAJQYD+A3FBCHRyIAlBCHZBgP4DcSAJQRh2cnIiEGogAUEPdyABQQ13cyABQQp2c2oiCUEPdyAJQQ13cyAJQQp2c2oiEUEPdyARQQ13cyARQQp2c2oiEkEPdyASQQ13cyASQQp2c2oiE2ogACgCNCIUQRh0IBRBgP4DcUEIdHIgFEEIdkGA/gNxIBRBGHZyciIVQRl3IBVBDndzIBVBA3ZzIA5qIBJqIAAoAiwiAEEYdCAAQYD+A3FBCHRyIABBCHZBgP4DcSAAQRh2cnIiFkEZdyAWQQ53cyAWQQN2cyAQaiARaiAIQRl3IAhBDndzIAhBA3ZzIARqIAlqIAVBGXcgBUEOd3MgBUEDdnMgCmogAWogC0EZdyALQQ53cyALQQN2cyAMaiAVaiANQRl3IA1BDndzIA1BA3ZzIA9qIBZqIANBD3cgA0ENd3MgA0EKdnNqIhRBD3cgFEENd3MgFEEKdnNqIhdBD3cgF0ENd3MgF0EKdnNqIhhBD3cgGEENd3MgGEEKdnNqIhlBD3cgGUENd3MgGUEKdnNqIhpBD3cgGkENd3MgGkEKdnNqIhtBD3cgG0ENd3MgG0EKdnNqIhxBGXcgHEEOd3MgHEEDdnMgAkEZdyACQQ53cyACQQN2cyAVaiAYaiAOQRl3IA5BDndzIA5BA3ZzIBZqIBdqIBBBGXcgEEEOd3MgEEEDdnMgCGogFGogE0EPdyATQQ13cyATQQp2c2oiHUEPdyAdQQ13cyAdQQp2c2oiHkEPdyAeQQ13cyAeQQp2c2oiH2ogE0EZdyATQQ53cyATQQN2cyAYaiADQRl3IANBDndzIANBA3ZzIAFqIBlqIB9BD3cgH0ENd3MgH0EKdnNqIiBqIBJBGXcgEkEOd3MgEkEDdnMgF2ogH2ogEUEZdyARQQ53cyARQQN2cyAUaiAeaiAJQRl3IAlBDndzIAlBA3ZzIANqIB1qIBxBD3cgHEENd3MgHEEKdnNqIiFBD3cgIUENd3MgIUEKdnNqIiJBD3cgIkENd3MgIkEKdnNqIiNBD3cgI0ENd3MgI0EKdnNqIiRqIBtBGXcgG0EOd3MgG0EDdnMgHmogI2ogGkEZdyAaQQ53cyAaQQN2cyAdaiAiaiAZQRl3IBlBDndzIBlBA3ZzIBNqICFqIBhBGXcgGEEOd3MgGEEDdnMgEmogHGogF0EZdyAXQQ53cyAXQQN2cyARaiAbaiAUQRl3IBRBDndzIBRBA3ZzIAlqIBpqICBBD3cgIEENd3MgIEEKdnNqIiVBD3cgJUENd3MgJUEKdnNqIiZBD3cgJkENd3MgJkEKdnNqIidBD3cgJ0ENd3MgJ0EKdnNqIihBD3cgKEENd3MgKEEKdnNqIilBD3cgKUENd3MgKUEKdnNqIipBD3cgKkENd3MgKkEKdnNqIitBGXcgK0EOd3MgK0EDdnMgH0EZdyAfQQ53cyAfQQN2cyAbaiAnaiAeQRl3IB5BDndzIB5BA3ZzIBpqICZqIB1BGXcgHUEOd3MgHUEDdnMgGWogJWogJEEPdyAkQQ13cyAkQQp2c2oiLEEPdyAsQQ13cyAsQQp2c2oiLUEPdyAtQQ13cyAtQQp2c2oiLmogJEEZdyAkQQ53cyAkQQN2cyAnaiAgQRl3ICBBDndzICBBA3ZzIBxqIChqIC5BD3cgLkENd3MgLkEKdnNqIi9qICNBGXcgI0EOd3MgI0EDdnMgJmogLmogIkEZdyAiQQ53cyAiQQN2cyAlaiAtaiAhQRl3ICFBDndzICFBA3ZzICBqICxqICtBD3cgK0ENd3MgK0EKdnNqIjBBD3cgMEENd3MgMEEKdnNqIjFBD3cgMUENd3MgMUEKdnNqIjJBD3cgMkENd3MgMkEKdnNqIjNqICpBGXcgKkEOd3MgKkEDdnMgLWogMmogKUEZdyApQQ53cyApQQN2cyAsaiAxaiAoQRl3IChBDndzIChBA3ZzICRqIDBqICdBGXcgJ0EOd3MgJ0EDdnMgI2ogK2ogJkEZdyAmQQ53cyAmQQN2cyAiaiAqaiAlQRl3ICVBDndzICVBA3ZzICFqIClqIC9BD3cgL0ENd3MgL0EKdnNqIjRBD3cgNEENd3MgNEEKdnNqIjVBD3cgNUENd3MgNUEKdnNqIjZBD3cgNkENd3MgNkEKdnNqIjdBD3cgN0ENd3MgN0EKdnNqIjhBD3cgOEENd3MgOEEKdnNqIjlBD3cgOUENd3MgOUEKdnNqIjogOCA0IC4gLCAhIBsgGSADIA4gBEEAKALYiQEiO0EadyA7QRV3cyA7QQd3c0EAKALkiQEiPGpBACgC4IkBIj1BACgC3IkBIj5zIDtxID1zaiAHakGY36iUBGoiB0EAKALUiQEiP2oiACAMaiA7IA1qID4gD2ogPSAGaiAAID4gO3NxID5zaiAAQRp3IABBFXdzIABBB3dzakGRid2JB2oiQEEAKALQiQEiQWoiDCAAIDtzcSA7c2ogDEEadyAMQRV3cyAMQQd3c2pBz/eDrntqIkJBACgCzIkBIkNqIg0gDCAAc3EgAHNqIA1BGncgDUEVd3MgDUEHd3NqQaW3181+aiJEQQAoAsiJASIAaiIPIA0gDHNxIAxzaiAPQRp3IA9BFXdzIA9BB3dzakHbhNvKA2oiRSBBIEMgAHNxIEMgAHFzIABBHncgAEETd3MgAEEKd3NqIAdqIgZqIgdqIAUgD2ogCiANaiALIAxqIAcgDyANc3EgDXNqIAdBGncgB0EVd3MgB0EHd3NqQfGjxM8FaiIKIAYgAHMgQ3EgBiAAcXMgBkEedyAGQRN3cyAGQQp3c2ogQGoiDGoiBCAHIA9zcSAPc2ogBEEadyAEQRV3cyAEQQd3c2pBpIX+kXlqIgsgDCAGcyAAcSAMIAZxcyAMQR53IAxBE3dzIAxBCndzaiBCaiINaiIPIAQgB3NxIAdzaiAPQRp3IA9BFXdzIA9BB3dzakHVvfHYemoiQCANIAxzIAZxIA0gDHFzIA1BHncgDUETd3MgDUEKd3NqIERqIgZqIgcgDyAEc3EgBHNqIAdBGncgB0EVd3MgB0EHd3NqQZjVnsB9aiJCIAYgDXMgDHEgBiANcXMgBkEedyAGQRN3cyAGQQp3c2ogRWoiDGoiBWogFiAHaiAQIA9qIAggBGogBSAHIA9zcSAPc2ogBUEadyAFQRV3cyAFQQd3c2pBgbaNlAFqIgggDCAGcyANcSAMIAZxcyAMQR53IAxBE3dzIAxBCndzaiAKaiINaiIPIAUgB3NxIAdzaiAPQRp3IA9BFXdzIA9BB3dzakG+i8ahAmoiDiANIAxzIAZxIA0gDHFzIA1BHncgDUETd3MgDUEKd3NqIAtqIgZqIgcgDyAFc3EgBXNqIAdBGncgB0EVd3MgB0EHd3NqQcP7sagFaiIQIAYgDXMgDHEgBiANcXMgBkEedyAGQRN3cyAGQQp3c2ogQGoiDGoiBCAHIA9zcSAPc2ogBEEadyAEQRV3cyAEQQd3c2pB9Lr5lQdqIhYgDCAGcyANcSAMIAZxcyAMQR53IAxBE3dzIAxBCndzaiBCaiINaiIFaiABIARqIAIgB2ogFSAPaiAFIAQgB3NxIAdzaiAFQRp3IAVBFXdzIAVBB3dzakH+4/qGeGoiByANIAxzIAZxIA0gDHFzIA1BHncgDUETd3MgDUEKd3NqIAhqIgFqIgYgBSAEc3EgBHNqIAZBGncgBkEVd3MgBkEHd3NqQaeN8N55aiIEIAEgDXMgDHEgASANcXMgAUEedyABQRN3cyABQQp3c2ogDmoiAmoiDCAGIAVzcSAFc2ogDEEadyAMQRV3cyAMQQd3c2pB9OLvjHxqIgUgAiABcyANcSACIAFxcyACQR53IAJBE3dzIAJBCndzaiAQaiIDaiINIAwgBnNxIAZzaiANQRp3IA1BFXdzIA1BB3dzakHB0+2kfmoiCCADIAJzIAFxIAMgAnFzIANBHncgA0ETd3MgA0EKd3NqIBZqIgFqIg8gF2ogESANaiAUIAxqIAkgBmogDyANIAxzcSAMc2ogD0EadyAPQRV3cyAPQQd3c2pBho/5/X5qIgYgASADcyACcSABIANxcyABQR53IAFBE3dzIAFBCndzaiAHaiICaiIJIA8gDXNxIA1zaiAJQRp3IAlBFXdzIAlBB3dzakHGu4b+AGoiDCACIAFzIANxIAIgAXFzIAJBHncgAkETd3MgAkEKd3NqIARqIgNqIhEgCSAPc3EgD3NqIBFBGncgEUEVd3MgEUEHd3NqQczDsqACaiINIAMgAnMgAXEgAyACcXMgA0EedyADQRN3cyADQQp3c2ogBWoiAWoiFCARIAlzcSAJc2ogFEEadyAUQRV3cyAUQQd3c2pB79ik7wJqIg8gASADcyACcSABIANxcyABQR53IAFBE3dzIAFBCndzaiAIaiICaiIXaiATIBRqIBggEWogEiAJaiAXIBQgEXNxIBFzaiAXQRp3IBdBFXdzIBdBB3dzakGqidLTBGoiGCACIAFzIANxIAIgAXFzIAJBHncgAkETd3MgAkEKd3NqIAZqIgNqIgkgFyAUc3EgFHNqIAlBGncgCUEVd3MgCUEHd3NqQdzTwuUFaiIUIAMgAnMgAXEgAyACcXMgA0EedyADQRN3cyADQQp3c2ogDGoiAWoiESAJIBdzcSAXc2ogEUEadyARQRV3cyARQQd3c2pB2pHmtwdqIhcgASADcyACcSABIANxcyABQR53IAFBE3dzIAFBCndzaiANaiICaiISIBEgCXNxIAlzaiASQRp3IBJBFXdzIBJBB3dzakHSovnBeWoiGSACIAFzIANxIAIgAXFzIAJBHncgAkETd3MgAkEKd3NqIA9qIgNqIhNqIB4gEmogGiARaiAdIAlqIBMgEiARc3EgEXNqIBNBGncgE0EVd3MgE0EHd3NqQe2Mx8F6aiIaIAMgAnMgAXEgAyACcXMgA0EedyADQRN3cyADQQp3c2ogGGoiAWoiCSATIBJzcSASc2ogCUEadyAJQRV3cyAJQQd3c2pByM+MgHtqIhggASADcyACcSABIANxcyABQR53IAFBE3dzIAFBCndzaiAUaiICaiIRIAkgE3NxIBNzaiARQRp3IBFBFXdzIBFBB3dzakHH/+X6e2oiFCACIAFzIANxIAIgAXFzIAJBHncgAkETd3MgAkEKd3NqIBdqIgNqIhIgESAJc3EgCXNqIBJBGncgEkEVd3MgEkEHd3NqQfOXgLd8aiIXIAMgAnMgAXEgAyACcXMgA0EedyADQRN3cyADQQp3c2ogGWoiAWoiE2ogICASaiAcIBFqIB8gCWogEyASIBFzcSARc2ogE0EadyATQRV3cyATQQd3c2pBx6KerX1qIhkgASADcyACcSABIANxcyABQR53IAFBE3dzIAFBCndzaiAaaiICaiIJIBMgEnNxIBJzaiAJQRp3IAlBFXdzIAlBB3dzakHRxqk2aiIaIAIgAXMgA3EgAiABcXMgAkEedyACQRN3cyACQQp3c2ogGGoiA2oiESAJIBNzcSATc2ogEUEadyARQRV3cyARQQd3c2pB59KkoQFqIhggAyACcyABcSADIAJxcyADQR53IANBE3dzIANBCndzaiAUaiIBaiISIBEgCXNxIAlzaiASQRp3IBJBFXdzIBJBB3dzakGFldy9AmoiFCABIANzIAJxIAEgA3FzIAFBHncgAUETd3MgAUEKd3NqIBdqIgJqIhMgI2ogJiASaiAiIBFqICUgCWogEyASIBFzcSARc2ogE0EadyATQRV3cyATQQd3c2pBuMLs8AJqIhcgAiABcyADcSACIAFxcyACQR53IAJBE3dzIAJBCndzaiAZaiIDaiIJIBMgEnNxIBJzaiAJQRp3IAlBFXdzIAlBB3dzakH827HpBGoiGSADIAJzIAFxIAMgAnFzIANBHncgA0ETd3MgA0EKd3NqIBpqIgFqIhEgCSATc3EgE3NqIBFBGncgEUEVd3MgEUEHd3NqQZOa4JkFaiIaIAEgA3MgAnEgASADcXMgAUEedyABQRN3cyABQQp3c2ogGGoiAmoiEiARIAlzcSAJc2ogEkEadyASQRV3cyASQQd3c2pB1OapqAZqIhggAiABcyADcSACIAFxcyACQR53IAJBE3dzIAJBCndzaiAUaiIDaiITaiAoIBJqICQgEWogJyAJaiATIBIgEXNxIBFzaiATQRp3IBNBFXdzIBNBB3dzakG7laizB2oiFCADIAJzIAFxIAMgAnFzIANBHncgA0ETd3MgA0EKd3NqIBdqIgFqIgkgEyASc3EgEnNqIAlBGncgCUEVd3MgCUEHd3NqQa6Si454aiIXIAEgA3MgAnEgASADcXMgAUEedyABQRN3cyABQQp3c2ogGWoiAmoiESAJIBNzcSATc2ogEUEadyARQRV3cyARQQd3c2pBhdnIk3lqIhkgAiABcyADcSACIAFxcyACQR53IAJBE3dzIAJBCndzaiAaaiIDaiISIBEgCXNxIAlzaiASQRp3IBJBFXdzIBJBB3dzakGh0f+VemoiGiADIAJz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",hash:"8c18dd94"};new E;new E;function J(){return h(G,32).then(A=>{A.init(256);const I={init:()=>(A.init(256),I),update:g=>(A.update(g),I),digest:I=>A.digest(I),save:()=>A.save(),load:g=>(A.load(g),I),blockSize:64,digestSize:32};return I})}new E;new E;new E;new E;new Uint8Array(8);new E;new Uint8Array(8);new E;new Uint8Array(8);new E;new E;new E}}]);
services/explorer/dist/static/js/hash-wasm.d37b139f.chunk.js.LICENSE.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ /*!
2
+ * hash-wasm (https://www.npmjs.com/package/hash-wasm)
3
+ * (c) Dani Biro
4
+ * @license MIT
5
+ */
services/explorer/dist/static/js/main.846b9fc7.js ADDED
The diff for this file is too large to render. See raw diff
 
services/explorer/dist/static/js/main.846b9fc7.js.LICENSE.txt ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * @license React
3
+ * react-dom.production.min.js
4
+ *
5
+ * Copyright (c) Facebook, Inc. and its affiliates.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */
10
+
11
+ /**
12
+ * @license React
13
+ * react-jsx-runtime.production.min.js
14
+ *
15
+ * Copyright (c) Facebook, Inc. and its affiliates.
16
+ *
17
+ * This source code is licensed under the MIT license found in the
18
+ * LICENSE file in the root directory of this source tree.
19
+ */
20
+
21
+ /**
22
+ * @license React
23
+ * react.production.min.js
24
+ *
25
+ * Copyright (c) Facebook, Inc. and its affiliates.
26
+ *
27
+ * This source code is licensed under the MIT license found in the
28
+ * LICENSE file in the root directory of this source tree.
29
+ */
30
+
31
+ /**
32
+ * @license React
33
+ * scheduler.production.min.js
34
+ *
35
+ * Copyright (c) Facebook, Inc. and its affiliates.
36
+ *
37
+ * This source code is licensed under the MIT license found in the
38
+ * LICENSE file in the root directory of this source tree.
39
+ */
services/explorer/dist/static/usd-reader/81290bc/esm/errors.js ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** Why a load failed: `aborted`, `fetch` (root layer or a resource limit), `compose`, `worker` or `webgl`. */
2
+ export class UsdLoadError extends Error {
3
+ name = "UsdLoadError";
4
+ code;
5
+ constructor(code, message, { url, status, cause } = {}) {
6
+ super(message, cause === undefined ? undefined : { cause });
7
+ this.code = code;
8
+ if (url !== undefined) {
9
+ this.url = url;
10
+ }
11
+ if (status !== undefined) {
12
+ this.status = status;
13
+ }
14
+ }
15
+ }
services/explorer/dist/static/usd-reader/81290bc/esm/hub-prefetch.js ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // The layers of a Hub package, listed with one tree-API call, so a load can
2
+ // request them all at once instead of discovering them a round trip at a time.
3
+ const RESOLVE = /^(https:\/\/(?:huggingface\.co|hf\.co))\/((?:datasets\/|spaces\/)?)([^/?#]+\/[^/?#]+)\/resolve\/([^/?#]+)\/([^?#]+)$/;
4
+ const LAYER = /\.(usd|usda|usdc)$/i;
5
+ const SIMREADY_PACKAGE = "com.nvidia.simready.packaging.json";
6
+ const MAX_FILES = 256;
7
+ const MAX_BYTES = 64 * 2 ** 20;
8
+ /**
9
+ * The USD layers of the package holding a Hub `resolve` URL, as `{ url, size }`:
10
+ * the directory with a SimReady packaging manifest among the root's parent
11
+ * and grandparent, else everything under the root's own directory. `eager`
12
+ * when a manifest declares the package, so its layers are worth requesting
13
+ * before the root is read. No layers, without a request, for a root at the
14
+ * top of its repo or any other URL, and none if the listing fails: the load then discovers layers as usual.
15
+ */
16
+ export async function hubPackageLayers(rootUrl, request) {
17
+ const match = rootUrl.split(/[?#]/)[0].match(RESOLVE);
18
+ const none = { layers: [], eager: false };
19
+ if (!match) {
20
+ return none;
21
+ }
22
+ const [, origin, prefix, repo, revision, path] = match;
23
+ const parent = path.split("/").slice(0, -1);
24
+ // A root at the top of a repo would list, and preload, the whole repo.
25
+ if (!parent.length) {
26
+ return none;
27
+ }
28
+ const listed = parent.length > 1 ? parent.slice(0, -1) : parent;
29
+ try {
30
+ const response = await request(`${origin}/api/${prefix || "models/"}${repo}/tree/${revision}/${listed.join("/")}?recursive=true`);
31
+ if (!response.ok) {
32
+ return none;
33
+ }
34
+ const entries = await response.json();
35
+ const decoded = parent.map(decodeURIComponent);
36
+ const manifest = [decoded, decoded.slice(0, -1)].find((dir) => dir.length >= listed.length && entries.some((e) => e.path === [...dir, SIMREADY_PACKAGE].join("/")));
37
+ const depth = (manifest ?? decoded).length;
38
+ const packageDir = decoded
39
+ .slice(0, depth)
40
+ .map((name) => name + "/")
41
+ .join("");
42
+ // As the root spells it, so URLs match the ones composition resolves.
43
+ const base = `${origin}/${prefix}${repo}/resolve/${revision}/${parent
44
+ .slice(0, depth)
45
+ .map((name) => name + "/")
46
+ .join("")}`;
47
+ const layers = [];
48
+ let bytes = 0;
49
+ for (const { type, path: file, size } of entries) {
50
+ if (type !== "file" || !file.startsWith(packageDir) || !LAYER.test(file)) {
51
+ continue;
52
+ }
53
+ if (layers.length >= MAX_FILES || bytes + size > MAX_BYTES) {
54
+ continue;
55
+ }
56
+ bytes += size;
57
+ layers.push({
58
+ url: new URL(file.slice(packageDir.length).replace(/[%#?]/g, encodeURIComponent), base).href,
59
+ size,
60
+ });
61
+ }
62
+ return { layers, eager: !!manifest };
63
+ }
64
+ catch {
65
+ return none;
66
+ }
67
+ }
68
+ /**
69
+ * A Hub `resolve` URL pinned to the commit its branch or tag points at now,
70
+ * so every layer and texture of one load (all resolved against the root)
71
+ * comes from the same commit even if the repo is pushed to meanwhile. Unchanged,
72
+ * without a request, for a commit or any other URL, and if the lookup fails.
73
+ */
74
+ export async function pinHubRevision(rootUrl, request) {
75
+ const match = rootUrl.split(/[?#]/)[0].match(RESOLVE);
76
+ if (!match) {
77
+ return rootUrl;
78
+ }
79
+ const [, origin, prefix, repo, revision] = match;
80
+ if (/^[0-9a-f]{40}$/.test(revision)) {
81
+ return rootUrl;
82
+ }
83
+ try {
84
+ const response = await request(`${origin}/api/${prefix || "models/"}${repo}/revision/${revision}?expand%5B%5D=sha`);
85
+ const { sha } = response.ok ? await response.json() : {};
86
+ if (!/^[0-9a-f]{40}$/.test(sha ?? "")) {
87
+ return rootUrl;
88
+ }
89
+ return rootUrl.replace(`/resolve/${revision}/`, `/resolve/${sha}/`);
90
+ }
91
+ catch {
92
+ return rootUrl;
93
+ }
94
+ }
services/explorer/dist/static/usd-reader/81290bc/esm/load-core.js ADDED
@@ -0,0 +1,760 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { UsdLoadError } from "./errors.js";
2
+ /** The load options' defaults, and the largest image side read at all. SECURITY.md documents the limits. */
3
+ export const DEFAULTS = {
4
+ textures: "preview",
5
+ maxTextureSize: 1024,
6
+ maxConcurrentFetches: 16,
7
+ maxLayerBytes: 768 * 2 ** 20,
8
+ maxLayers: 1024,
9
+ maxInstances: 100000,
10
+ maxTriangles: 20e6,
11
+ maxTextureBytes: 512 * 2 ** 20,
12
+ maxImageSize: 16384,
13
+ };
14
+ /** Loads and composes the stage at `rootUrl`. */
15
+ export async function composeStage({ UsdLoader, fetchBytes, rootUrl, maxConcurrentFetches = DEFAULTS.maxConcurrentFetches, maxLayerBytes = DEFAULTS.maxLayerBytes, maxLayers = DEFAULTS.maxLayers, maxInstances = DEFAULTS.maxInstances, allowedOrigins, preload, onProgress = () => { }, physics, }) {
16
+ const root = rootUrl.split(/[?#]/)[0];
17
+ const urlOf = (path) => (path === root ? rootUrl : path);
18
+ const loader = new UsdLoader();
19
+ if (physics) {
20
+ loader.setPhysics([...physics]);
21
+ }
22
+ const stats = {
23
+ layers: 0,
24
+ layerBytes: 0,
25
+ missing: 0,
26
+ rounds: 0,
27
+ fetchMs: 0,
28
+ parseMs: 0,
29
+ composeMs: 0,
30
+ warnings: [],
31
+ };
32
+ const started = new Map();
33
+ const progress = () => onProgress({ stage: "layers", loaded: stats.layers + stats.missing, total: started.size, bytes: stats.layerBytes });
34
+ const throttle = limiter(maxConcurrentFetches);
35
+ // One budget for every layer body, charged as its bytes arrive, so fetches
36
+ // in parallel cannot each count on the whole remainder.
37
+ let heldBytes = 0;
38
+ const charge = (bytes, path) => {
39
+ heldBytes += bytes;
40
+ if (heldBytes > maxLayerBytes) {
41
+ throw resourceLimit(`layers exceed maxLayerBytes (${maxLayerBytes} bytes) at ${path}`);
42
+ }
43
+ };
44
+ // Re-fetched layers replace their earlier bytes, so count each path once.
45
+ const layerSizes = new Map();
46
+ // Speculative fetches by URL, dropped once composition is done. One that
47
+ // has not started when its layer is asked for, or that failed, gives way to
48
+ // the regular fetch, so the result is the same as without them. Their
49
+ // bytes are charged as they arrive, and stay charged once used.
50
+ const preloaded = new Map();
51
+ let composed = false;
52
+ // Every distinct layer URL requested, preloads included, for maxLayers.
53
+ const requested = new Set();
54
+ const startPreload = (layers) => {
55
+ let bytes = 0;
56
+ for (const { url, size } of layers) {
57
+ const key = urlKey(url);
58
+ bytes += size;
59
+ if (composed || bytes > maxLayerBytes) {
60
+ break;
61
+ }
62
+ if (requested.has(key)) {
63
+ continue;
64
+ }
65
+ if (requested.size >= maxLayers) {
66
+ break;
67
+ }
68
+ requested.add(key);
69
+ const entry = { started: false, charged: 0 };
70
+ preloaded.set(key, entry);
71
+ // Unused once composed: the next chunk cancels the body.
72
+ const budget = (bytes) => {
73
+ if (composed) {
74
+ throw new Error("composed without it");
75
+ }
76
+ entry.charged += bytes;
77
+ charge(bytes, url);
78
+ };
79
+ entry.bytes = throttle(async () => {
80
+ if (composed || preloaded.get(key) !== entry) {
81
+ return null;
82
+ }
83
+ entry.started = true;
84
+ const bytes = await fetchBytes(url, budget);
85
+ if (bytes) {
86
+ budget(bytes.byteLength - entry.charged);
87
+ }
88
+ return bytes;
89
+ }, { later: true }).catch(() => {
90
+ heldBytes -= entry.charged;
91
+ entry.charged = 0;
92
+ return null;
93
+ });
94
+ }
95
+ };
96
+ const takePreloaded = (path) => {
97
+ const entry = preloaded.get(urlKey(path));
98
+ preloaded.delete(urlKey(path));
99
+ return entry?.started ? entry : null;
100
+ };
101
+ // Jobs in flight. A job queues its dependencies here rather than awaiting
102
+ // them, so layers that reference each other cannot wait on each other.
103
+ const pending = [];
104
+ const drain = async () => {
105
+ while (pending.length) {
106
+ await Promise.all(pending.splice(0));
107
+ }
108
+ };
109
+ const fetchLayer = (path) => {
110
+ if (loader.has(path) || started.has(path)) {
111
+ return;
112
+ }
113
+ requested.add(urlKey(path));
114
+ if (requested.size > maxLayers) {
115
+ throw resourceLimit(`more than maxLayers (${maxLayers}) layer files at ${path}`);
116
+ }
117
+ const { refused } = requestPolicy(urlOf(path), rootUrl, allowedOrigins);
118
+ if (refused) {
119
+ started.set(path, Promise.resolve());
120
+ stats.missing++;
121
+ stats.warnings.push({ code: "layer-missing", message: `layer not fetched: ${refused}`, path });
122
+ loader.markUnavailable(path);
123
+ progress();
124
+ return;
125
+ }
126
+ const job = (async () => {
127
+ const t0 = performance.now();
128
+ heldBytes -= layerSizes.get(path) ?? 0;
129
+ layerSizes.delete(path);
130
+ let charged = 0;
131
+ const budget = (bytes) => {
132
+ charged += bytes;
133
+ charge(bytes, path);
134
+ };
135
+ // Any fetch failure, HTTP or network: the root fails the load, any
136
+ // other layer is left out with a warning.
137
+ let bytes = null;
138
+ let failure = null;
139
+ try {
140
+ const entry = takePreloaded(path);
141
+ bytes = entry && (await entry.bytes);
142
+ if (entry && bytes) {
143
+ charged = entry.charged;
144
+ }
145
+ bytes ??= await throttle(() => fetchBytes(urlOf(path), budget));
146
+ }
147
+ catch (error) {
148
+ heldBytes -= charged;
149
+ // HTTP errors carry a status; network errors are TypeErrors (as from fetch).
150
+ if (error?.status === undefined && !(error instanceof TypeError)) {
151
+ throw error;
152
+ }
153
+ failure = error;
154
+ }
155
+ stats.fetchMs = Math.max(stats.fetchMs, performance.now() - t0);
156
+ if (!bytes) {
157
+ if (path === root) {
158
+ const status = failure?.status ?? (failure ? undefined : 404);
159
+ throw new UsdLoadError("fetch", `could not fetch ${rootUrl}${status ? ` (HTTP ${status})` : ""}`, {
160
+ url: rootUrl,
161
+ status,
162
+ cause: failure ?? undefined,
163
+ });
164
+ }
165
+ stats.missing++;
166
+ stats.warnings.push({
167
+ code: "layer-missing",
168
+ message: `layer not found: ${failure?.message ?? urlOf(path)}`,
169
+ path: urlOf(path),
170
+ });
171
+ loader.markUnavailable(path);
172
+ progress();
173
+ return;
174
+ }
175
+ charge(bytes.byteLength - charged, path);
176
+ layerSizes.set(path, bytes.byteLength);
177
+ stats.layers++;
178
+ stats.layerBytes += bytes.byteLength;
179
+ const t1 = performance.now();
180
+ let deps;
181
+ try {
182
+ deps = loader.addLayer(path, bytes);
183
+ }
184
+ catch (error) {
185
+ // After a trap the module is unusable: the load fails.
186
+ if (isTrap(error)) {
187
+ throw error;
188
+ }
189
+ // An unreadable layer is left out; composition carries on without it.
190
+ stats.warnings.push({
191
+ code: "layer-unreadable",
192
+ message: String(error.message || error),
193
+ path: urlOf(path),
194
+ });
195
+ loader.markUnavailable(path);
196
+ progress();
197
+ return;
198
+ }
199
+ finally {
200
+ stats.parseMs += performance.now() - t1;
201
+ }
202
+ progress();
203
+ for (const dep of deps) {
204
+ fetchLayer(dep);
205
+ }
206
+ })();
207
+ started.set(path, job);
208
+ pending.push(job);
209
+ };
210
+ fetchLayer(root);
211
+ // A root without dependencies needs nothing else from its directory.
212
+ const rootHasDependencies = () => (started.get(root) ?? Promise.resolve()).then(() => started.size > 1, () => false);
213
+ preload?.then(async ({ layers, eager }) => (eager || (await rootHasDependencies())) && startPreload(layers));
214
+ await drain();
215
+ if (!loader.has(root)) {
216
+ const reason = stats.warnings.find((w) => w.path === rootUrl)?.message;
217
+ throw new UsdLoadError("compose", `could not read ${rootUrl}${reason ? `: ${reason}` : ""}`, { url: rootUrl });
218
+ }
219
+ for (;;) {
220
+ stats.rounds++;
221
+ onProgress({ stage: "compose", round: stats.rounds });
222
+ const t0 = performance.now();
223
+ const missing = loader.compose(root, maxInstances);
224
+ stats.composeMs += performance.now() - t0;
225
+ if (!missing.length) {
226
+ break;
227
+ }
228
+ if (stats.rounds > 16) {
229
+ throw new UsdLoadError("compose", `composition still missing layers: ${missing.join(", ")}`);
230
+ }
231
+ // The list also names layers the failed attempt consumed; fetch them again.
232
+ for (const path of missing) {
233
+ started.delete(path);
234
+ }
235
+ missing.forEach(fetchLayer);
236
+ await drain();
237
+ }
238
+ composed = true;
239
+ const scene = loader.takeScene();
240
+ loader.free();
241
+ const meta = JSON.parse(scene.meta());
242
+ return { scene, meta, stats };
243
+ }
244
+ /**
245
+ * What the page is told about a failed load. Fetch and resource-limit errors
246
+ * keep their code, url and status; anything the WASM side throws is a
247
+ * composition failure. Running out of WASM memory (4 GiB at most) reads as a
248
+ * scene too large to load: an allocation that fails while reading a layer
249
+ * reports "out of memory", one that aborts traps as a bare `unreachable`. A
250
+ * Rust panic, which also traps as `unreachable`, gives its message instead,
251
+ * read with `lastPanic` (the module's export). Overflowing the stack, the WASM one (an
252
+ * out-of-bounds access) or the engine's, means layers nested too deeply to read.
253
+ */
254
+ export function loadFailure(error, wasmMemoryBytes, lastPanic) {
255
+ const { code = "compose", url, status } = (error ?? {});
256
+ const message = String(error?.message || error);
257
+ const failure = (detail) => ({ code, message: detail, url, status });
258
+ if (code !== "compose") {
259
+ return failure(message);
260
+ }
261
+ const tooLarge = () => failure(`scene too large to load: ran out of memory (${(wasmMemoryBytes / 2 ** 30).toFixed(1)} GiB of WebAssembly memory in use): ${message}`);
262
+ if (OUT_OF_MEMORY.test(message) || (error instanceof WebAssembly.RuntimeError && wasmMemoryBytes > 3 * 2 ** 30)) {
263
+ return tooLarge();
264
+ }
265
+ if (!isTrap(error)) {
266
+ return failure(message);
267
+ }
268
+ const panic = readPanic(lastPanic);
269
+ if (panic) {
270
+ return failure(`${message}: ${panic}`);
271
+ }
272
+ if (/out of bounds|call stack|recursion/i.test(message)) {
273
+ return failure(`stack overflow: the layers nest too deeply to read (${message})`);
274
+ }
275
+ // Rust aborts on a failed allocation without a panic: a bare `unreachable`.
276
+ if (/unreachable/i.test(message)) {
277
+ return tooLarge();
278
+ }
279
+ return failure(message);
280
+ }
281
+ /** Messages of allocations that failed, in Rust or in the engine. */
282
+ export const OUT_OF_MEMORY = /out of memory|memory allocation|allocation failed|memory size exceeded|could not allocate/i;
283
+ /** Reading the panic calls into the trapped module, which can trap again (an exhausted stack does). */
284
+ function readPanic(lastPanic) {
285
+ try {
286
+ return lastPanic?.();
287
+ }
288
+ catch {
289
+ return undefined;
290
+ }
291
+ }
292
+ /** A WebAssembly trap or an exhausted engine call stack: the module is no longer usable. */
293
+ function isTrap(error) {
294
+ return (error instanceof WebAssembly.RuntimeError ||
295
+ error instanceof RangeError ||
296
+ error?.name === "InternalError");
297
+ }
298
+ function resourceLimit(detail) {
299
+ return new UsdLoadError("fetch", `resource limit exceeded: ${detail}`);
300
+ }
301
+ /** Runs at most `max` of the given tasks at once; tasks marked `later` wait for the others. */
302
+ export function limiter(max) {
303
+ let active = 0;
304
+ const queue = [];
305
+ const later = [];
306
+ const next = () => {
307
+ if (active >= max) {
308
+ return;
309
+ }
310
+ const job = queue.shift() ?? later.shift();
311
+ if (!job) {
312
+ return;
313
+ }
314
+ active++;
315
+ const { task, resolve, reject } = job;
316
+ task()
317
+ .then(resolve, reject)
318
+ .finally(() => {
319
+ active--;
320
+ next();
321
+ });
322
+ };
323
+ return (task, { later: low = false } = {}) => new Promise((resolve, reject) => {
324
+ (low ? later : queue).push({ task, resolve: resolve, reject });
325
+ next();
326
+ });
327
+ }
328
+ /** A layer URL as fetch would spell it, so an authored `a b.usd` matches a listed `a%20b.usd`. */
329
+ function urlKey(url) {
330
+ try {
331
+ return new URL(url).href;
332
+ }
333
+ catch {
334
+ return url;
335
+ }
336
+ }
337
+ /**
338
+ * Fetches a body, passing each chunk's size to `budget` as it arrives and
339
+ * giving up (cancelling the body) when `budget` throws. An HTTP error throws a
340
+ * `fetch` UsdLoadError carrying the status. `fetchFn` is the global fetch or a
341
+ * stand-in with the same contract. Rate limiting (429) and server errors
342
+ * (5xx) are retried with backoff, as the Hub answers bursts with 429.
343
+ */
344
+ export async function fetchLimited(url, budget, { fetchFn = fetch, retries = 3, retryDelayMs = 500, } = {}) {
345
+ let response = await fetchFn(url);
346
+ for (let attempt = 0; attempt < retries && (response.status === 429 || response.status >= 500); attempt++) {
347
+ response.body?.cancel().catch(() => { });
348
+ const retryAfterMs = Number(response.headers?.get("retry-after")) * 1000;
349
+ const delay = retryAfterMs > 0 ? Math.min(retryAfterMs, 10_000) : retryDelayMs * 2 ** attempt * (1 + Math.random());
350
+ await new Promise((resolve) => setTimeout(resolve, delay));
351
+ response = await fetchFn(url);
352
+ }
353
+ if (!response.ok) {
354
+ throw new UsdLoadError("fetch", `HTTP ${response.status} for ${url}`, { url, status: response.status });
355
+ }
356
+ if (!response.body) {
357
+ return new Uint8Array();
358
+ }
359
+ const reader = response.body.getReader();
360
+ const chunks = [];
361
+ let size = 0;
362
+ for (;;) {
363
+ const { done, value } = await reader.read();
364
+ if (done) {
365
+ break;
366
+ }
367
+ try {
368
+ budget(value.byteLength);
369
+ }
370
+ catch (error) {
371
+ await reader.cancel();
372
+ throw error;
373
+ }
374
+ size += value.byteLength;
375
+ chunks.push(value);
376
+ }
377
+ const out = new Uint8Array(size);
378
+ let offset = 0;
379
+ for (const chunk of chunks) {
380
+ out.set(chunk, offset);
381
+ offset += chunk.byteLength;
382
+ }
383
+ return out;
384
+ }
385
+ /**
386
+ * Size of a PNG, JPEG or WebP from its header, without decoding, and whether
387
+ * it is color: 8-bit RGB(A) or palette, rather than greyscale or 16-bit data
388
+ * (the images `sourceColorSpace = "auto"` decodes as sRGB; WebP is always
389
+ * color). Null for other formats, whose size cannot be checked before decoding.
390
+ */
391
+ export function imageInfo(b) {
392
+ const v = new DataView(b.buffer, b.byteOffset, b.byteLength);
393
+ const ascii = (at, text) => [...text].every((c, i) => b[at + i] === c.charCodeAt(0));
394
+ if (b.length > 25 && b[0] === 0x89 && ascii(1, "PNG")) {
395
+ const [bitDepth, colorType] = [b[24], b[25]];
396
+ const color = colorType === 3 || (bitDepth === 8 && (colorType === 2 || colorType === 6));
397
+ return { width: v.getUint32(16), height: v.getUint32(20), color };
398
+ }
399
+ if (b[0] === 0xff && b[1] === 0xd8) {
400
+ let i = 2;
401
+ while (i + 9 < b.length) {
402
+ if (b[i] !== 0xff) {
403
+ return null;
404
+ }
405
+ const marker = b[i + 1];
406
+ const length = (b[i + 2] << 8) | b[i + 3];
407
+ const isFrame = marker >= 0xc0 && marker <= 0xcf && marker !== 0xc4 && marker !== 0xc8 && marker !== 0xcc;
408
+ if (isFrame) {
409
+ return {
410
+ height: (b[i + 5] << 8) | b[i + 6],
411
+ width: (b[i + 7] << 8) | b[i + 8],
412
+ color: b[i + 4] === 8 && b[i + 9] >= 3,
413
+ };
414
+ }
415
+ i += 2 + length;
416
+ }
417
+ return null;
418
+ }
419
+ if (b.length >= 30 && ascii(0, "RIFF") && ascii(8, "WEBP")) {
420
+ // The first chunk: lossy (VP8), lossless (VP8L) or extended (VP8X).
421
+ if (ascii(12, "VP8 ")) {
422
+ return { width: v.getUint16(26, true) & 0x3fff, height: v.getUint16(28, true) & 0x3fff, color: true };
423
+ }
424
+ if (ascii(12, "VP8L")) {
425
+ const bits = v.getUint32(21, true);
426
+ return { width: (bits & 0x3fff) + 1, height: ((bits >>> 14) & 0x3fff) + 1, color: true };
427
+ }
428
+ if (ascii(12, "VP8X")) {
429
+ const u24 = (at) => b[at] | (b[at + 1] << 8) | (b[at + 2] << 16);
430
+ return { width: u24(24) + 1, height: u24(27) + 1, color: true };
431
+ }
432
+ }
433
+ return null;
434
+ }
435
+ // A trailing dot names the same host (`huggingface.co.`), so it matches too.
436
+ const HUB_HOST = /^(huggingface\.co|hf\.co)\.?$/;
437
+ const HUB_CDN = /\.hf\.co\.?$/;
438
+ // Paths of Hub repo files, of the tree listing the prefetch reads and of the
439
+ // revision lookup that pins a load to one commit: the only Hub URLs a load
440
+ // requests, never other `/api/*` endpoints or account pages. The last group is
441
+ // the revision.
442
+ const HUB_FILE = /^\/(?:(datasets|spaces)\/)?([\w.-]+)\/([\w.-]+)\/resolve\/([^/]*)/;
443
+ const HUB_TREE = /^\/api\/(datasets|models|spaces)\/([\w.-]+)\/([\w.-]+)\/(?:tree|revision)\/([^/]*)/;
444
+ // First path segments of Hub pages and endpoints: never a model's owner.
445
+ const HUB_RESERVED = new Set([
446
+ "api",
447
+ "oauth",
448
+ "settings",
449
+ "login",
450
+ "logout",
451
+ "join",
452
+ "docs",
453
+ "models",
454
+ "datasets",
455
+ "spaces",
456
+ "organizations",
457
+ "new",
458
+ "pricing",
459
+ "blog",
460
+ "papers",
461
+ "posts",
462
+ "collections",
463
+ "notifications",
464
+ "search",
465
+ "chat",
466
+ "learn",
467
+ "tasks",
468
+ "enterprise",
469
+ "billing",
470
+ "static-proxy",
471
+ "avatars",
472
+ "front",
473
+ ]);
474
+ /** The path match of a Hub file or tree-listing URL (`[, type, owner, repo, revision]`), else null. */
475
+ function hubMatch(url) {
476
+ if (!HUB_HOST.test(url.hostname) || url.protocol !== "https:") {
477
+ return null;
478
+ }
479
+ const file = url.pathname.match(HUB_FILE);
480
+ if (file && (file[1] || !HUB_RESERVED.has(file[2].toLowerCase()))) {
481
+ return file;
482
+ }
483
+ return url.pathname.match(HUB_TREE);
484
+ }
485
+ /** `type/owner/repo` of a Hub file or tree-listing URL, else null. */
486
+ function hubRepo(url) {
487
+ const match = hubMatch(url);
488
+ return match && `${match[1] ?? "models"}/${match[2]}/${match[3]}`;
489
+ }
490
+ /**
491
+ * A URL on hf.co, the Hub's short domain, as the huggingface.co URL it
492
+ * redirects to: fetched directly, a request keeps its headers (a redirect
493
+ * to another origin drops them) and its credentials scope stays the same.
494
+ */
495
+ export function canonicalUrl(url) {
496
+ try {
497
+ const parsed = new URL(url);
498
+ if (!/^hf\.co\.?$/.test(parsed.hostname)) {
499
+ return url;
500
+ }
501
+ parsed.hostname = "huggingface.co";
502
+ return parsed.href;
503
+ }
504
+ catch {
505
+ return url;
506
+ }
507
+ }
508
+ /** The scheme of files given with the `files` option: `local:///<key>`, the key percent-encoded. */
509
+ export const LOCAL = "local:";
510
+ /** A `files` key as the load spells it: `/` separators, no leading `./` or `/`. */
511
+ export function localKey(key) {
512
+ return key.replace(/\\/g, "/").replace(/^(?:\.?\/)+/, "");
513
+ }
514
+ /** The URL a `files` key loads as; relative asset paths in the file resolve against it. */
515
+ export function localUrl(key) {
516
+ return `${LOCAL}///${localKey(key).split("/").map(encodeURIComponent).join("/")}`;
517
+ }
518
+ /** The `files` key a `local:` URL names. */
519
+ export function keyOfLocalUrl(url) {
520
+ return decodeURIComponent(new URL(url).pathname.slice(1));
521
+ }
522
+ /**
523
+ * How a load rooted at `rootUrl` may request `url`: `{ refused }` with the
524
+ * reason, or the fetch options to use. Every request a load makes goes
525
+ * through this first, then through {@link fetchWithPolicy}. Only the
526
+ * requested URL is checked: fetches follow redirects (a Hub `resolve` URL
527
+ * redirects to its CDN, which the Hub controls), but never with the caller's
528
+ * headers off the Hub.
529
+ *
530
+ * - hf.co URLs are checked as the huggingface.co URLs they redirect to.
531
+ * - The root URL itself, as the caller gave it, is always allowed.
532
+ * - A `local:` root (the `files` option) may read other `local:` URLs, which
533
+ * are looked up in its files and never fetched; no other root may.
534
+ * - Only http(s), with no user name or password in the URL.
535
+ * - Origins: the root's, those in `allowedOrigins` (`'*'` for any) and, for a
536
+ * root on the Hugging Face Hub, the Hub and its CDN hosts.
537
+ * - On huggingface.co and hf.co, only repo files (`…/resolve/…`) and tree
538
+ * listings, under a user or organization name (not `/api/…`, `/oauth/…`
539
+ * and other Hub pages), with no encoded slashes outside the revision (a
540
+ * pull request's is `refs%2Fpr%2F1`).
541
+ * - Credentials (cookies and the caller's headers) go only to the root's own
542
+ * origin or, for a Hub root, only to the root's own repo.
543
+ */
544
+ export function requestPolicy(url, rootUrl, allowedOrigins = []) {
545
+ const refused = refusal(canonicalUrl(url), canonicalUrl(rootUrl), allowedOrigins);
546
+ if (refused) {
547
+ return { refused };
548
+ }
549
+ return {
550
+ credentials: credentialed(new URL(canonicalUrl(url)), new URL(canonicalUrl(rootUrl))) ? "same-origin" : "omit",
551
+ referrerPolicy: "no-referrer",
552
+ };
553
+ }
554
+ function refusal(url, rootUrl, allowedOrigins) {
555
+ if (url === rootUrl) {
556
+ return null;
557
+ }
558
+ let target;
559
+ try {
560
+ target = new URL(url);
561
+ }
562
+ catch {
563
+ return `not a URL: ${url}`;
564
+ }
565
+ const root = new URL(rootUrl);
566
+ if (root.protocol === LOCAL && target.protocol === LOCAL) {
567
+ return null;
568
+ }
569
+ if (target.protocol !== "http:" && target.protocol !== "https:") {
570
+ return `only http(s) URLs are fetched: ${url}`;
571
+ }
572
+ if (target.username || target.password) {
573
+ return `URLs with credentials are not fetched: ${url}`;
574
+ }
575
+ const hub = HUB_HOST.test(target.hostname);
576
+ if (hub && !hubFile(target)) {
577
+ return `only Hub repo files are fetched from ${target.host}: ${url}`;
578
+ }
579
+ const fromHub = HUB_HOST.test(root.hostname) && (hub || HUB_CDN.test(target.hostname)) && target.protocol === "https:";
580
+ if (target.origin === root.origin ||
581
+ fromHub ||
582
+ allowedOrigins.includes("*") ||
583
+ allowedOrigins.includes(target.origin)) {
584
+ return null;
585
+ }
586
+ return `its origin is not in allowedOrigins: ${url}`;
587
+ }
588
+ /** A Hub repo file or tree listing with no encoded slash or backslash, but for a `%2F` in its revision. */
589
+ function hubFile(url) {
590
+ const match = hubMatch(url);
591
+ if (!match) {
592
+ return false;
593
+ }
594
+ const revisionStart = match[0].length - match[4].length;
595
+ const outside = url.pathname.slice(0, revisionStart) + url.pathname.slice(match[0].length);
596
+ return !/%2f|%5c/i.test(outside) && !/%5c/i.test(match[4]);
597
+ }
598
+ function credentialed(target, root) {
599
+ // Every `local:` URL's origin is the string "null", which would match any other's.
600
+ if (root.protocol === LOCAL) {
601
+ return false;
602
+ }
603
+ if (target.origin !== root.origin) {
604
+ return false;
605
+ }
606
+ const repo = hubRepo(root);
607
+ return HUB_HOST.test(root.hostname) ? !!repo && hubRepo(target) === repo : true;
608
+ }
609
+ /**
610
+ * Fetches `url` under `policy` (see {@link requestPolicy}), sending `headers`
611
+ * only where credentials may go. A request carrying them does not follow a
612
+ * redirect with them: unless it is on the Hub (whose redirects stay on its own
613
+ * hosts), it is not followed, and the URL is fetched again without headers or
614
+ * cookies, for the browser to follow.
615
+ */
616
+ export async function fetchWithPolicy(url, policy, headers) {
617
+ const sendHeaders = policy.credentials === "same-origin" && !!headers && Object.keys(headers).length > 0;
618
+ if (!sendHeaders) {
619
+ return fetch(url, policy);
620
+ }
621
+ if (HUB_HOST.test(new URL(url).hostname)) {
622
+ return fetch(url, { ...policy, headers });
623
+ }
624
+ const response = await fetch(url, { ...policy, headers, redirect: "manual" });
625
+ if (response.type !== "opaqueredirect" && !(response.status >= 300 && response.status < 400)) {
626
+ return response;
627
+ }
628
+ response.body?.cancel().catch(() => { });
629
+ return fetch(url, { ...policy, credentials: "omit" });
630
+ }
631
+ /**
632
+ * Reads each geometry out of WASM in turn, so only one mesh's arrays are in
633
+ * WASM memory at a time, and calls `onGeometry(index, meta, arrays)` with
634
+ * JS-owned typed arrays (`meta` and `arrays` are null for a mesh with nothing
635
+ * drawable, or left out). Triangles count as drawn, once per instance:
636
+ * meshes that would take them past `maxTriangles` are left out unread.
637
+ * Releases the stage afterwards. Returns warnings: `triangle-limit` for
638
+ * meshes left out, `nothing-drawable` when no mesh had anything to draw.
639
+ */
640
+ export function readGeometries(scene, meta, onGeometry, { maxTriangles = DEFAULTS.maxTriangles } = {}) {
641
+ const instances = Array.from({ length: meta.geometryCount }, () => 0);
642
+ for (const { geometry } of meta.instances) {
643
+ instances[geometry]++;
644
+ }
645
+ let drawn = 0;
646
+ let left = maxTriangles;
647
+ const skipped = [];
648
+ for (let i = 0; i < meta.geometryCount; i++) {
649
+ // Not drawn anywhere (e.g. all its instances past maxInstances).
650
+ if (!instances[i]) {
651
+ onGeometry(i, null, null);
652
+ continue;
653
+ }
654
+ const json = scene.read(i, Math.min(Math.floor(left / instances[i]), 2 ** 32 - 1));
655
+ const g = json && JSON.parse(json);
656
+ if (!g || "overBudget" in g) {
657
+ if (g) {
658
+ skipped.push(g.path);
659
+ }
660
+ onGeometry(i, null, null);
661
+ continue;
662
+ }
663
+ drawn++;
664
+ left = Math.max(0, left - instances[i] * g.groups.reduce((n, [, count]) => n + count / 3, 0));
665
+ onGeometry(i, g, {
666
+ positions: scene.positions(),
667
+ normals: scene.normals(),
668
+ uvs: g.uvSets.map((_, k) => scene.uvs(k)),
669
+ colors: g.hasColors ? scene.colors() : null,
670
+ indices: g.maxIndex < 65536 ? scene.indices16() : scene.indices(),
671
+ });
672
+ }
673
+ scene.finish();
674
+ const warnings = [];
675
+ if (skipped.length) {
676
+ warnings.push({
677
+ code: "triangle-limit",
678
+ message: `${skipped.length} meshes left out: past maxTriangles (${maxTriangles}) drawn`,
679
+ path: skipped[0],
680
+ });
681
+ }
682
+ if (!drawn) {
683
+ warnings.push({
684
+ code: "nothing-drawable",
685
+ message: "nothing to draw: the stage has no visible meshes with geometry",
686
+ });
687
+ }
688
+ return warnings;
689
+ }
690
+ /**
691
+ * Reads the colliders of a scene composed with `physics` (`SceneMeta.physics.colliderCount`), one at a time, and calls
692
+ * `onCollider(index, meta, arrays)` with JS-owned typed arrays: its points as authored and its faces fan-triangulated.
693
+ * Reads nothing for a scene composed without it. Call it before `scene.free()`; each collider reads once.
694
+ */
695
+ export function readColliders(scene, onCollider) {
696
+ const count = scene.colliderCount();
697
+ for (let i = 0; i < count; i++) {
698
+ const meta = JSON.parse(scene.readCollider(i));
699
+ onCollider(i, meta, { points: scene.positions(), indices: scene.indices() });
700
+ }
701
+ return count;
702
+ }
703
+ /**
704
+ * Images stored inside a USDZ package (they cannot be fetched by URL) among
705
+ * the texture `jobs` (see {@link textureJobs}), each read once, by path, all
706
+ * together at most `maxBytes`. One that cannot be read maps to its error, so
707
+ * it fails as that texture rather than the whole load.
708
+ */
709
+ export function takePackagedTextures(scene, jobs, { maxBytes = Infinity } = {}) {
710
+ const out = new Map();
711
+ let left = maxBytes;
712
+ for (const { path } of jobs) {
713
+ if (!path.includes("[")) {
714
+ continue;
715
+ }
716
+ try {
717
+ const bytes = scene.packagedFile(path, left);
718
+ if (bytes) {
719
+ out.set(path, bytes);
720
+ }
721
+ left -= bytes?.byteLength ?? 0;
722
+ }
723
+ catch (error) {
724
+ out.set(path, error);
725
+ }
726
+ }
727
+ return out;
728
+ }
729
+ /** Long-side cap for data maps (roughness, metallic, occlusion, ...) in `preview` mode. */
730
+ const PREVIEW_DATA_SIZE = 512;
731
+ /**
732
+ * The texture files to load and the size to decode each to, base colors first.
733
+ * `preview`: base color up to `maxSize`, other maps up to 512 px, no normal
734
+ * maps. `full`: every map, including normals, up to `maxSize`. `none`: nothing.
735
+ */
736
+ export function textureJobs(meta, { textures, maxSize }) {
737
+ if (textures === "none") {
738
+ return [];
739
+ }
740
+ const full = textures === "full";
741
+ const dataSize = full ? maxSize : Math.min(maxSize, PREVIEW_DATA_SIZE);
742
+ const tiers = [
743
+ [["diffuseColor"], maxSize],
744
+ [["opacity", "emissiveColor", "roughness", "metallic", "occlusion"], dataSize],
745
+ [full ? ["normal"] : [], maxSize],
746
+ ];
747
+ const jobs = new Map();
748
+ for (const [inputs, size] of tiers) {
749
+ for (const m of meta.materials) {
750
+ for (const input of inputs) {
751
+ const path = m.maps[input]?.path;
752
+ // A file shared by several inputs is decoded once, at the largest size asked.
753
+ if (path) {
754
+ jobs.set(path, Math.max(jobs.get(path) ?? 0, size));
755
+ }
756
+ }
757
+ }
758
+ }
759
+ return [...jobs].map(([path, size]) => ({ path, size }));
760
+ }
services/explorer/dist/static/usd-reader/81290bc/esm/worker.js ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Loads, composes and extracts a USD stage off the main thread, then streams
2
+ // textures as downscaled ImageBitmaps. One worker per load: the page
3
+ // terminates it when done, disposed or aborted, which releases all WASM memory.
4
+ import init, { lastPanic, UsdLoader } from "../wasm/usd_wasm.js";
5
+ import { hubPackageLayers, pinHubRevision } from "./hub-prefetch.js";
6
+ import { DEFAULTS, LOCAL, canonicalUrl, composeStage, fetchLimited, fetchWithPolicy, imageInfo, keyOfLocalUrl, limiter, loadFailure, readColliders, readGeometries, requestPolicy, takePackagedTextures, textureJobs, } from "./load-core.js";
7
+ // Textures in flight at once (fetch and decode): decoding a large image
8
+ // briefly holds it at full size, so wide parallelism spikes memory.
9
+ const TEXTURE_CONCURRENCY = 4;
10
+ // Longest side of an image read at all: larger ones are refused from their
11
+ // header, before decoding (WebGL's own limit is commonly 16384 too).
12
+ const MAX_IMAGE_SIZE = DEFAULTS.maxImageSize;
13
+ self.onmessage = async ({ data }) => {
14
+ const { url, wasmModule, maxTextureSize = DEFAULTS.maxTextureSize, textures = DEFAULTS.textures, maxConcurrentFetches = DEFAULTS.maxConcurrentFetches, maxLayerBytes, maxTextureBytes = DEFAULTS.maxTextureBytes, maxLayers, maxInstances, maxTriangles, allowedOrigins, headers, files, physics, } = data;
15
+ // Every request (layer, texture, Hub listing) goes through here, and
16
+ // through the request policy first. The caller's headers go only where
17
+ // cookies may, and never through a redirect off the Hub.
18
+ const request = async (target) => {
19
+ target = canonicalUrl(target);
20
+ const policy = requestPolicy(target, url, allowedOrigins);
21
+ // Reads like a network failure: a missing layer or a failed texture.
22
+ if (policy.refused !== undefined) {
23
+ throw new TypeError(`request refused: ${policy.refused}`);
24
+ }
25
+ if (target.startsWith(LOCAL)) {
26
+ const file = files?.get(keyOfLocalUrl(target));
27
+ return file ? new Response(file) : new Response(null, { status: 404 });
28
+ }
29
+ return fetchWithPolicy(target, policy, headers);
30
+ };
31
+ const fetchBytes = (target, budget) => fetchLimited(target, budget, { fetchFn: request });
32
+ // One budget for every texture, packaged ones first, then each fetched
33
+ // body as its bytes arrive. Bytes of a body cut short stay charged: they
34
+ // were downloaded.
35
+ let textureBytes = 0;
36
+ const chargeTexture = (bytes) => {
37
+ textureBytes += bytes;
38
+ if (textureBytes > maxTextureBytes) {
39
+ throw new Error(`textures exceed maxTextureBytes (${maxTextureBytes} bytes)`);
40
+ }
41
+ };
42
+ const progress = (p) => self.postMessage({ type: "progress", progress: p });
43
+ let wasmMemory;
44
+ try {
45
+ const t0 = performance.now();
46
+ // Looked up while the WASM module initializes.
47
+ const rootUrl = pinHubRevision(url, request);
48
+ const preload = rootUrl.then((root) => hubPackageLayers(root, request));
49
+ const wasm = await init({ module_or_path: wasmModule });
50
+ wasmMemory = wasm.memory;
51
+ const tInit = performance.now();
52
+ const { scene, meta, stats } = await composeStage({
53
+ UsdLoader,
54
+ fetchBytes,
55
+ rootUrl: await rootUrl,
56
+ maxConcurrentFetches,
57
+ maxLayerBytes,
58
+ maxLayers,
59
+ maxInstances,
60
+ allowedOrigins,
61
+ preload,
62
+ onProgress: progress,
63
+ physics: physics?.namespaces,
64
+ });
65
+ stats.initMs = tInit - t0;
66
+ self.postMessage({ type: "meta", meta });
67
+ // One mesh at a time: each is transferred (not copied) as soon as it is read.
68
+ const onGeometry = (index, g, arrays) => {
69
+ const transfer = arrays
70
+ ? [arrays.positions, arrays.normals, arrays.colors, arrays.indices, ...arrays.uvs]
71
+ .filter((a) => !!a)
72
+ .map((a) => a.buffer)
73
+ : [];
74
+ self.postMessage({ type: "geometry", index, meta: g, arrays }, transfer);
75
+ progress({ stage: "geometry", loaded: index + 1, total: meta.geometryCount });
76
+ };
77
+ const warnings = readGeometries(scene, meta, onGeometry, { maxTriangles });
78
+ // Then the colliders (only when asked for), each transferred as it is read.
79
+ readColliders(scene, (index, c, arrays) => self.postMessage({ type: "collider", index, meta: c, arrays }, [arrays.points.buffer, arrays.indices.buffer]));
80
+ const jobs = textureJobs(meta, { textures, maxSize: maxTextureSize });
81
+ const packaged = takePackagedTextures(scene, jobs, { maxBytes: maxTextureBytes });
82
+ for (const entry of packaged.values()) {
83
+ if (!(entry instanceof Error)) {
84
+ textureBytes += entry.byteLength;
85
+ }
86
+ }
87
+ scene.free();
88
+ stats.warnings.push(...warnings);
89
+ stats.totalMs = performance.now() - t0;
90
+ stats.wasmMemoryBytes = wasm.memory.buffer.byteLength;
91
+ self.postMessage({ type: "scene", stats: stats });
92
+ let loaded = 0;
93
+ let bytes = 0;
94
+ progress({ stage: "textures", loaded, total: jobs.length, bytes });
95
+ // The limiter runs jobs in order, so base colors come first.
96
+ const throttle = limiter(Math.min(maxConcurrentFetches, TEXTURE_CONCURRENCY));
97
+ await Promise.all(jobs.map(({ path, size }) => throttle(async () => {
98
+ try {
99
+ const entry = packaged.get(path);
100
+ if (entry instanceof Error) {
101
+ throw entry;
102
+ }
103
+ // A packaged path is never a URL to fetch.
104
+ if (!entry && path.includes("[")) {
105
+ throw new Error(`not found in its package: ${path}`);
106
+ }
107
+ const image = entry ?? (await fetchBytes(path, chargeTexture));
108
+ bytes += image.byteLength;
109
+ const { bitmap, color } = await decodeTexture(image, size);
110
+ self.postMessage({ type: "texture", path, bitmap, color }, [bitmap]);
111
+ }
112
+ catch (error) {
113
+ self.postMessage({ type: "texture", path, error: String(error?.message || error) });
114
+ }
115
+ progress({ stage: "textures", loaded: ++loaded, total: jobs.length, bytes });
116
+ })));
117
+ self.postMessage({ type: "done" });
118
+ }
119
+ catch (error) {
120
+ self.postMessage({ type: "error", ...loadFailure(error, wasmMemory?.buffer.byteLength ?? 0, lastPanic) });
121
+ }
122
+ };
123
+ /**
124
+ * Decodes a PNG, JPEG or WebP straight to at most `maxSize` px on its long
125
+ * side, and tells whether it holds color (what `sourceColorSpace = "auto"`
126
+ * decodes as sRGB). Images whose size the header does not give, or that are
127
+ * too large, are refused before decoding.
128
+ */
129
+ async function decodeTexture(bytes, maxSize) {
130
+ const info = imageInfo(bytes);
131
+ if (!info) {
132
+ throw new Error("unsupported image format: only PNG, JPEG and WebP are read");
133
+ }
134
+ if (Math.max(info.width, info.height) > MAX_IMAGE_SIZE) {
135
+ throw new Error(`image too large: ${info.width}x${info.height} (at most ${MAX_IMAGE_SIZE} px a side)`);
136
+ }
137
+ // USD texture coordinates put (0,0) at the bottom-left, three.js's default.
138
+ const options = {
139
+ imageOrientation: "flipY",
140
+ premultiplyAlpha: "none",
141
+ colorSpaceConversion: "none",
142
+ };
143
+ const scale = Math.min(1, maxSize / Math.max(info.width, info.height));
144
+ if (scale < 1) {
145
+ options.resizeWidth = Math.max(1, Math.round(info.width * scale));
146
+ options.resizeHeight = Math.max(1, Math.round(info.height * scale));
147
+ options.resizeQuality = "high";
148
+ }
149
+ return { bitmap: await createImageBitmap(new Blob([bytes]), options), color: info.color };
150
+ }
services/explorer/dist/static/usd-reader/81290bc/wasm/usd_wasm.js ADDED
@@ -0,0 +1,760 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* @ts-self-types="./usd_wasm.d.ts" */
2
+
3
+ export class UsdLoader {
4
+ __destroy_into_raw() {
5
+ const ptr = this.__wbg_ptr;
6
+ this.__wbg_ptr = 0;
7
+ UsdLoaderFinalization.unregister(this);
8
+ return ptr;
9
+ }
10
+ free() {
11
+ const ptr = this.__destroy_into_raw();
12
+ wasm.__wbg_usdloader_free(ptr, 0);
13
+ }
14
+ /**
15
+ * Stores a layer and returns the layers it names outside unselected
16
+ * variants (see [`Loader::add_layer`]).
17
+ * @param {string} path
18
+ * @param {Uint8Array} bytes
19
+ * @returns {string[]}
20
+ */
21
+ addLayer(path, bytes) {
22
+ try {
23
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
24
+ const ptr0 = passStringToWasm0(path, wasm.__wbindgen_export, wasm.__wbindgen_export2);
25
+ const len0 = WASM_VECTOR_LEN;
26
+ const ptr1 = passArray8ToWasm0(bytes, wasm.__wbindgen_export);
27
+ const len1 = WASM_VECTOR_LEN;
28
+ wasm.usdloader_addLayer(retptr, this.__wbg_ptr, ptr0, len0, ptr1, len1);
29
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
30
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
31
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
32
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
33
+ if (r3) {
34
+ throw takeObject(r2);
35
+ }
36
+ var v3 = getArrayJsValueFromWasm0(r0, r1);
37
+ wasm.__wbindgen_export3(r0, r1 * 4, 4);
38
+ return v3;
39
+ } finally {
40
+ wasm.__wbindgen_add_to_stack_pointer(16);
41
+ }
42
+ }
43
+ /**
44
+ * Composes the stage at `root`. Returns the layers still missing; when
45
+ * that is empty the scene is ready for [`take_scene`](Self::take_scene).
46
+ * The scene draws at most `max_instances` mesh instances.
47
+ * @param {string} root
48
+ * @param {number} max_instances
49
+ * @returns {string[]}
50
+ */
51
+ compose(root, max_instances) {
52
+ try {
53
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
54
+ const ptr0 = passStringToWasm0(root, wasm.__wbindgen_export, wasm.__wbindgen_export2);
55
+ const len0 = WASM_VECTOR_LEN;
56
+ wasm.usdloader_compose(retptr, this.__wbg_ptr, ptr0, len0, max_instances);
57
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
58
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
59
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
60
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
61
+ if (r3) {
62
+ throw takeObject(r2);
63
+ }
64
+ var v2 = getArrayJsValueFromWasm0(r0, r1);
65
+ wasm.__wbindgen_export3(r0, r1 * 4, 4);
66
+ return v2;
67
+ } finally {
68
+ wasm.__wbindgen_add_to_stack_pointer(16);
69
+ }
70
+ }
71
+ /**
72
+ * @param {string} path
73
+ * @returns {boolean}
74
+ */
75
+ has(path) {
76
+ const ptr0 = passStringToWasm0(path, wasm.__wbindgen_export, wasm.__wbindgen_export2);
77
+ const len0 = WASM_VECTOR_LEN;
78
+ const ret = wasm.usdloader_has(this.__wbg_ptr, ptr0, len0);
79
+ return ret !== 0;
80
+ }
81
+ /**
82
+ * @param {string} path
83
+ */
84
+ markUnavailable(path) {
85
+ const ptr0 = passStringToWasm0(path, wasm.__wbindgen_export, wasm.__wbindgen_export2);
86
+ const len0 = WASM_VECTOR_LEN;
87
+ wasm.usdloader_markUnavailable(this.__wbg_ptr, ptr0, len0);
88
+ }
89
+ constructor() {
90
+ const ret = wasm.usdloader_new();
91
+ this.__wbg_ptr = ret;
92
+ UsdLoaderFinalization.register(this, this.__wbg_ptr, this);
93
+ return this;
94
+ }
95
+ /**
96
+ * Also reads the stage's physics when composing (see
97
+ * [`Loader::set_physics`]); `namespaces` are the host's own attribute
98
+ * namespaces (`["simready"]`). The scene's meta then carries `physics`,
99
+ * and [`UsdScene::read_collider`] reads its colliders.
100
+ * @param {string[]} namespaces
101
+ */
102
+ setPhysics(namespaces) {
103
+ const ptr0 = passArrayJsValueToWasm0(namespaces, wasm.__wbindgen_export);
104
+ const len0 = WASM_VECTOR_LEN;
105
+ wasm.usdloader_setPhysics(this.__wbg_ptr, ptr0, len0);
106
+ }
107
+ /**
108
+ * Hands over the extracted scene and drops every stored layer.
109
+ * @returns {UsdScene}
110
+ */
111
+ takeScene() {
112
+ try {
113
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
114
+ wasm.usdloader_takeScene(retptr, this.__wbg_ptr);
115
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
116
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
117
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
118
+ if (r2) {
119
+ throw takeObject(r1);
120
+ }
121
+ return UsdScene.__wrap(r0);
122
+ } finally {
123
+ wasm.__wbindgen_add_to_stack_pointer(16);
124
+ }
125
+ }
126
+ }
127
+ if (Symbol.dispose) UsdLoader.prototype[Symbol.dispose] = UsdLoader.prototype.free;
128
+
129
+ /**
130
+ * A composed scene whose meshes are read one at a time: `read(i)` makes
131
+ * geometry `i` current, and the array getters move its data out (each once).
132
+ * Only the current mesh's arrays live in WASM memory at any time.
133
+ */
134
+ export class UsdScene {
135
+ static __wrap(ptr) {
136
+ const obj = Object.create(UsdScene.prototype);
137
+ obj.__wbg_ptr = ptr;
138
+ UsdSceneFinalization.register(obj, obj.__wbg_ptr, obj);
139
+ return obj;
140
+ }
141
+ __destroy_into_raw() {
142
+ const ptr = this.__wbg_ptr;
143
+ this.__wbg_ptr = 0;
144
+ UsdSceneFinalization.unregister(this);
145
+ return ptr;
146
+ }
147
+ free() {
148
+ const ptr = this.__destroy_into_raw();
149
+ wasm.__wbg_usdscene_free(ptr, 0);
150
+ }
151
+ /**
152
+ * How many colliders the scene's physics holds (0 when it was not read).
153
+ * @returns {number}
154
+ */
155
+ colliderCount() {
156
+ const ret = wasm.usdscene_colliderCount(this.__wbg_ptr);
157
+ return ret >>> 0;
158
+ }
159
+ /**
160
+ * @returns {Float32Array}
161
+ */
162
+ colors() {
163
+ try {
164
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
165
+ wasm.usdscene_colors(retptr, this.__wbg_ptr);
166
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
167
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
168
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
169
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
170
+ if (r3) {
171
+ throw takeObject(r2);
172
+ }
173
+ var v1 = getArrayF32FromWasm0(r0, r1).slice();
174
+ wasm.__wbindgen_export3(r0, r1 * 4, 4);
175
+ return v1;
176
+ } finally {
177
+ wasm.__wbindgen_add_to_stack_pointer(16);
178
+ }
179
+ }
180
+ /**
181
+ * Releases the stage once every geometry has been read.
182
+ */
183
+ finish() {
184
+ wasm.usdscene_finish(this.__wbg_ptr);
185
+ }
186
+ /**
187
+ * Indices as 16-bit, for geometries with fewer than 65536 vertices.
188
+ * @returns {Uint16Array}
189
+ */
190
+ indices16() {
191
+ try {
192
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
193
+ wasm.usdscene_indices16(retptr, this.__wbg_ptr);
194
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
195
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
196
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
197
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
198
+ if (r3) {
199
+ throw takeObject(r2);
200
+ }
201
+ var v1 = getArrayU16FromWasm0(r0, r1).slice();
202
+ wasm.__wbindgen_export3(r0, r1 * 2, 2);
203
+ return v1;
204
+ } finally {
205
+ wasm.__wbindgen_add_to_stack_pointer(16);
206
+ }
207
+ }
208
+ /**
209
+ * @returns {Uint32Array}
210
+ */
211
+ indices() {
212
+ try {
213
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
214
+ wasm.usdscene_indices(retptr, this.__wbg_ptr);
215
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
216
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
217
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
218
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
219
+ if (r3) {
220
+ throw takeObject(r2);
221
+ }
222
+ var v1 = getArrayU32FromWasm0(r0, r1).slice();
223
+ wasm.__wbindgen_export3(r0, r1 * 4, 4);
224
+ return v1;
225
+ } finally {
226
+ wasm.__wbindgen_add_to_stack_pointer(16);
227
+ }
228
+ }
229
+ /**
230
+ * Everything but the triangle data, as JSON.
231
+ * @returns {string}
232
+ */
233
+ meta() {
234
+ let deferred1_0;
235
+ let deferred1_1;
236
+ try {
237
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
238
+ wasm.usdscene_meta(retptr, this.__wbg_ptr);
239
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
240
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
241
+ deferred1_0 = r0;
242
+ deferred1_1 = r1;
243
+ return getStringFromWasm0(r0, r1);
244
+ } finally {
245
+ wasm.__wbindgen_add_to_stack_pointer(16);
246
+ wasm.__wbindgen_export3(deferred1_0, deferred1_1, 1);
247
+ }
248
+ }
249
+ /**
250
+ * @returns {Float32Array}
251
+ */
252
+ normals() {
253
+ try {
254
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
255
+ wasm.usdscene_normals(retptr, this.__wbg_ptr);
256
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
257
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
258
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
259
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
260
+ if (r3) {
261
+ throw takeObject(r2);
262
+ }
263
+ var v1 = getArrayF32FromWasm0(r0, r1).slice();
264
+ wasm.__wbindgen_export3(r0, r1 * 4, 4);
265
+ return v1;
266
+ } finally {
267
+ wasm.__wbindgen_add_to_stack_pointer(16);
268
+ }
269
+ }
270
+ /**
271
+ * A texture that lives inside a USDZ package, if `path` names one there.
272
+ * Fails rather than expand it past `limit` bytes.
273
+ * @param {string} path
274
+ * @param {number} limit
275
+ * @returns {Uint8Array | undefined}
276
+ */
277
+ packagedFile(path, limit) {
278
+ try {
279
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
280
+ const ptr0 = passStringToWasm0(path, wasm.__wbindgen_export, wasm.__wbindgen_export2);
281
+ const len0 = WASM_VECTOR_LEN;
282
+ wasm.usdscene_packagedFile(retptr, this.__wbg_ptr, ptr0, len0, limit);
283
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
284
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
285
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
286
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
287
+ if (r3) {
288
+ throw takeObject(r2);
289
+ }
290
+ let v2;
291
+ if (r0 !== 0) {
292
+ v2 = getArrayU8FromWasm0(r0, r1).slice();
293
+ wasm.__wbindgen_export3(r0, r1 * 1, 1);
294
+ }
295
+ return v2;
296
+ } finally {
297
+ wasm.__wbindgen_add_to_stack_pointer(16);
298
+ }
299
+ }
300
+ /**
301
+ * @returns {Float32Array}
302
+ */
303
+ positions() {
304
+ try {
305
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
306
+ wasm.usdscene_positions(retptr, this.__wbg_ptr);
307
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
308
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
309
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
310
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
311
+ if (r3) {
312
+ throw takeObject(r2);
313
+ }
314
+ var v1 = getArrayF32FromWasm0(r0, r1).slice();
315
+ wasm.__wbindgen_export3(r0, r1 * 4, 4);
316
+ return v1;
317
+ } finally {
318
+ wasm.__wbindgen_add_to_stack_pointer(16);
319
+ }
320
+ }
321
+ /**
322
+ * Reads collider `index`: returns its metadata as JSON (`path`, `body`,
323
+ * `approximation`, `enabled`, `purpose`, `vertices`, `triangles`) and makes
324
+ * its points and triangle indices current for [`positions`](Self::positions)
325
+ * and [`indices`](Self::indices) (each once).
326
+ * @param {number} index
327
+ * @returns {string}
328
+ */
329
+ readCollider(index) {
330
+ let deferred2_0;
331
+ let deferred2_1;
332
+ try {
333
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
334
+ wasm.usdscene_readCollider(retptr, this.__wbg_ptr, index);
335
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
336
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
337
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
338
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
339
+ var ptr1 = r0;
340
+ var len1 = r1;
341
+ if (r3) {
342
+ ptr1 = 0; len1 = 0;
343
+ throw takeObject(r2);
344
+ }
345
+ deferred2_0 = ptr1;
346
+ deferred2_1 = len1;
347
+ return getStringFromWasm0(ptr1, len1);
348
+ } finally {
349
+ wasm.__wbindgen_add_to_stack_pointer(16);
350
+ wasm.__wbindgen_export3(deferred2_0, deferred2_1, 1);
351
+ }
352
+ }
353
+ /**
354
+ * Reads geometry `index` and returns its metadata as JSON, or `None` when
355
+ * the mesh has nothing drawable. A mesh with more than `max_triangles` is
356
+ * left unread: `{"overBudget": triangles, "path": prim path}`.
357
+ * @param {number} index
358
+ * @param {number} max_triangles
359
+ * @returns {string | undefined}
360
+ */
361
+ read(index, max_triangles) {
362
+ try {
363
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
364
+ wasm.usdscene_read(retptr, this.__wbg_ptr, index, max_triangles);
365
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
366
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
367
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
368
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
369
+ if (r3) {
370
+ throw takeObject(r2);
371
+ }
372
+ let v1;
373
+ if (r0 !== 0) {
374
+ v1 = getStringFromWasm0(r0, r1);
375
+ wasm.__wbindgen_export3(r0, r1 * 1, 1);
376
+ }
377
+ return v1;
378
+ } finally {
379
+ wasm.__wbindgen_add_to_stack_pointer(16);
380
+ }
381
+ }
382
+ /**
383
+ * UV set `set` (in the order of the geometry's `uvSets`).
384
+ * @param {number} set
385
+ * @returns {Float32Array}
386
+ */
387
+ uvs(set) {
388
+ try {
389
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
390
+ wasm.usdscene_uvs(retptr, this.__wbg_ptr, set);
391
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
392
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
393
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
394
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
395
+ if (r3) {
396
+ throw takeObject(r2);
397
+ }
398
+ var v1 = getArrayF32FromWasm0(r0, r1).slice();
399
+ wasm.__wbindgen_export3(r0, r1 * 4, 4);
400
+ return v1;
401
+ } finally {
402
+ wasm.__wbindgen_add_to_stack_pointer(16);
403
+ }
404
+ }
405
+ }
406
+ if (Symbol.dispose) UsdScene.prototype[Symbol.dispose] = UsdScene.prototype.free;
407
+
408
+ /**
409
+ * Takes the message of the last panic, if any.
410
+ * @returns {string | undefined}
411
+ */
412
+ export function lastPanic() {
413
+ try {
414
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
415
+ wasm.lastPanic(retptr);
416
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
417
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
418
+ let v1;
419
+ if (r0 !== 0) {
420
+ v1 = getStringFromWasm0(r0, r1);
421
+ wasm.__wbindgen_export3(r0, r1 * 1, 1);
422
+ }
423
+ return v1;
424
+ } finally {
425
+ wasm.__wbindgen_add_to_stack_pointer(16);
426
+ }
427
+ }
428
+
429
+ export function start() {
430
+ wasm.start();
431
+ }
432
+ function __wbg_get_imports() {
433
+ const import0 = {
434
+ __proto__: null,
435
+ __wbg_Error_30c8987f7c2ed4e2: function(arg0, arg1) {
436
+ const ret = Error(getStringFromWasm0(arg0, arg1));
437
+ return addHeapObject(ret);
438
+ },
439
+ __wbg___wbindgen_string_get_0380ccaa2f57f0d9: function(arg0, arg1) {
440
+ const obj = getObject(arg1);
441
+ const ret = typeof(obj) === 'string' ? obj : undefined;
442
+ var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
443
+ var len1 = WASM_VECTOR_LEN;
444
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
445
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
446
+ },
447
+ __wbg___wbindgen_throw_41e9ee4f547fc59a: function(arg0, arg1) {
448
+ throw new Error(getStringFromWasm0(arg0, arg1));
449
+ },
450
+ __wbindgen_generic_0000000000000001: function(arg0, arg1) {
451
+ // Cast intrinsic for `Ref(String) -> Externref`.
452
+ const ret = getStringFromWasm0(arg0, arg1);
453
+ return addHeapObject(ret);
454
+ },
455
+ __wbindgen_object_drop_ref: function(arg0) {
456
+ takeObject(arg0);
457
+ },
458
+ };
459
+ return {
460
+ __proto__: null,
461
+ "./usd_wasm_bg.js": import0,
462
+ };
463
+ }
464
+
465
+ const UsdLoaderFinalization = (typeof FinalizationRegistry === 'undefined')
466
+ ? { register: () => {}, unregister: () => {} }
467
+ : new FinalizationRegistry(ptr => wasm.__wbg_usdloader_free(ptr, 1));
468
+ const UsdSceneFinalization = (typeof FinalizationRegistry === 'undefined')
469
+ ? { register: () => {}, unregister: () => {} }
470
+ : new FinalizationRegistry(ptr => wasm.__wbg_usdscene_free(ptr, 1));
471
+
472
+ function addHeapObject(obj) {
473
+ if (heap_next === heap.length) heap.push(heap.length + 1);
474
+ const idx = heap_next;
475
+ heap_next = heap[idx];
476
+
477
+ heap[idx] = obj;
478
+ return idx;
479
+ }
480
+
481
+ function dropObject(idx) {
482
+ if (idx < 1028) return;
483
+ heap[idx] = heap_next;
484
+ heap_next = idx;
485
+ }
486
+
487
+ function getArrayF32FromWasm0(ptr, len) {
488
+ ptr = ptr >>> 0;
489
+ return getFloat32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len);
490
+ }
491
+
492
+ function getArrayJsValueFromWasm0(ptr, len) {
493
+ ptr = ptr >>> 0;
494
+ const mem = getDataViewMemory0();
495
+ const result = [];
496
+ for (let i = ptr; i < ptr + 4 * len; i += 4) {
497
+ result.push(takeObject(mem.getUint32(i, true)));
498
+ }
499
+ return result;
500
+ }
501
+
502
+ function getArrayU16FromWasm0(ptr, len) {
503
+ ptr = ptr >>> 0;
504
+ return getUint16ArrayMemory0().subarray(ptr / 2, ptr / 2 + len);
505
+ }
506
+
507
+ function getArrayU32FromWasm0(ptr, len) {
508
+ ptr = ptr >>> 0;
509
+ return getUint32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len);
510
+ }
511
+
512
+ function getArrayU8FromWasm0(ptr, len) {
513
+ ptr = ptr >>> 0;
514
+ return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
515
+ }
516
+
517
+ let cachedDataViewMemory0 = null;
518
+ function getDataViewMemory0() {
519
+ if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
520
+ cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
521
+ }
522
+ return cachedDataViewMemory0;
523
+ }
524
+
525
+ let cachedFloat32ArrayMemory0 = null;
526
+ function getFloat32ArrayMemory0() {
527
+ if (cachedFloat32ArrayMemory0 === null || cachedFloat32ArrayMemory0.byteLength === 0) {
528
+ cachedFloat32ArrayMemory0 = new Float32Array(wasm.memory.buffer);
529
+ }
530
+ return cachedFloat32ArrayMemory0;
531
+ }
532
+
533
+ function getStringFromWasm0(ptr, len) {
534
+ return decodeText(ptr >>> 0, len);
535
+ }
536
+
537
+ let cachedUint16ArrayMemory0 = null;
538
+ function getUint16ArrayMemory0() {
539
+ if (cachedUint16ArrayMemory0 === null || cachedUint16ArrayMemory0.byteLength === 0) {
540
+ cachedUint16ArrayMemory0 = new Uint16Array(wasm.memory.buffer);
541
+ }
542
+ return cachedUint16ArrayMemory0;
543
+ }
544
+
545
+ let cachedUint32ArrayMemory0 = null;
546
+ function getUint32ArrayMemory0() {
547
+ if (cachedUint32ArrayMemory0 === null || cachedUint32ArrayMemory0.byteLength === 0) {
548
+ cachedUint32ArrayMemory0 = new Uint32Array(wasm.memory.buffer);
549
+ }
550
+ return cachedUint32ArrayMemory0;
551
+ }
552
+
553
+ let cachedUint8ArrayMemory0 = null;
554
+ function getUint8ArrayMemory0() {
555
+ if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
556
+ cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
557
+ }
558
+ return cachedUint8ArrayMemory0;
559
+ }
560
+
561
+ function getObject(idx) { return heap[idx]; }
562
+
563
+ let heap = new Array(1024).fill(undefined);
564
+ heap.push(undefined, null, true, false);
565
+
566
+ let heap_next = heap.length;
567
+
568
+ function isLikeNone(x) {
569
+ return x === undefined || x === null;
570
+ }
571
+
572
+ function passArray8ToWasm0(arg, malloc) {
573
+ const ptr = malloc(arg.length * 1, 1) >>> 0;
574
+ getUint8ArrayMemory0().set(arg, ptr / 1);
575
+ WASM_VECTOR_LEN = arg.length;
576
+ return ptr;
577
+ }
578
+
579
+ function passArrayJsValueToWasm0(array, malloc) {
580
+ const ptr = malloc(array.length * 4, 4) >>> 0;
581
+ const mem = getDataViewMemory0();
582
+ for (let i = 0; i < array.length; i++) {
583
+ mem.setUint32(ptr + 4 * i, addHeapObject(array[i]), true);
584
+ }
585
+ WASM_VECTOR_LEN = array.length;
586
+ return ptr;
587
+ }
588
+
589
+ function passStringToWasm0(arg, malloc, realloc) {
590
+ if (realloc === undefined) {
591
+ const buf = cachedTextEncoder.encode(arg);
592
+ const ptr = malloc(buf.length, 1) >>> 0;
593
+ getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
594
+ WASM_VECTOR_LEN = buf.length;
595
+ return ptr;
596
+ }
597
+
598
+ let len = arg.length;
599
+ let ptr = malloc(len, 1) >>> 0;
600
+
601
+ const mem = getUint8ArrayMemory0();
602
+
603
+ let offset = 0;
604
+
605
+ for (; offset < len; offset++) {
606
+ const code = arg.charCodeAt(offset);
607
+ if (code > 0x7F) break;
608
+ mem[ptr + offset] = code;
609
+ }
610
+ if (offset !== len) {
611
+ if (offset !== 0) {
612
+ arg = arg.slice(offset);
613
+ }
614
+ ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
615
+ const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
616
+ const ret = cachedTextEncoder.encodeInto(arg, view);
617
+
618
+ offset += ret.written;
619
+ ptr = realloc(ptr, len, offset, 1) >>> 0;
620
+ }
621
+
622
+ WASM_VECTOR_LEN = offset;
623
+ return ptr;
624
+ }
625
+
626
+ function takeObject(idx) {
627
+ const ret = getObject(idx);
628
+ dropObject(idx);
629
+ return ret;
630
+ }
631
+
632
+ let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
633
+ cachedTextDecoder.decode();
634
+ const MAX_SAFARI_DECODE_BYTES = 2146435072;
635
+ let numBytesDecoded = 0;
636
+ function decodeText(ptr, len) {
637
+ numBytesDecoded += len;
638
+ if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
639
+ cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
640
+ cachedTextDecoder.decode();
641
+ numBytesDecoded = len;
642
+ }
643
+ return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
644
+ }
645
+
646
+ const cachedTextEncoder = new TextEncoder();
647
+
648
+ if (!('encodeInto' in cachedTextEncoder)) {
649
+ cachedTextEncoder.encodeInto = function (arg, view) {
650
+ const buf = cachedTextEncoder.encode(arg);
651
+ view.set(buf);
652
+ return {
653
+ read: arg.length,
654
+ written: buf.length
655
+ };
656
+ };
657
+ }
658
+
659
+ let WASM_VECTOR_LEN = 0;
660
+
661
+ let wasmModule, wasmInstance, wasm;
662
+ function __wbg_finalize_init(instance, module) {
663
+ wasmInstance = instance;
664
+ wasm = instance.exports;
665
+ wasmModule = module;
666
+ cachedDataViewMemory0 = null;
667
+ cachedFloat32ArrayMemory0 = null;
668
+ cachedUint16ArrayMemory0 = null;
669
+ cachedUint32ArrayMemory0 = null;
670
+ cachedUint8ArrayMemory0 = null;
671
+ wasm.__wbindgen_start();
672
+ return wasm;
673
+ }
674
+
675
+ async function __wbg_load(module, imports) {
676
+ if (typeof Response === 'function' && module instanceof Response) {
677
+ if (!module.ok) {
678
+ throw new Error(`failed to fetch Wasm: ${module.status} ${module.statusText} fetching '${module.url}'`);
679
+ }
680
+
681
+ if (typeof WebAssembly.instantiateStreaming === 'function') {
682
+ try {
683
+ return await WebAssembly.instantiateStreaming(module, imports);
684
+ } catch (e) {
685
+ const validResponse = expectedResponseType(module.type);
686
+
687
+ if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {
688
+ console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
689
+
690
+ } else { throw e; }
691
+ }
692
+ }
693
+
694
+ const bytes = await module.arrayBuffer();
695
+ return await WebAssembly.instantiate(bytes, imports);
696
+ } else {
697
+ const instance = await WebAssembly.instantiate(module, imports);
698
+
699
+ if (instance instanceof WebAssembly.Instance) {
700
+ return { instance, module };
701
+ } else {
702
+ return instance;
703
+ }
704
+ }
705
+
706
+ function expectedResponseType(type) {
707
+ switch (type) {
708
+ case 'basic': case 'cors': case 'default': return true;
709
+ }
710
+ return false;
711
+ }
712
+ }
713
+
714
+ function initSync(module) {
715
+ if (wasm !== undefined) return wasm;
716
+
717
+
718
+ if (module !== undefined) {
719
+ if (Object.getPrototypeOf(module) === Object.prototype) {
720
+ ({module} = module)
721
+ } else {
722
+ console.warn('using deprecated parameters for `initSync()`; pass a single object instead')
723
+ }
724
+ }
725
+
726
+ const imports = __wbg_get_imports();
727
+ if (!(module instanceof WebAssembly.Module)) {
728
+ module = new WebAssembly.Module(module);
729
+ }
730
+ const instance = new WebAssembly.Instance(module, imports);
731
+ return __wbg_finalize_init(instance, module);
732
+ }
733
+
734
+ async function __wbg_init(module_or_path) {
735
+ if (wasm !== undefined) return wasm;
736
+
737
+
738
+ if (module_or_path !== undefined) {
739
+ if (Object.getPrototypeOf(module_or_path) === Object.prototype) {
740
+ ({module_or_path} = module_or_path)
741
+ } else {
742
+ console.warn('using deprecated parameters for the initialization function; pass a single object instead')
743
+ }
744
+ }
745
+
746
+ if (module_or_path === undefined) {
747
+ module_or_path = new URL('usd_wasm_bg.wasm', import.meta.url);
748
+ }
749
+ const imports = __wbg_get_imports();
750
+
751
+ if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {
752
+ module_or_path = fetch(module_or_path);
753
+ }
754
+
755
+ const { instance, module } = await __wbg_load(await module_or_path, imports);
756
+
757
+ return __wbg_finalize_init(instance, module);
758
+ }
759
+
760
+ export { initSync, __wbg_init as default };
services/explorer/dist/static/usd-reader/81290bc/wasm/usd_wasm_bg.wasm ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d746ca57ac800465e447c67d1790b6c19da772e02501083a25a189bcd9aaa74b
3
+ size 2356773
services/explorer/dist/third-party-notices.txt CHANGED
@@ -1,4 +1,4 @@
1
- Third-party notices — SimReady Central Explorer slim-ui-35349654
2
 
3
  The software in this web application's browser bundle includes the packages below, each under its own
4
  license. Each entry gives the package, its version, its license and the license / notice text it ships.
 
1
+ Third-party notices — SimReady Central Explorer slim-ui-9d95b298
2
 
3
  The software in this web application's browser bundle includes the packages below, each under its own
4
  license. Each entry gives the package, its version, its license and the license / notice text it ships.