specimba commited on
Commit
9b75320
·
verified ·
1 Parent(s): 5aa6a58

diag: minimal diagnostic app.py to find runtime error

Browse files
Files changed (1) hide show
  1. app.py +61 -1090
app.py CHANGED
@@ -1,1105 +1,76 @@
1
- """NEXUS Visual Weaver - Build Small Hackathon command center."""
2
-
3
- from __future__ import annotations
4
-
5
  import os
6
  import sys
7
- import hashlib
8
- import secrets
9
- from pathlib import Path
10
- from typing import Any
11
- from urllib.parse import urlparse
12
-
13
- import gradio as gr
14
-
15
- ROOT = Path(__file__).resolve().parent
16
- SRC = ROOT / "src"
17
- if str(SRC) not in sys.path:
18
- sys.path.insert(0, str(SRC))
19
-
20
- try:
21
- import spaces # type: ignore # noqa: F401
22
- except Exception: # pragma: no cover - local development does not require Spaces.
23
- spaces = None
24
-
25
- from nexus_visual_weaver.catalog import catalog_summary
26
- from nexus_visual_weaver.exporter import write_export_packet
27
- from nexus_visual_weaver.hf_runtime import generate_flux_image
28
- from nexus_visual_weaver.model_relay import WeaverModelRelay
29
- from nexus_visual_weaver.planner import build_command_center_run
30
- from nexus_visual_weaver.provider_runtime import judge_with_minicpm, judge_with_nemotron
31
- from nexus_visual_weaver.render import render_catalog_table, render_command_header, render_dashboard_regions
32
- from nexus_visual_weaver.security import scan_file
33
- from nexus_visual_weaver.styles import APP_CSS
34
-
35
- APP_THEME = gr.themes.Base(
36
- primary_hue="rose",
37
- secondary_hue="cyan",
38
- neutral_hue="slate",
39
- radius_size="sm",
40
- font=["Inter", "ui-sans-serif", "system-ui"],
41
- )
42
-
43
-
44
- DEFAULT_PROMPT = (
45
- "A Slavic archivist in a rain-slick neon city, wearing a structured black patent "
46
- "leather long coat with faux fur collar, Chantilly lace neckline, glowing crimson "
47
- "hardware, platform boots, NEXUS sigils and floating code streams behind her."
48
- )
49
-
50
- MODEL_RELAY = WeaverModelRelay()
51
-
52
- STYLE_MODIFIERS = {
53
- "Balanced": "balanced editorial lighting, precise garment detail, clean composition",
54
- "High Fashion": "haute couture editorial styling, premium material finish, runway-grade silhouette",
55
- "Cinematic": "cinematic rain-lit atmosphere, dramatic lensing, high contrast neon reflections",
56
- }
57
-
58
- ASPECT_DIMENSIONS = {
59
- "Square": (1024, 1024),
60
- "Portrait": (832, 1216),
61
- }
62
-
63
-
64
- def _default_operator_state() -> dict[str, Any]:
65
- return {
66
- "provider_state": "idle",
67
- "checkpoint": "pending",
68
- "export": "pending",
69
- "message": "No operator action yet.",
70
- }
71
-
72
-
73
- def _zero_gpu_entrypoint(fn: Any) -> Any:
74
- """
75
- Optionally wrap a function with ZeroGPU acceleration.
76
-
77
- If the spaces module is available and provides GPU support, wraps the function with `spaces.GPU(duration=300)`. Otherwise, returns the function unchanged.
78
-
79
- Parameters:
80
- fn: The callback function.
81
-
82
- Returns:
83
- The function, optionally wrapped with ZeroGPU acceleration.
84
- """
85
- gpu_decorator = getattr(spaces, "GPU", None) if spaces is not None else None
86
- if gpu_decorator is None:
87
- return fn
88
- return gpu_decorator(duration=300)(fn)
89
-
90
-
91
- def _relay_snapshot(adult_mode: bool = False) -> dict[str, Any]:
92
- """
93
- Retrieves the relay dashboard snapshot based on visibility mode.
94
-
95
- Returns:
96
- dict[str, Any]: Dashboard snapshot containing relay status and model information.
97
- """
98
- return MODEL_RELAY.dashboard_snapshot(public_demo=not adult_mode)
99
-
100
-
101
- def _file_path(uploaded: Any) -> str | None:
102
- """
103
- Extract a file path from various upload input formats.
104
-
105
- Returns:
106
- str | None: The file path string, or None if the input is None or lacks a valid path.
107
- """
108
- if uploaded is None:
109
- return None
110
- if isinstance(uploaded, str):
111
- return uploaded
112
- path = getattr(uploaded, "name", None)
113
- return str(path) if path else None
114
-
115
-
116
- def _safe_file_hash(path: str | None) -> tuple[str | None, int | None]:
117
- """
118
- Compute the SHA-256 hash and size of a file.
119
-
120
- Returns:
121
- tuple[str | None, int | None]: The file's SHA-256 hash as a hex string and size in bytes. Returns (None, None) if the path is falsy or the file cannot be read.
122
- """
123
- if not path:
124
- return None, None
125
- try:
126
- target = Path(path)
127
- sha256 = hashlib.sha256()
128
- size = 0
129
- with target.open("rb") as handle:
130
- while chunk := handle.read(1024 * 1024):
131
- sha256.update(chunk)
132
- size += len(chunk)
133
- except OSError:
134
- return None, None
135
- return sha256.hexdigest(), size
136
-
137
-
138
- def _safe_reference_url_metadata(reference_url: str | None) -> dict[str, Any] | None:
139
- """
140
- Validates a reference URL and extracts its metadata.
141
-
142
- Returns:
143
- A dict with status "metadata_only" containing domain (lowercased) and URL hash if valid;
144
- a dict with status "invalid_url" if the URL scheme is not HTTP(S) or domain is missing;
145
- None if reference_url is falsy.
146
- """
147
- if not reference_url:
148
- return None
149
- parsed = urlparse(reference_url.strip())
150
- if parsed.scheme not in {"http", "https"} or not parsed.netloc:
151
- return {"source": "url", "status": "invalid_url", "message": "Reference URL must be http(s)."}
152
- url_hash = hashlib.sha256(reference_url.strip().encode("utf-8")).hexdigest()
153
- return {
154
- "source": "url",
155
- "status": "metadata_only",
156
- "domain": parsed.netloc.lower(),
157
- "url_hash": url_hash,
158
- "message": "URL stored as metadata only; Space runtime does not crawl or copy shop images.",
159
- }
160
-
161
-
162
- def _reference_metadata(uploaded: Any, reference_url: str | None, scan: dict[str, Any]) -> list[dict[str, Any]]:
163
- """
164
- Builds a list of metadata records from an uploaded file and/or reference URL.
165
-
166
- For an uploaded file, includes basename, SHA-256 hash, size, and scan results (status,
167
- export gate, magic, extension). For a reference URL, includes domain, URL hash, and status.
168
-
169
- Parameters:
170
- uploaded: An uploaded file object, path string, or None.
171
- reference_url: Optional reference URL string.
172
- scan: Dictionary of ST3GG scan results for the uploaded file.
173
-
174
- Returns:
175
- List of metadata dictionaries for the file and/or URL. Empty if neither is provided.
176
- """
177
- records: list[dict[str, Any]] = []
178
- path = _file_path(uploaded)
179
- if path:
180
- file_hash, size = _safe_file_hash(path)
181
- records.append(
182
- {
183
- "source": "upload",
184
- "basename": Path(path).name,
185
- "sha256": file_hash,
186
- "size_bytes": size,
187
- "st3gg_status": scan.get("status"),
188
- "export_gate": scan.get("export_gate"),
189
- "magic": scan.get("magic"),
190
- "extension": scan.get("extension"),
191
- }
192
- )
193
- url_record = _safe_reference_url_metadata(reference_url)
194
- if url_record:
195
- records.append(url_record)
196
- return records
197
-
198
-
199
- def _creator_controls(
200
- reasoning_mode: str,
201
- video_preset: str,
202
- silhouette: str | None = None,
203
- outerwear: str | None = None,
204
- upper_body: str | None = None,
205
- footwear: str | None = None,
206
- palette: str | None = None,
207
- hardware: str | None = None,
208
- locate_focus: list[str] | None = None,
209
- seed: int | None = None,
210
- style_strength: str = "High Fashion",
211
- aspect: str = "Portrait",
212
- ) -> dict[str, Any]:
213
- """
214
- Create a control object combining wardrobe selections with generation policy and reasoning configuration.
215
-
216
- Returns:
217
- dict: Nested structure containing reasoning mode, video preset, wardrobe selections with locked slots,
218
- and FLUX generation configuration.
219
- """
220
- wardrobe = {
221
- "silhouette": silhouette or "structured long coat",
222
- "outerwear": outerwear or "black patent leather long coat",
223
- "upper_body": upper_body or "Chantilly lace neckline",
224
- "footwear": footwear or "platform boots",
225
- "palette": palette or "black, crimson, cyan neon",
226
- "hardware": hardware or "crimson hardware",
227
- "locked_slots": ["outerwear", "upper_body", "footwear", "jewelry"],
228
- "locate_focus": locate_focus or ["outerwear", "footwear", "jewelry"],
229
- }
230
- return {
231
- "reasoning_mode": reasoning_mode,
232
- "video_preset": video_preset,
233
- "wardrobe": wardrobe,
234
- "generation": {
235
- "flux_primary": "black-forest-labs/FLUX.2-klein-9B",
236
- "flux_sidecar": "black-forest-labs/FLUX.2-klein-4B",
237
- "lora_policy": "attempt compatible runtime adapter; report loaded/skipped/failed",
238
- "seed": seed,
239
- "style_strength": style_strength,
240
- "aspect": aspect,
241
- },
242
- }
243
-
244
-
245
- def _resolve_seed(seed_value: Any) -> int:
246
- """Resolve user seed input. Empty or -1 means randomize."""
247
- try:
248
- if seed_value is None or str(seed_value).strip() == "":
249
- return secrets.randbelow(1_000_000_000)
250
- seed = int(float(seed_value))
251
- except (TypeError, ValueError):
252
- return secrets.randbelow(1_000_000_000)
253
- return secrets.randbelow(1_000_000_000) if seed < 0 else seed
254
 
 
 
 
 
 
255
 
256
- def _generation_dimensions(aspect: str | None) -> tuple[int, int]:
257
- return ASPECT_DIMENSIONS.get(str(aspect or "Portrait"), ASPECT_DIMENSIONS["Portrait"])
258
 
259
-
260
- def _style_modifier(style_strength: str | None) -> str:
261
- return STYLE_MODIFIERS.get(str(style_strength or "High Fashion"), STYLE_MODIFIERS["High Fashion"])
262
-
263
-
264
- def _prompt_with_controls(prompt: str, controls: dict[str, Any]) -> str:
265
- """
266
- Augments a prompt with wardrobe control parameters.
267
-
268
- If any wardrobe fields are specified in the controls, appends them to the
269
- prompt with a "Wardrobe controls:" prefix. Otherwise returns the prompt unchanged.
270
-
271
- Parameters:
272
- controls (dict[str, Any]): A controls dictionary containing a "wardrobe" key with fields for silhouette, outerwear, upper_body, footwear, palette, and hardware.
273
-
274
- Returns:
275
- str: The prompt with wardrobe controls appended, or the original prompt if no wardrobe items are specified.
276
- """
277
- wardrobe = controls.get("wardrobe", {})
278
- additions = [
279
- wardrobe.get("silhouette"),
280
- wardrobe.get("outerwear"),
281
- wardrobe.get("upper_body"),
282
- wardrobe.get("footwear"),
283
- wardrobe.get("palette"),
284
- wardrobe.get("hardware"),
285
- ]
286
- suffix = ", ".join(str(item) for item in additions if item)
287
- generation = controls.get("generation", {})
288
- if not suffix and not generation:
289
- return prompt
290
- style = _style_modifier(str(generation.get("style_strength", "High Fashion")))
291
- prompt = f"{prompt}\nWardrobe controls: {suffix}" if suffix else prompt
292
- return f"{prompt}\nStyle direction: {style}"
293
-
294
-
295
- def _generated_output_path(operator_state: dict[str, Any] | None) -> str | None:
296
- """
297
- Extract the generated artifact output path from the operator state.
298
-
299
- Returns:
300
- The output path string if a generated artifact exists, None otherwise.
301
- """
302
- generation = (operator_state or {}).get("generation") or {}
303
- output_path = generation.get("output_path")
304
- return str(output_path) if output_path else None
305
-
306
-
307
- def _authoritative_generated_scan(operator_state: dict[str, Any] | None) -> dict[str, Any]:
308
- """
309
- Obtain the current scan for a generated artifact.
310
-
311
- Returns:
312
- dict[str, Any]: A scan record sourced from the generated output file, stored state, or a default scan.
313
- """
314
- output_path = _generated_output_path(operator_state)
315
- if output_path:
316
- return scan_file(output_path)
317
- stored_scan = (operator_state or {}).get("generated_scan")
318
- return stored_scan if isinstance(stored_scan, dict) else scan_file(None)
319
-
320
-
321
- def _checkpoint_seed(checkpoint_id: str) -> int:
322
- """
323
- Derives a numeric seed from a checkpoint ID.
324
-
325
- Parameters:
326
- checkpoint_id (str): A checkpoint identifier string.
327
 
328
- Returns:
329
- int: An integer seed bounded to less than 1,000,000, or 0 if no valid seed data can be extracted from the checkpoint ID.
330
- """
331
- suffix = "".join(char for char in checkpoint_id[-8:] if char in "0123456789abcdefABCDEF")
332
- if not suffix:
333
- return 0
334
  try:
335
- return int(suffix, 16) % 1_000_000
336
- except ValueError:
337
- return 0
338
-
339
-
340
- def _wardrobe_summary(run: Any) -> str:
341
- """
342
- Formats outfit wardrobe slots into a semicolon-separated summary string.
343
-
344
- Returns:
345
- A semicolon-separated string listing each outfit slot's name, description, material, palette, and locked status.
346
- """
347
- slots = getattr(getattr(run, "outfit", None), "slots", []) or []
348
- return "; ".join(
349
- f"{slot.name}: {slot.description}, material={slot.material}, palette={slot.palette}, locked={slot.locked}"
350
- for slot in slots
351
- )
352
-
353
-
354
- SECTIONS = ["Forge", "Wardrobe", "Lore", "Models", "Security", "Runs"]
355
-
356
-
357
- def _button_updates(run: Any | None, operator_state: dict[str, Any] | None) -> tuple[Any, Any, Any]:
358
- state = operator_state or {}
359
- generated = bool(_generated_output_path(state)) and (state.get("generation") or {}).get("status") == "success"
360
- checkpoint_approved = state.get("checkpoint") == "approved"
361
- exported = state.get("provider_state") == "exported"
362
- return (
363
- gr.update(interactive=generated and not checkpoint_approved and not exported),
364
- gr.update(interactive=generated and checkpoint_approved and not exported),
365
- gr.update(interactive=False),
366
- )
367
-
368
-
369
- def _dashboard_regions(
370
- run: Any | None = None,
371
- adult_mode: bool = False,
372
- scan: dict[str, Any] | None = None,
373
- active_section: str = "Forge",
374
- operator_state: dict[str, Any] | None = None,
375
- ) -> dict[str, str]:
376
- return render_dashboard_regions(
377
- run=run,
378
- adult_mode=adult_mode,
379
- scan=scan,
380
- relay_status=_relay_snapshot(adult_mode),
381
- active_section=active_section,
382
- operator_state=operator_state,
383
- )
384
-
385
-
386
- @_zero_gpu_entrypoint
387
- def run_weave(
388
- prompt: str,
389
- reasoning_mode: str,
390
- video_preset: str,
391
- adult_mode: bool,
392
- upload: Any,
393
- active_section: str,
394
- silhouette: str | None = None,
395
- outerwear: str | None = None,
396
- upper_body: str | None = None,
397
- footwear: str | None = None,
398
- palette: str | None = None,
399
- hardware: str | None = None,
400
- reference_url: str | None = None,
401
- seed_value: Any = -1,
402
- style_strength: str = "High Fashion",
403
- aspect: str = "Portrait",
404
- ) -> tuple[Any, ...]:
405
- """
406
- Execute the complete weaving workflow from prompt through image generation and evaluation.
407
-
408
- Assembles wardrobe controls, generates an image via FLUX, scans and judges the output through ST3GG scanning and dual judges (Minicpm and Nemotron), and compiles operator state reflecting generation status, checkpoint readiness, and export gating.
409
-
410
- Returns:
411
- Tuple containing dashboard region HTML fragments (topbar, command_rail, workflow, operations, inspector, drawer, status, artifacts, providers), catalog HTML, run data, catalog summary, scan results, operator state with generation details and judge evidence, and button state updates.
412
- """
413
- prompt = prompt.strip() or DEFAULT_PROMPT
414
- resolved_seed = _resolve_seed(seed_value)
415
- width, height = _generation_dimensions(aspect)
416
- controls = _creator_controls(
417
- reasoning_mode=reasoning_mode,
418
- video_preset=video_preset,
419
- silhouette=silhouette,
420
- outerwear=outerwear,
421
- upper_body=upper_body,
422
- footwear=footwear,
423
- palette=palette,
424
- hardware=hardware,
425
- seed=resolved_seed,
426
- style_strength=style_strength,
427
- aspect=aspect,
428
- )
429
- controlled_prompt = _prompt_with_controls(prompt, controls)
430
- reference_scan = scan_file(_file_path(upload))
431
- reference_metadata = _reference_metadata(upload, reference_url, reference_scan)
432
- run = build_command_center_run(
433
- prompt=controlled_prompt,
434
- mode=reasoning_mode,
435
- video_preset=video_preset,
436
- adult_mode=adult_mode,
437
- creator_controls=controls,
438
- reference_metadata=reference_metadata,
439
- )
440
- generation = generate_flux_image(
441
- run.refined_prompt.refined,
442
- seed=resolved_seed,
443
- width=width,
444
- height=height,
445
- adult_mode=adult_mode,
446
- )
447
- generated_scan = scan_file(generation.output_path) if generation.output_path else scan_file(None)
448
- minicpm = judge_with_minicpm(
449
- prompt=run.refined_prompt.refined,
450
- image_path=generation.output_path,
451
- scan=generated_scan,
452
- wardrobe_summary=_wardrobe_summary(run),
453
- )
454
- nemotron = judge_with_nemotron(
455
- prompt=run.refined_prompt.refined,
456
- run_packet=run.to_dict(),
457
- minicpm_result=minicpm.to_dict(),
458
- )
459
- if generation.status == "success":
460
- provider_state = "generated"
461
- elif generation.status in {"disabled", "missing_runtime", "no_cuda", "error"}:
462
- provider_state = generation.provider_state
463
  else:
464
- provider_state = "checkpointed"
465
- operator_state = {
466
- "provider_state": provider_state,
467
- "checkpoint": "pending_review",
468
- "export": generated_scan.get("export_gate", "pending"),
469
- "message": generation.message or "Image run complete. Human checkpoint required before export.",
470
- "generation": generation.to_dict(),
471
- "creator_controls": controls,
472
- "reference_metadata": reference_metadata,
473
- "reference_scan": reference_scan,
474
- "generated_scan": generated_scan,
475
- "minicpm_judge": minicpm.to_dict(),
476
- "nemotron_evidence": nemotron.to_dict(),
477
- }
478
- regions = _dashboard_regions(
479
- run=run,
480
- adult_mode=adult_mode,
481
- scan=generated_scan,
482
- active_section=active_section,
483
- operator_state=operator_state,
484
- )
485
- catalog = render_catalog_table(adult_mode=adult_mode)
486
- return (
487
- regions["topbar"],
488
- regions["command_rail"],
489
- regions["workflow"],
490
- regions["operations"],
491
- regions["inspector"],
492
- regions["drawer"],
493
- regions["status"],
494
- regions["artifacts"],
495
- regions["providers"],
496
- catalog,
497
- run.to_dict(),
498
- catalog_summary(adult_mode),
499
- generated_scan,
500
- run,
501
- generated_scan,
502
- operator_state,
503
- *_button_updates(run, operator_state),
504
- )
505
-
506
-
507
- def toggle_adult_visibility(
508
- adult_mode: bool,
509
- active_section: str,
510
- upload: Any,
511
- ) -> tuple[Any, ...]:
512
- """
513
- Update the dashboard to reflect a change in adult content visibility.
514
 
515
- Re-scans any uploaded file and regenerates all dashboard regions to show or hide adult content while maintaining ST3GG, consent, and export gates.
516
-
517
- Returns:
518
- tuple: Updated UI fragments and state (topbar, command rail, operations, inspector, artifacts, providers, catalog table, catalog summary, scan metadata, operator state).
519
- """
520
- scan = scan_file(_file_path(upload))
521
- operator_state = {
522
- **_default_operator_state(),
523
- "message": "Adult catalog visibility changed. ST3GG, consent, and export gates remain active.",
524
- }
525
- regions = _dashboard_regions(adult_mode=adult_mode, scan=scan, active_section=active_section, operator_state=operator_state)
526
- return (
527
- regions["topbar"],
528
- regions["command_rail"],
529
- regions["operations"],
530
- regions["inspector"],
531
- regions["artifacts"],
532
- regions["providers"],
533
- render_catalog_table(adult_mode=adult_mode),
534
- catalog_summary(adult_mode),
535
- scan,
536
- operator_state,
537
- )
538
-
539
-
540
- def refresh_section(
541
- active_section: str,
542
- adult_mode: bool,
543
- run: Any | None,
544
- scan: dict[str, Any] | None,
545
- operator_state: dict[str, Any] | None,
546
- ) -> tuple[str, str, str, str, str, dict[str, Any]]:
547
- """
548
- Render dashboard regions for the currently selected navigation section.
549
-
550
- Returns:
551
- A tuple of (command_rail, operations, inspector, artifacts, providers, scan),
552
- where the first five elements are HTML strings for dashboard regions and the last
553
- is the ST3GG scan results dictionary.
554
- """
555
- scan = scan or scan_file(None)
556
- regions = _dashboard_regions(
557
- run=run,
558
- adult_mode=adult_mode,
559
- scan=scan,
560
- active_section=active_section,
561
- operator_state=operator_state or _default_operator_state(),
562
- )
563
- return regions["command_rail"], regions["operations"], regions["inspector"], regions["artifacts"], regions["providers"], scan
564
 
565
-
566
- def _render_stateful(
567
- run: Any | None,
568
- adult_mode: bool,
569
- scan: dict[str, Any] | None,
570
- active_section: str,
571
- operator_state: dict[str, Any],
572
- ) -> tuple[Any, ...]:
573
- """
574
- Render the dashboard with current state and return all UI outputs and state objects.
575
 
576
- Ensures scan data exists, calls the dashboard region renderer with current state, and assembles
577
- a comprehensive tuple of HTML fragments, state objects, and button updates for Gradio output.
578
 
579
- Parameters:
580
- run: The current run object, or None if no run is active.
581
- adult_mode: Whether adult-mode visibility is enabled.
582
- scan: Scan/ST3GG evidence dict. If None or falsy, defaults to empty scan from scan_file.
583
- active_section: The currently active dashboard section identifier.
584
- operator_state: Current operator state dict containing provider status, checkpoint, export, and messaging.
585
 
586
- Returns:
587
- A tuple containing: topbar, command_rail, workflow, operations, inspector, drawer, status,
588
- artifacts, providers (all HTML fragments), catalog table HTML, run dict (or empty dict),
589
- catalog summary, scan dict, operator_state dict, and a Gradio update object for the stop
590
- button (interactive if run exists and provider is neither idle, stopped, nor exported).
591
- """
592
- scan = scan or scan_file(None)
593
- regions = _dashboard_regions(
594
- run=run,
595
- adult_mode=adult_mode,
596
- scan=scan,
597
- active_section=active_section,
598
- operator_state=operator_state,
599
- )
600
- return (
601
- regions["topbar"],
602
- regions["command_rail"],
603
- regions["workflow"],
604
- regions["operations"],
605
- regions["inspector"],
606
- regions["drawer"],
607
- regions["status"],
608
- regions["artifacts"],
609
- regions["providers"],
610
- render_catalog_table(adult_mode=adult_mode),
611
- run.to_dict() if hasattr(run, "to_dict") else {},
612
- catalog_summary(adult_mode),
613
- scan,
614
- operator_state,
615
- *_button_updates(run, operator_state),
616
- )
617
-
618
-
619
- def scan_reference(
620
- run: Any | None,
621
- adult_mode: bool,
622
- upload: Any,
623
- active_section: str,
624
- operator_state: dict[str, Any] | None,
625
- reference_url: str | None = None,
626
- ) -> tuple[Any, ...]:
627
- """
628
- Scan and evaluate a reference image or URL, updating the operator state with findings.
629
-
630
- Parameters:
631
- reference_url (str | None): Optional URL for reference metadata validation.
632
- Only domain and URL hash are recorded; no content crawling or copying occurs.
633
-
634
- Returns:
635
- Rendered dashboard outputs and the computed generated scan.
636
- """
637
- state = operator_state or _default_operator_state()
638
- reference_path = _file_path(upload)
639
- reference_scan = scan_file(reference_path)
640
- reference_metadata = _reference_metadata(upload, reference_url, reference_scan)
641
- generated_scan = _authoritative_generated_scan(state)
642
- minicpm = None
643
- if run is not None and reference_path:
644
- minicpm = judge_with_minicpm(
645
- prompt=getattr(getattr(run, "refined_prompt", None), "refined", DEFAULT_PROMPT),
646
- image_path=reference_path,
647
- scan=reference_scan,
648
- wardrobe_summary=_wardrobe_summary(run),
649
- )
650
- next_state = {
651
- **state,
652
- **({"reference_judge": minicpm.to_dict()} if minicpm else {}),
653
- "reference_metadata": reference_metadata,
654
- "reference_scan": reference_scan,
655
- "reference_export_gate": reference_scan.get("export_gate", "pending"),
656
- "export": state.get("export", generated_scan.get("export_gate", "pending")),
657
- "message": (
658
- "Reference scan complete. Generated artifact export gate is unchanged."
659
- if reference_scan.get("export_gate") == "clear"
660
- else "Reference scan requires review. Generated artifact export gate is unchanged."
661
- ),
662
- }
663
- rendered = _render_stateful(run, adult_mode, generated_scan, active_section, next_state)
664
- return (*rendered, generated_scan)
665
-
666
-
667
- def approve_checkpoint(
668
- run: Any | None,
669
- adult_mode: bool,
670
- scan: dict[str, Any] | None,
671
- active_section: str,
672
- operator_state: dict[str, Any] | None,
673
- ) -> tuple[Any, ...]:
674
- """
675
- Approves the checkpoint if a run and generated artifact exist, blocking approval otherwise. Sets provider readiness based on the ST3GG export gate status.
676
-
677
- Returns:
678
- tuple[Any, ...]: Updated dashboard and operator state reflecting the checkpoint decision.
679
- """
680
- state = operator_state or _default_operator_state()
681
- scan = _authoritative_generated_scan(state)
682
- if run is None:
683
- next_state = {**_default_operator_state(), "provider_state": "blocked", "message": "No run exists yet. Generate an image first."}
684
- elif not _generated_output_path(state):
685
- next_state = {
686
- **state,
687
- "provider_state": "blocked",
688
- "checkpoint": "pending",
689
- "message": "Checkpoint blocked: no generated artifact exists yet.",
690
- }
691
- else:
692
- export_state = scan.get("export_gate", "pending")
693
- next_state = {
694
- **state,
695
- "provider_state": "export_ready" if export_state == "clear" else "checkpointed",
696
- "checkpoint": "approved",
697
- "generated_scan": scan,
698
- "export": export_state,
699
- "message": (
700
- "Checkpoint approved. Export is ready after clear ST3GG scan."
701
- if export_state == "clear"
702
- else "Checkpoint approved. Add an override reason and click Prepare Audit Export to write an audit packet."
703
- ),
704
- }
705
- return _render_stateful(run, adult_mode, scan, active_section, next_state)
706
-
707
-
708
- def export_packet(
709
- run: Any | None,
710
- adult_mode: bool,
711
- scan: dict[str, Any] | None,
712
- active_section: str,
713
- operator_state: dict[str, Any] | None,
714
- override_reason: str | None = None,
715
- ) -> tuple[Any, ...]:
716
- """
717
- Prepare an export packet for the generated artifact with precondition validation and ST3GG gating.
718
-
719
- Validates that a run, approved checkpoint, and generated artifact exist, and checks the
720
- ST3GG export gate status. Blocks export if any precondition fails or if the gate is not
721
- clear (unless an explicit override reason is provided). Writes a governed export packet
722
- when the gate is clear, or an audit-marked packet when overridden.
723
-
724
- Parameters:
725
- run: Active run packet; export is blocked if None.
726
- adult_mode: Whether adult content is enabled for the export.
727
- scan: ST3GG scan results; checked for export gate status.
728
- active_section: Current UI section for rendering.
729
- operator_state: Current operator state; defaults to idle state if None.
730
- override_reason: Reason to override when ST3GG gate is not clear.
731
-
732
- Returns:
733
- Tuple containing dashboard region HTML, run dict, catalog outputs, scan, operator state,
734
- and stop button interactive state.
735
- """
736
- state = operator_state or _default_operator_state()
737
- scan = _authoritative_generated_scan(state)
738
- override_reason = (override_reason or "").strip()
739
- if run is None:
740
- next_state = {**state, "provider_state": "blocked", "export": "blocked", "message": "Export waits for review: generate an image before preparing an audit packet."}
741
- elif state.get("checkpoint") != "approved":
742
- next_state = {**state, "provider_state": "blocked", "export": "blocked", "message": "Export gate active: approve the human checkpoint before release."}
743
- elif not _generated_output_path(state):
744
- next_state = {**state, "provider_state": "blocked", "export": "blocked", "message": "Export waits for review: generate an artifact before preparing evidence."}
745
- elif scan.get("export_gate") != "clear" and not override_reason:
746
- next_state = {**state, "provider_state": "blocked", "export": scan.get("export_gate", "blocked"), "message": "Export gate active: ST3GG is not clear. Add an explicit override reason to write an audit packet."}
747
- else:
748
- export_state = "clear" if scan.get("export_gate") == "clear" else "override"
749
- override_applies = scan.get("export_gate") != "clear" and bool(override_reason)
750
- export_operator_state = {
751
- **state,
752
- **({"st3gg_override_reason": override_reason} if override_applies else {}),
753
- "export": export_state,
754
- }
755
- export = write_export_packet(run=run, scan=scan, operator_state=export_operator_state, adult_mode=adult_mode)
756
- next_state = {
757
- **export_operator_state,
758
- "provider_state": "exported",
759
- "export": export_state,
760
- "export_packet": {"path": export["path"]},
761
- "message": f"Governed export packet prepared: {export['path']}" if export_state == "clear" else f"ST3GG override audit packet prepared: {export['path']}",
762
- }
763
- return _render_stateful(run, adult_mode, scan, active_section, next_state)
764
-
765
-
766
- def stop_provider_job(
767
- run: Any | None,
768
- adult_mode: bool,
769
- scan: dict[str, Any] | None,
770
- active_section: str,
771
- operator_state: dict[str, Any] | None,
772
- ) -> tuple[Any, ...]:
773
- """
774
- Stop the active provider job.
775
-
776
- Halts the current image generation or provider handoff, preserving local evidence and
777
- the dry-run packet. Re-renders the dashboard with provider state set to stopped.
778
-
779
- Returns:
780
- tuple[Any, ...]: Dashboard region HTML fragments, run dict, scan dict, operator state, and UI control updates.
781
- """
782
- scan = scan or scan_file(None)
783
- next_state = {
784
- **(operator_state or _default_operator_state()),
785
- "provider_state": "stopped",
786
- "message": "Provider handoff stopped. Local run packet and evidence remain available.",
787
- }
788
- return _render_stateful(run, adult_mode, scan, active_section, next_state)
789
-
790
-
791
- def reset_demo(
792
- adult_mode: bool,
793
- active_section: str,
794
- ) -> tuple[Any, ...]:
795
- """
796
- Reset the application to its initial state by clearing all generated evidence and reinitializing operator state.
797
-
798
- Returns:
799
- tuple[Any, ...]: Dashboard region HTML fragments, catalog table, empty run state, catalog summary, scan state, operator state, and button state for a reset application.
800
- """
801
- scan = scan_file(None)
802
- operator_state = _default_operator_state()
803
- regions = _dashboard_regions(adult_mode=adult_mode, scan=scan, active_section=active_section, operator_state=operator_state)
804
- return (
805
- regions["topbar"],
806
- regions["command_rail"],
807
- regions["workflow"],
808
- regions["operations"],
809
- regions["inspector"],
810
- regions["drawer"],
811
- regions["status"],
812
- regions["artifacts"],
813
- regions["providers"],
814
- render_catalog_table(adult_mode=adult_mode),
815
- {},
816
- catalog_summary(adult_mode),
817
- scan,
818
- None,
819
- scan,
820
- operator_state,
821
- gr.update(interactive=False),
822
- gr.update(interactive=False),
823
- gr.update(interactive=False),
824
- )
825
-
826
-
827
- initial_operator_state = _default_operator_state()
828
- initial_regions = _dashboard_regions(scan=scan_file(None), operator_state=initial_operator_state)
829
-
830
- with gr.Blocks(title="NEXUS Visual Weaver") as demo:
831
- active_run_state = gr.State(None)
832
- scan_state = gr.State(scan_file(None))
833
- operator_state = gr.State(initial_operator_state)
834
- topbar_html = gr.HTML(initial_regions["topbar"], container=False, visible=False)
835
-
836
- with gr.Row(elem_id="nw-creator-workbench", elem_classes=["nw-creator-workbench"]):
837
- with gr.Column(scale=5, min_width=520, elem_id="nw-creator-panel"):
838
- gr.Markdown("### Create Couture Image")
839
- gr.Markdown("Describe the look, choose wardrobe controls, then generate. Reference upload is optional.")
840
- prompt = gr.Textbox(
841
- value=DEFAULT_PROMPT,
842
- label="Describe the look",
843
- lines=4,
844
- max_lines=6,
845
- )
846
-
847
- with gr.Row():
848
- seed_value = gr.Number(value=-1, precision=0, label="Seed (-1 randomizes)")
849
- style_strength = gr.Dropdown(
850
- ["Balanced", "High Fashion", "Cinematic"],
851
- value="High Fashion",
852
- label="Style Strength",
853
- )
854
- aspect = gr.Dropdown(["Portrait", "Square"], value="Portrait", label="Aspect")
855
- with gr.Row(elem_classes=["nw-primary-actions"]):
856
- run_btn = gr.Button("Generate Image", variant="primary", scale=2)
857
- reset_btn = gr.Button("Reset", scale=1)
858
-
859
- with gr.Row():
860
- silhouette = gr.Dropdown(
861
- ["structured long coat", "fitted gothic bodice", "layered tactical silhouette"],
862
- value="structured long coat",
863
- label="Silhouette",
864
- )
865
- outerwear = gr.Dropdown(
866
- ["black patent leather long coat", "faux fur collar coat", "tailored rain slicker"],
867
- value="black patent leather long coat",
868
- label="Outerwear",
869
- )
870
- with gr.Row():
871
- upper_body = gr.Dropdown(
872
- ["Chantilly lace neckline", "black mesh layer", "structured corset bodice"],
873
- value="Chantilly lace neckline",
874
- label="Upper Body",
875
- )
876
- footwear = gr.Dropdown(
877
- ["platform boots", "patent leather heels", "armored couture boots"],
878
- value="platform boots",
879
- label="Footwear",
880
- )
881
- with gr.Row():
882
- palette = gr.Dropdown(
883
- ["black, crimson, cyan neon", "obsidian, pearl, crimson", "graphite, magenta, cold blue"],
884
- value="black, crimson, cyan neon",
885
- label="Palette",
886
- )
887
- hardware = gr.Dropdown(
888
- ["crimson hardware", "silver occult buckles", "holographic NEXUS sigils"],
889
- value="crimson hardware",
890
- label="Hardware",
891
- )
892
-
893
- with gr.Accordion("Advanced: scan external file", open=False):
894
- gr.Markdown("Optional. Generate directly unless you need ST3GG to inspect an uploaded reference or output file.")
895
- with gr.Row():
896
- reasoning_mode = gr.Radio(["Strict", "Frontier"], value="Strict", label="Reasoning Mode")
897
- video_preset = gr.Dropdown(["Wan2.2 I2V", "LTX-2.3"], value="Wan2.2 I2V", label="Video preset (deferred)")
898
- with gr.Row():
899
- adult_mode = gr.Checkbox(
900
- value=False,
901
- label="Adult Mode 18+ catalog scope",
902
- info="Off by default. Never disables security, consent, or export gates.",
903
- )
904
- reference_url = gr.Textbox(
905
- label="Reference URL (metadata only)",
906
- placeholder="https://shop.example/reference-garment",
907
- )
908
- upload = gr.File(label="Optional file for ST3GG scan", file_count="single", type="filepath")
909
- with gr.Row():
910
- scan_btn = gr.Button("Scan Uploaded File", scale=1)
911
- stop_btn = gr.Button("Stop Job", variant="stop", interactive=False, scale=1)
912
-
913
- with gr.Column(scale=4, min_width=460, elem_id="nw-output-panel"):
914
- gr.Markdown("### Output")
915
- artifact_html = gr.HTML(initial_regions["artifacts"], container=False)
916
- with gr.Row(elem_id="nw-checkpoint-actions", elem_classes=["nw-checkpoint-actions"]):
917
- checkpoint_btn = gr.Button("Approve Checkpoint", scale=1, interactive=False)
918
- export_btn = gr.Button("Prepare Audit Export", scale=1, interactive=False)
919
- override_reason = gr.Textbox(
920
- label="ST3GG Override Reason",
921
- placeholder="Required only when ST3GG asks for review; explain why this audit packet may be written.",
922
- lines=2,
923
- max_lines=3,
924
- )
925
- gr.Markdown("Generation is not export. Every artifact stays behind ST3GG review and human checkpoint.")
926
-
927
- with gr.Accordion("Run Anatomy", open=False):
928
- with gr.Row(elem_id="nw-workspace", elem_classes=["nw-workspace"]):
929
- with gr.Column(scale=1, min_width=160, elem_id="nw-native-rail"):
930
- section_nav = gr.Radio(SECTIONS, value="Forge", label="Technical Section", elem_id="nw-section-nav")
931
- command_rail_html = gr.HTML(initial_regions["command_rail"], container=False)
932
- with gr.Column(scale=5, min_width=620, elem_id="nw-main-column"):
933
- workflow_html = gr.HTML(initial_regions["workflow"], container=False)
934
-
935
- with gr.Accordion("Wardrobe Evidence", open=False):
936
- operations_html = gr.HTML(initial_regions["operations"], container=False)
937
- drawer_html = gr.HTML(initial_regions["drawer"], container=False)
938
-
939
- with gr.Accordion("Technical Evidence", open=False):
940
- status_html = gr.HTML(initial_regions["status"], container=False)
941
- inspector_html = gr.HTML(initial_regions["inspector"], container=False)
942
- with gr.Accordion("Provider Diagnostics", open=False):
943
- provider_html = gr.HTML(initial_regions["providers"], container=False)
944
-
945
- with gr.Accordion("Catalog, run record, and security evidence", open=False):
946
- catalog_html = gr.HTML(render_catalog_table(False), container=False)
947
- with gr.Row():
948
- run_json = gr.JSON(label="GenerationRun")
949
- catalog_json = gr.JSON(label="Catalog Summary")
950
- scan_json = gr.JSON(label="ST3GG Scan")
951
-
952
- dashboard_outputs = [
953
- topbar_html,
954
- command_rail_html,
955
- workflow_html,
956
- operations_html,
957
- inspector_html,
958
- drawer_html,
959
- status_html,
960
- artifact_html,
961
- provider_html,
962
- catalog_html,
963
- run_json,
964
- catalog_json,
965
- scan_json,
966
- ]
967
-
968
- stateful_outputs = dashboard_outputs + [active_run_state, scan_state, operator_state, checkpoint_btn, export_btn, stop_btn]
969
-
970
- operator_outputs = dashboard_outputs + [operator_state, checkpoint_btn, export_btn, stop_btn]
971
-
972
- run_click = run_btn.click(
973
- fn=run_weave,
974
- inputs=[
975
- prompt,
976
- reasoning_mode,
977
- video_preset,
978
- adult_mode,
979
- upload,
980
- section_nav,
981
- silhouette,
982
- outerwear,
983
- upper_body,
984
- footwear,
985
- palette,
986
- hardware,
987
- reference_url,
988
- seed_value,
989
- style_strength,
990
- aspect,
991
- ],
992
- outputs=stateful_outputs,
993
- api_name="run_active_weave",
994
- concurrency_limit=1,
995
- concurrency_id="flux-gpu",
996
- )
997
- run_submit = prompt.submit(
998
- fn=run_weave,
999
- inputs=[
1000
- prompt,
1001
- reasoning_mode,
1002
- video_preset,
1003
- adult_mode,
1004
- upload,
1005
- section_nav,
1006
- silhouette,
1007
- outerwear,
1008
- upper_body,
1009
- footwear,
1010
- palette,
1011
- hardware,
1012
- reference_url,
1013
- seed_value,
1014
- style_strength,
1015
- aspect,
1016
- ],
1017
- outputs=stateful_outputs,
1018
- api_name=False,
1019
- concurrency_limit=1,
1020
- concurrency_id="flux-gpu",
1021
- )
1022
- adult_mode.change(
1023
- fn=toggle_adult_visibility,
1024
- inputs=[adult_mode, section_nav, upload],
1025
- outputs=[
1026
- topbar_html,
1027
- command_rail_html,
1028
- operations_html,
1029
- inspector_html,
1030
- artifact_html,
1031
- provider_html,
1032
- catalog_html,
1033
- catalog_json,
1034
- scan_json,
1035
- operator_state,
1036
- ],
1037
- api_name="toggle_adult_catalog",
1038
- queue=False,
1039
- )
1040
- section_nav.change(
1041
- fn=refresh_section,
1042
- inputs=[section_nav, adult_mode, active_run_state, scan_state, operator_state],
1043
- outputs=[command_rail_html, operations_html, inspector_html, artifact_html, provider_html, scan_json],
1044
- api_name=False,
1045
- queue=False,
1046
- )
1047
- scan_btn.click(
1048
- fn=scan_reference,
1049
- inputs=[active_run_state, adult_mode, upload, section_nav, operator_state, reference_url],
1050
- outputs=dashboard_outputs + [operator_state, checkpoint_btn, export_btn, stop_btn, scan_state],
1051
- api_name="scan_reference",
1052
- queue=False,
1053
- )
1054
- checkpoint_btn.click(
1055
- fn=approve_checkpoint,
1056
- inputs=[active_run_state, adult_mode, scan_state, section_nav, operator_state],
1057
- outputs=operator_outputs,
1058
- api_name="approve_checkpoint",
1059
- queue=False,
1060
- )
1061
- export_btn.click(
1062
- fn=export_packet,
1063
- inputs=[active_run_state, adult_mode, scan_state, section_nav, operator_state, override_reason],
1064
- outputs=operator_outputs,
1065
- api_name="prepare_export_packet",
1066
- queue=False,
1067
- )
1068
- stop_btn.click(
1069
- fn=stop_provider_job,
1070
- inputs=[active_run_state, adult_mode, scan_state, section_nav, operator_state],
1071
- outputs=operator_outputs,
1072
- api_name="stop_provider_job",
1073
- queue=False,
1074
- cancels=[run_click, run_submit],
1075
- )
1076
- reset_btn.click(
1077
- fn=reset_demo,
1078
- inputs=[adult_mode, section_nav],
1079
- outputs=stateful_outputs,
1080
- api_name="reset_demo_state",
1081
- queue=False,
1082
- cancels=[run_click, run_submit],
1083
- )
1084
- demo.load(
1085
- fn=lambda: (render_catalog_table(False), catalog_summary(False), scan_file(None), scan_file(None), _default_operator_state()),
1086
- outputs=[catalog_html, catalog_json, scan_json, scan_state, operator_state],
1087
- api_name=False,
1088
- )
1089
-
1090
 
1091
  if __name__ == "__main__":
1092
- if hasattr(sys.stdout, "reconfigure"):
1093
- sys.stdout.reconfigure(encoding="utf-8", errors="replace")
1094
- if hasattr(sys.stderr, "reconfigure"):
1095
- sys.stderr.reconfigure(encoding="utf-8", errors="replace")
1096
-
1097
- demo.launch(
1098
- server_name="0.0.0.0",
1099
- server_port=int(os.environ.get("NEXUS_PORT", os.environ.get("PORT", "7860"))),
1100
- quiet=True,
1101
- mcp_server=True,
1102
- ssr_mode=False,
1103
- css=APP_CSS,
1104
- theme=APP_THEME,
1105
- )
 
1
+ """NEXUS Visual Weaver v2.0 Diagnostic Build"""
2
+ import gradio as gr
 
 
3
  import os
4
  import sys
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
+ # Add src to path
7
+ ROOT = os.path.dirname(os.path.abspath(__file__))
8
+ SRC = os.path.join(ROOT, "src")
9
+ if SRC not in sys.path:
10
+ sys.path.insert(0, SRC)
11
 
12
+ DIAGNOSTIC = []
 
13
 
14
+ def check_imports():
15
+ results = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
+ # Basic imports
 
 
 
 
 
18
  try:
19
+ import spaces
20
+ results.append(("spaces", "OK", ""))
21
+ except Exception as e:
22
+ results.append(("spaces", "FAIL", str(e)[:100]))
23
+
24
+ # Package imports
25
+ for mod_name, mod_path in [
26
+ ("catalog", "nexus_visual_weaver.catalog"),
27
+ ("exporter", "nexus_visual_weaver.exporter"),
28
+ ("hf_runtime", "nexus_visual_weaver.hf_runtime"),
29
+ ("model_relay", "nexus_visual_weaver.model_relay"),
30
+ ("planner", "nexus_visual_weaver.planner"),
31
+ ("provider_runtime", "nexus_visual_weaver.provider_runtime"),
32
+ ("render", "nexus_visual_weaver.render"),
33
+ ("security", "nexus_visual_weaver.security"),
34
+ ("styles", "nexus_visual_weaver.styles"),
35
+ ]:
36
+ try:
37
+ __import__(mod_path)
38
+ results.append((mod_name, "OK", ""))
39
+ except Exception as e:
40
+ results.append((mod_name, "FAIL", str(e)[:100]))
41
+
42
+ return results
43
+
44
+ def run_diagnostics():
45
+ results = check_imports()
46
+ text = "## Import Diagnostics\n"
47
+ all_ok = True
48
+ for name, status, error in results:
49
+ icon = "✅" if status == "OK" else "❌"
50
+ text += f"- {icon} **{name}**: {status}"
51
+ if error:
52
+ text += f" — `{error}`"
53
+ all_ok = False
54
+ text += "\n"
55
+
56
+ if all_ok:
57
+ text += "\n🎉 All imports OK! The Space should work."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  else:
59
+ text += "\n⚠️ Some imports failed. Check the errors above."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
+ return text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
+ with gr.Blocks(title="NEXUS Visual Weaver v2.0 — Diagnostic") as demo:
64
+ gr.Markdown("# 🧵 NEXUS Visual Weaver v2.0 — Diagnostic Mode")
65
+ gr.Markdown("Checking all module imports to find the runtime error...")
 
 
 
 
 
 
 
66
 
67
+ diag_btn = gr.Button("Run Diagnostics", variant="primary")
68
+ diag_output = gr.Markdown("Click Run Diagnostics to check...")
69
 
70
+ diag_btn.click(fn=run_diagnostics, inputs=[], outputs=diag_output)
 
 
 
 
 
71
 
72
+ # Auto-run on load
73
+ demo.load(fn=run_diagnostics, inputs=[], outputs=diag_output)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
 
75
  if __name__ == "__main__":
76
+ demo.launch(server_name="0.0.0.0", server_port=int(os.environ.get("PORT", "7860")))