Spaces:
Running
Running
Commit ·
1433b16
1
Parent(s): 42bbd85
Updated README, added tracing capabilities, changed size of flowchart, vendored the animation assets so this meets off the grid.
Browse files- .gitignore +2 -0
- LICENSE +21 -0
- README.md +185 -9
- app.py +69 -5
- build/build.sh +17 -0
- build/cm-entry.mjs +10 -0
- build/gradio-entry.mjs +1 -0
- build/package.json +1 -0
- frontend.html +40 -49
- static/cm.bundle.js +0 -0
- static/fonts.css +333 -0
- static/fonts/6NU78FyLNQOQZAnv9bYEvDiIdE9Ea92uemAk_WBq8U_9v0c2Wa0KxC9TeP2Xz5c.woff2 +0 -0
- static/fonts/6NU78FyLNQOQZAnv9bYEvDiIdE9Ea92uemAk_WBq8U_9v0c2Wa0KxCBTeP2Xz5fU8w.woff2 +0 -0
- static/fonts/6NU78FyLNQOQZAnv9bYEvDiIdE9Ea92uemAk_WBq8U_9v0c2Wa0KxCFTeP2Xz5fU8w.woff2 +0 -0
- static/fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpQ59CxCis4UvI.woff2 +0 -0
- static/fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpS59CxCis4UvI.woff2 +0 -0
- static/fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpT59CxCis4UvI.woff2 +0 -0
- static/fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpd59CxCis4.woff2 +0 -0
- static/fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx3cwgknk-6nFg.woff2 +0 -0
- static/fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx7cwgknk-6nFg.woff2 +0 -0
- static/fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxDcwgknk-4.woff2 +0 -0
- static/fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxPcwgknk-6nFg.woff2 +0 -0
- static/fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxTcwgknk-6nFg.woff2 +0 -0
- static/fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx_cwgknk-6nFg.woff2 +0 -0
- static/gradio-client.js +3 -0
- static/mermaid.min.js +0 -0
.gitignore
CHANGED
|
@@ -5,3 +5,5 @@ venv
|
|
| 5 |
__pycache__
|
| 6 |
.DS_Store
|
| 7 |
Screenshot 2026-06-07 at 10.46.25 AM.png
|
|
|
|
|
|
|
|
|
| 5 |
__pycache__
|
| 6 |
.DS_Store
|
| 7 |
Screenshot 2026-06-07 at 10.46.25 AM.png
|
| 8 |
+
build/node_modules/
|
| 9 |
+
agent_traces.jsonl
|
LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2026 Rishi Jain
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
README.md
CHANGED
|
@@ -4,20 +4,196 @@ emoji: 📊
|
|
| 4 |
colorFrom: indigo
|
| 5 |
colorTo: blue
|
| 6 |
sdk: gradio
|
| 7 |
-
sdk_version: 6.16.0
|
| 8 |
python_version: '3.13'
|
|
|
|
| 9 |
app_file: app.py
|
| 10 |
-
pinned:
|
| 11 |
license: mit
|
| 12 |
-
short_description: Turn code into a readable Mermaid.js flowchart 📊
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
---
|
| 14 |
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
|
| 19 |
-
|
| 20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
|
|
|
|
| 22 |
|
| 23 |
-
|
|
|
|
| 4 |
colorFrom: indigo
|
| 5 |
colorTo: blue
|
| 6 |
sdk: gradio
|
|
|
|
| 7 |
python_version: '3.13'
|
| 8 |
+
sdk_version: 6.16.0
|
| 9 |
app_file: app.py
|
| 10 |
+
pinned: true
|
| 11 |
license: mit
|
| 12 |
+
short_description: Turn code into a readable Mermaid.js flowchart 📊!
|
| 13 |
+
tags:
|
| 14 |
+
- build-small-hackathon
|
| 15 |
+
- backyard-ai
|
| 16 |
+
- llama-cpp
|
| 17 |
+
- field-notes
|
| 18 |
+
- sharing-is-caring
|
| 19 |
+
- off-brand
|
| 20 |
+
- off-the-grid
|
| 21 |
+
- code
|
| 22 |
+
- mermaid.js
|
| 23 |
+
- flowchart
|
| 24 |
+
- small-models
|
| 25 |
+
- seq2seq
|
| 26 |
+
- gradio
|
| 27 |
+
- agentic
|
| 28 |
+
---
|
| 29 |
+
|
| 30 |
+
# 📊 CodeFlow
|
| 31 |
+
|
| 32 |
+
**Paste code → read its logic as a flowchart.** A 30B coder model runs entirely on **CPU via llama.cpp** to translate source code into a clean, animated [Mermaid.js](https://mermaid.js.org/) control-flow diagram — with each node wired back to the exact lines it came from.
|
| 33 |
+
|
| 34 |
+
### 🔗 Links
|
| 35 |
+
|
| 36 |
+
[🚀 **Live Space**][space] · [▶️ **Demo Video**][video] · [🐦 **Social Post**][social] · [📓 **Field Notes (blog)**][blog] · [🔍 **Agent Traces**][traces]
|
| 37 |
+
|
| 38 |
+
<!-- ╔═══════════════════════════════════════════════════════════════╗
|
| 39 |
+
║ FILL THESE IN — replace each REPLACE_ME with your real URL. ║
|
| 40 |
+
╚═══════════════════════════════════════════════════════════════╝ -->
|
| 41 |
+
[space]: REPLACE_ME "Hugging Face Space"
|
| 42 |
+
[video]: REPLACE_ME "Demo video"
|
| 43 |
+
[social]: REPLACE_ME "Social post"
|
| 44 |
+
[blog]: REPLACE_ME "Field notes / blog post"
|
| 45 |
+
[traces]: REPLACE_ME "Agent traces (or https://<your-space>.hf.space/traces)"
|
| 46 |
+
|
| 47 |
---
|
| 48 |
|
| 49 |
+
## ❓ The Problem
|
| 50 |
+
|
| 51 |
+
Reading unfamiliar code means simulating its control flow in your head — chasing branches, loops, and early returns line by line. That's slow, error-prone, and gets worse the deeper the nesting. Existing "code → diagram" tools are usually rigid AST parsers (brittle, language-locked) or cloud LLM APIs (your code leaves the building).
|
| 52 |
+
|
| 53 |
+
**CodeFlow** turns any snippet into a scannable flowchart you can audit at a glance — generated by a real language model that runs **100% locally**, so nothing is sent to an external API.
|
| 54 |
+
|
| 55 |
+
## ⚙️ How It Works
|
| 56 |
+
|
| 57 |
+
```
|
| 58 |
+
Paste code ──▶ Generate ──▶ POST /generate_flowchart (Gradio API)
|
| 59 |
+
│
|
| 60 |
+
number the source lines + structured system prompt
|
| 61 |
+
│
|
| 62 |
+
Qwen3-Coder-30B-A3B (llama.cpp · CPU)
|
| 63 |
+
│
|
| 64 |
+
<thinking> …reasoning… </thinking>
|
| 65 |
+
graph TD … nodes & edges …
|
| 66 |
+
<linemap> A:1 B:2 C:3-4 </linemap>
|
| 67 |
+
│
|
| 68 |
+
strip reasoning · parse + validate the line-map · sanitize labels
|
| 69 |
+
│
|
| 70 |
+
{ mermaid, linemap } ──▶ append agent_traces.jsonl
|
| 71 |
+
│
|
| 72 |
+
Mermaid render + "trace-the-path" reveal + node ↔ code linking
|
| 73 |
+
```
|
| 74 |
+
|
| 75 |
+
1. You paste code (or pick a pre-rendered example) into the **CodeMirror** editor and hit **Generate**.
|
| 76 |
+
2. The backend numbers the source lines and sends them with a strict system prompt to **Qwen3-Coder** running on **llama.cpp**.
|
| 77 |
+
3. The model returns hidden `<thinking>`, the Mermaid `graph`, and a `<linemap>` mapping every node to its source line(s).
|
| 78 |
+
4. The server strips the reasoning, **validates** the line-map against the source, sanitizes labels for Mermaid, and returns `{ mermaid, linemap }`.
|
| 79 |
+
5. The frontend renders the diagram with a **trace-the-path reveal** that flows out of a persistent Start node while the canvas scrolls along in real time.
|
| 80 |
+
6. **Node ↔ code linking:** hover a node to highlight its source lines, click a node to jump-and-edit them, or move your cursor over a line to light up the matching node.
|
| 81 |
+
7. Every generation is captured as a structured **agent trace** (`/traces`).
|
| 82 |
+
|
| 83 |
+
## 🧰 Tech Stack
|
| 84 |
+
|
| 85 |
+
| Layer | What it is | Used for |
|
| 86 |
+
|---|---|---|
|
| 87 |
+
| **Model** | [Qwen3-Coder-30B-A3B-Instruct](https://huggingface.co/Qwen) (Mixture-of-Experts) | Code → Mermaid + line-map generation |
|
| 88 |
+
| **Quantization** | [Unsloth](https://huggingface.co/unsloth) Dynamic **UD-Q3_K_XL** GGUF (~3-bit) | Shrinks the 30B model to run on CPU |
|
| 89 |
+
| **Inference** | [`llama-cpp-python`](https://github.com/abetlen/llama-cpp-python) (llama.cpp) | Local CPU inference (`n_ctx=4096`) |
|
| 90 |
+
| **Model fetch** | `huggingface_hub` | Downloads the GGUF on first run |
|
| 91 |
+
| **Server** | [Gradio](https://www.gradio.app/) `gr.Server` + FastAPI | `/generate_flowchart` API, `/` UI, `/traces` |
|
| 92 |
+
| **Frontend** | A single self-contained `frontend.html` (vanilla JS + CSS custom properties) | Editor, diagram, animation, theming |
|
| 93 |
+
| **Editor** | [CodeMirror 6](https://codemirror.net/) — **vendored** bundle (`static/cm.bundle.js`) | Syntax-highlighted code input |
|
| 94 |
+
| **Diagrams** | [Mermaid.js 10](https://mermaid.js.org/) — **vendored** UMD (`static/mermaid.min.js`) | Flowchart rendering |
|
| 95 |
+
| **Animation** | Web Animations API | Trace-the-path reveal + theme crossfade |
|
| 96 |
+
| **Type** | Fraunces · Hanken Grotesk · JetBrains Mono — **vendored** woff2 (`static/fonts/`) | Custom, non-default look |
|
| 97 |
+
| **Assets** | All JS/CSS/fonts bundled into `static/` (no CDN at runtime) | True offline operation |
|
| 98 |
+
| **Observability** | Hand-rolled JSONL agent traces | One trace per generation, served at `/traces` |
|
| 99 |
+
| **Tests** | `smoke-test.sh` (headless Chrome) | 13 build/render checks |
|
| 100 |
+
| **Deploy** | Hugging Face Spaces | Hosting |
|
| 101 |
+
|
| 102 |
+
## 🔢 Total Parameters
|
| 103 |
+
|
| 104 |
+
CodeFlow is driven by **Qwen3-Coder-30B-A3B-Instruct** — a **Mixture-of-Experts** model with:
|
| 105 |
+
|
| 106 |
+
- **≈ 30.5 billion total parameters**
|
| 107 |
+
- **≈ 3.3 billion active parameters per token** (128 experts, 8 activated)
|
| 108 |
+
|
| 109 |
+
It's served as an **Unsloth Dynamic ~3-bit (UD-Q3_K_XL) GGUF**, which compresses those 30B weights to a CPU-runnable footprint (~13 GB on disk) — letting a 30B-class model generate diagrams **off the grid**, with no GPU and no external API.
|
| 110 |
+
|
| 111 |
+
## 🏅 Badges (5 / 6)
|
| 112 |
+
|
| 113 |
+
These map to the Space tags above.
|
| 114 |
+
|
| 115 |
+
| Badge | How CodeFlow earns it |
|
| 116 |
+
|---|---|
|
| 117 |
+
| 🔌 **Off the Grid** | **No external API or CDN at runtime — period.** The model runs fully locally (Qwen3-Coder GGUF on CPU via llama.cpp), and *every* frontend asset (Mermaid, CodeMirror, the Gradio client, all fonts) is vendored into `static/`. The Gradio share tunnel is off (`share=False`). The **only** network call in the whole project is the one-time model download at startup. The UI even runs fully offline from `file://`. |
|
| 118 |
+
| 🎨 **Off-Brand** | **Zero default-Gradio look.** A bespoke single-file UI: custom "Pine & Sage" palette (one-word rust fallback), Fraunces + Hanken Grotesk type, a hand-drawn decision-node logo, restyled Mermaid nodes, and a trace-the-path reveal animation — deliberately designed *not* to look templated. |
|
| 119 |
+
| 📓 **Field Notes** | See the [blog post][blog]. |
|
| 120 |
+
| 🤝 **Sharing is Caring** | Open-source under **MIT**, a public Space, plus a [social post][social] sharing the process and learnings. |
|
| 121 |
+
| 🤖 **Agentic** | Every model generation is captured as a structured agent trace (input code, the model's reasoning, output, token usage, latency), downloadable at [`/traces`][traces]. |
|
| 122 |
+
|
| 123 |
+
## 🎥 Demo
|
| 124 |
+
|
| 125 |
+
[][video]
|
| 126 |
+
|
| 127 |
+
> ▶️ Click above, or use the [Demo Video][video] link at the top.
|
| 128 |
+
|
| 129 |
+
## 💻 Run It Locally
|
| 130 |
+
|
| 131 |
+
> First launch downloads the **~13 GB GGUF** from Hugging Face. CPU inference is slow (cold generations can take minutes) — the built-in **examples render instantly** because their diagrams are pre-computed.
|
| 132 |
+
|
| 133 |
+
```bash
|
| 134 |
+
# 1. Clone
|
| 135 |
+
git clone REPLACE_ME_repo_url CodeFlow
|
| 136 |
+
cd CodeFlow
|
| 137 |
+
|
| 138 |
+
# 2. Create a virtual env
|
| 139 |
+
python -m venv .venv
|
| 140 |
+
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
| 141 |
+
|
| 142 |
+
# 3. Install deps (uses a prebuilt CPU wheel for llama-cpp-python)
|
| 143 |
+
pip install -r requirements.txt
|
| 144 |
+
|
| 145 |
+
# 4. Run — opens a local Gradio URL
|
| 146 |
+
python app.py
|
| 147 |
+
```
|
| 148 |
+
|
| 149 |
+
Then open the printed URL. **Preview the UI without the model** by opening `frontend.html` directly in a browser (`file://`) — fully offline, since all assets are vendored in `static/`; the example presets render their diagrams instantly.
|
| 150 |
+
|
| 151 |
+
> **Rebuilding the vendored bundles** (optional): the CodeMirror + Gradio-client bundles in `static/` are produced by `build/build.sh` (needs Node). Mermaid and the fonts are downloaded into `static/` as well. You never need this to *run* the app — only to regenerate the bundles.
|
| 152 |
+
|
| 153 |
+
**Endpoints:** `/` (UI) · `/generate_flowchart` (API) · `/traces` (download all agent traces as JSONL).
|
| 154 |
+
|
| 155 |
+
## 🗂️ Repository Structure
|
| 156 |
+
|
| 157 |
+
```
|
| 158 |
+
CodeFlow/
|
| 159 |
+
├── app.py # Gradio + FastAPI server: loads the model and exposes
|
| 160 |
+
│ # /generate_flowchart (API), / (UI), /static, /traces
|
| 161 |
+
├── frontend.html # Self-contained UI — CodeMirror editor, Mermaid render,
|
| 162 |
+
│ # trace-the-path animation, node↔code linking, theming
|
| 163 |
+
├── static/ # Vendored frontend assets — NO CDN at runtime
|
| 164 |
+
│ ├── mermaid.min.js # Mermaid (UMD, ~3.2 MB)
|
| 165 |
+
│ ├── cm.bundle.js # CodeMirror 6 (single IIFE bundle)
|
| 166 |
+
│ ├── gradio-client.js # @gradio/client (IIFE bundle)
|
| 167 |
+
│ ├── fonts.css # @font-face → local woff2
|
| 168 |
+
│ └── fonts/ # Fraunces · Hanken Grotesk · JetBrains Mono (woff2)
|
| 169 |
+
├── build/ # Reproducible bundle build (Node) — build.sh + entry files
|
| 170 |
+
├── requirements.txt # Python deps (CPU llama-cpp-python wheel, gradio, hub)
|
| 171 |
+
├── smoke-test.sh # Headless-Chrome smoke test (13 checks)
|
| 172 |
+
├── notes-for-blog.md # Field Notes — the full build log
|
| 173 |
+
├── README.md # You are here
|
| 174 |
+
├── LICENSE # MIT
|
| 175 |
+
└── agent_traces.jsonl # (created at runtime) one JSON line per generation
|
| 176 |
+
```
|
| 177 |
+
|
| 178 |
+
## ⚠️ Limitations
|
| 179 |
+
|
| 180 |
+
- **CPU inference is slow.** A 30B model on CPU means cold generations can take minutes; the demo leans on pre-rendered examples for instant feedback.
|
| 181 |
+
- **3-bit quantization** trades some fidelity for the ability to run a 30B model at all — occasional imperfect diagrams.
|
| 182 |
+
- **4096-token context** — very large files won't fit; works best on functions/snippets.
|
| 183 |
+
- **Line-map depends on the model.** The `<linemap>` is LLM-generated; the server validates and drops bad entries, so node↔code links can be partial on tricky code.
|
| 184 |
+
- **Paraphrased labels.** Nodes describe logic in plain words (no raw code), so they read cleanly but aren't verbatim.
|
| 185 |
+
- **Mermaid parse failures** on unusual syntax are possible (the raw output is shown so nothing is lost).
|
| 186 |
+
- **Ephemeral traces on Spaces.** `agent_traces.jsonl` lives on the runtime filesystem and resets on restart/rebuild — download it before then.
|
| 187 |
+
|
| 188 |
+
## 🙏 Credits
|
| 189 |
|
| 190 |
+
- **Model:** [Qwen3-Coder](https://huggingface.co/Qwen) (Qwen Team, Alibaba) — GGUF quant by [Unsloth](https://huggingface.co/unsloth).
|
| 191 |
+
- **Inference:** [llama.cpp](https://github.com/ggml-org/llama.cpp) via [`llama-cpp-python`](https://github.com/abetlen/llama-cpp-python) (Andrei Betlen).
|
| 192 |
+
- **App framework:** [Gradio](https://www.gradio.app/) (Hugging Face).
|
| 193 |
+
- **Diagrams:** [Mermaid.js](https://mermaid.js.org/) · **Editor:** [CodeMirror](https://codemirror.net/).
|
| 194 |
+
- **Type:** Fraunces, Hanken Grotesk, JetBrains Mono ([Google Fonts](https://fonts.google.com/), SIL OFL).
|
| 195 |
+
- **Built for** the Build Small Hackathon.
|
| 196 |
|
| 197 |
+
## 📄 License
|
| 198 |
|
| 199 |
+
Released under the **MIT License** — see [`LICENSE`](LICENSE). © 2026 Rishi Jain.
|
app.py
CHANGED
|
@@ -3,11 +3,14 @@ from huggingface_hub import hf_hub_download
|
|
| 3 |
from llama_cpp import Llama
|
| 4 |
import gradio as gr
|
| 5 |
from gradio import Server
|
| 6 |
-
from fastapi.responses import HTMLResponse #
|
|
|
|
| 7 |
from typing import Any, cast # to resolve PyLance freaking out over llama-cpp-python in the generate_flowchart function
|
| 8 |
from textwrap import dedent
|
| 9 |
from pathlib import Path # load the custom frontend from disk
|
| 10 |
import re # remove thinking tag from response
|
|
|
|
|
|
|
| 11 |
|
| 12 |
# ----- Get Model ----- #
|
| 13 |
# Download Q4_K_M GGUF file from the repo
|
|
@@ -26,6 +29,20 @@ llm = Llama(
|
|
| 26 |
# ----- Init App ----- #
|
| 27 |
app = gr.Server(title="Code-to-Flowchart Generator")
|
| 28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
# ----- Functions ----- #
|
| 30 |
|
| 31 |
# This is a cleaning function to resolve common syntax errors.
|
|
@@ -138,6 +155,7 @@ def generate_flowchart(src_code: str) -> dict:
|
|
| 138 |
llm.reset()
|
| 139 |
|
| 140 |
# Casting else PyLance gets mad
|
|
|
|
| 141 |
response = cast(Any, llm.create_chat_completion(
|
| 142 |
messages=[
|
| 143 |
{"role": "system", "content": system_prompt},
|
|
@@ -147,11 +165,15 @@ def generate_flowchart(src_code: str) -> dict:
|
|
| 147 |
max_tokens=1024,
|
| 148 |
stream=False
|
| 149 |
))
|
|
|
|
| 150 |
|
| 151 |
-
|
|
|
|
| 152 |
|
| 153 |
-
#
|
| 154 |
-
|
|
|
|
|
|
|
| 155 |
|
| 156 |
# Extract + strip the node→line map, then validate it against the source length
|
| 157 |
linemap: dict = {}
|
|
@@ -163,6 +185,25 @@ def generate_flowchart(src_code: str) -> dict:
|
|
| 163 |
# Quote-wrap each node label and escape any leaked code characters
|
| 164 |
mermaid = quote_labels(content).strip() # and remove excess whitespace
|
| 165 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
return {"mermaid": mermaid, "linemap": linemap}
|
| 167 |
|
| 168 |
# ----- Custom Frontend ----- #
|
|
@@ -176,4 +217,27 @@ index_html = (Path(__file__).parent / "frontend.html").read_text(encoding="utf-8
|
|
| 176 |
def index():
|
| 177 |
return HTMLResponse(index_html)
|
| 178 |
|
| 179 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
from llama_cpp import Llama
|
| 4 |
import gradio as gr
|
| 5 |
from gradio import Server
|
| 6 |
+
from fastapi.responses import HTMLResponse, PlainTextResponse, FileResponse # frontend + traces + vendored static assets
|
| 7 |
+
import mimetypes
|
| 8 |
from typing import Any, cast # to resolve PyLance freaking out over llama-cpp-python in the generate_flowchart function
|
| 9 |
from textwrap import dedent
|
| 10 |
from pathlib import Path # load the custom frontend from disk
|
| 11 |
import re # remove thinking tag from response
|
| 12 |
+
import json, time, uuid # agent-trace logging
|
| 13 |
+
from datetime import datetime, timezone
|
| 14 |
|
| 15 |
# ----- Get Model ----- #
|
| 16 |
# Download Q4_K_M GGUF file from the repo
|
|
|
|
| 29 |
# ----- Init App ----- #
|
| 30 |
app = gr.Server(title="Code-to-Flowchart Generator")
|
| 31 |
|
| 32 |
+
# ----- Agent traces ----- #
|
| 33 |
+
# Each generation appends one JSON line capturing the full LLM call (input code,
|
| 34 |
+
# the model's reasoning, output Mermaid + linemap, token usage, latency).
|
| 35 |
+
# Download the whole log from the running app at /traces .
|
| 36 |
+
MODEL_NAME = "unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF:UD-Q3_K_XL"
|
| 37 |
+
TRACE_PATH = Path(__file__).parent / "agent_traces.jsonl"
|
| 38 |
+
|
| 39 |
+
def write_trace(record: dict) -> None:
|
| 40 |
+
try:
|
| 41 |
+
with open(TRACE_PATH, "a", encoding="utf-8") as f:
|
| 42 |
+
f.write(json.dumps(record, ensure_ascii=False) + "\n")
|
| 43 |
+
except Exception:
|
| 44 |
+
pass # tracing must never break generation
|
| 45 |
+
|
| 46 |
# ----- Functions ----- #
|
| 47 |
|
| 48 |
# This is a cleaning function to resolve common syntax errors.
|
|
|
|
| 155 |
llm.reset()
|
| 156 |
|
| 157 |
# Casting else PyLance gets mad
|
| 158 |
+
t0 = time.perf_counter()
|
| 159 |
response = cast(Any, llm.create_chat_completion(
|
| 160 |
messages=[
|
| 161 |
{"role": "system", "content": system_prompt},
|
|
|
|
| 165 |
max_tokens=1024,
|
| 166 |
stream=False
|
| 167 |
))
|
| 168 |
+
latency_ms = round((time.perf_counter() - t0) * 1000)
|
| 169 |
|
| 170 |
+
raw = response["choices"][0]["message"]["content"]
|
| 171 |
+
usage = response.get("usage", {}) or {}
|
| 172 |
|
| 173 |
+
# Capture the model's hidden reasoning for the trace, then strip the tags
|
| 174 |
+
think = re.search(r'<thinking>(.*?)</thinking>', raw, flags=re.DOTALL)
|
| 175 |
+
reasoning = think.group(1).strip() if think else ""
|
| 176 |
+
content = re.sub(r'<thinking>.*?</thinking>', '', raw, flags=re.DOTALL)
|
| 177 |
|
| 178 |
# Extract + strip the node→line map, then validate it against the source length
|
| 179 |
linemap: dict = {}
|
|
|
|
| 185 |
# Quote-wrap each node label and escape any leaked code characters
|
| 186 |
mermaid = quote_labels(content).strip() # and remove excess whitespace
|
| 187 |
|
| 188 |
+
# ----- Agent trace (append-only JSONL; downloadable at /traces) -----
|
| 189 |
+
write_trace({
|
| 190 |
+
"id": uuid.uuid4().hex,
|
| 191 |
+
"ts": datetime.now(timezone.utc).isoformat(),
|
| 192 |
+
"event": "generate_flowchart",
|
| 193 |
+
"model": MODEL_NAME,
|
| 194 |
+
"params": {"temperature": 0.1, "max_tokens": 1024, "n_ctx": 4096},
|
| 195 |
+
"input": {"src_code": src_code, "num_lines": num_lines},
|
| 196 |
+
"reasoning": reasoning,
|
| 197 |
+
"output": {"raw": raw, "mermaid": mermaid, "linemap": linemap},
|
| 198 |
+
"usage": {
|
| 199 |
+
"prompt_tokens": usage.get("prompt_tokens"),
|
| 200 |
+
"completion_tokens": usage.get("completion_tokens"),
|
| 201 |
+
"total_tokens": usage.get("total_tokens"),
|
| 202 |
+
},
|
| 203 |
+
"latency_ms": latency_ms,
|
| 204 |
+
"status": "ok",
|
| 205 |
+
})
|
| 206 |
+
|
| 207 |
return {"mermaid": mermaid, "linemap": linemap}
|
| 208 |
|
| 209 |
# ----- Custom Frontend ----- #
|
|
|
|
| 217 |
def index():
|
| 218 |
return HTMLResponse(index_html)
|
| 219 |
|
| 220 |
+
# Serve the vendored frontend assets (Mermaid, CodeMirror bundle, Gradio client,
|
| 221 |
+
# fonts) locally so the app needs NO external CDN/API at runtime.
|
| 222 |
+
STATIC_DIR = (Path(__file__).parent / "static").resolve()
|
| 223 |
+
mimetypes.add_type("text/javascript", ".js")
|
| 224 |
+
mimetypes.add_type("font/woff2", ".woff2")
|
| 225 |
+
|
| 226 |
+
@app.get("/static/{fname:path}")
|
| 227 |
+
def static_files(fname: str):
|
| 228 |
+
fp = (STATIC_DIR / fname).resolve()
|
| 229 |
+
# contain to STATIC_DIR (no path traversal) and require a real file
|
| 230 |
+
if not str(fp).startswith(str(STATIC_DIR) + "/") or not fp.is_file():
|
| 231 |
+
return PlainTextResponse("not found", status_code=404)
|
| 232 |
+
mt, _ = mimetypes.guess_type(str(fp))
|
| 233 |
+
return FileResponse(fp, media_type=mt or "application/octet-stream")
|
| 234 |
+
|
| 235 |
+
# Download every agent trace collected this run (one JSON object per line).
|
| 236 |
+
# curl https://<your-space>/traces > agent_traces.jsonl
|
| 237 |
+
@app.get("/traces")
|
| 238 |
+
def traces():
|
| 239 |
+
text = TRACE_PATH.read_text(encoding="utf-8") if TRACE_PATH.exists() else ""
|
| 240 |
+
return PlainTextResponse(text, media_type="application/x-ndjson",
|
| 241 |
+
headers={"Content-Disposition": 'attachment; filename="agent_traces.jsonl"'})
|
| 242 |
+
|
| 243 |
+
app.launch(share=False) # no external gradio.live tunnel — fully self-hosted
|
build/build.sh
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
# Rebuild the vendored frontend bundles in ../static/ from scratch.
|
| 3 |
+
# Requires Node. Run from this build/ directory: ./build.sh
|
| 4 |
+
set -euo pipefail
|
| 5 |
+
cd "$(dirname "$0")"
|
| 6 |
+
npm install --no-fund --no-audit \
|
| 7 |
+
@codemirror/state@6 @codemirror/view@6 @codemirror/commands@6 @codemirror/language@6 \
|
| 8 |
+
@codemirror/lang-python@6 @codemirror/lang-javascript@6 @codemirror/lang-java@6 @codemirror/lang-cpp@6 \
|
| 9 |
+
@lezer/highlight@1 @gradio/client@1 esbuild
|
| 10 |
+
EB=./node_modules/.bin/esbuild
|
| 11 |
+
"$EB" cm-entry.mjs --bundle --format=iife --global-name=CM6 --minify --outfile=../static/cm.bundle.js
|
| 12 |
+
"$EB" gradio-entry.mjs --bundle --format=iife --global-name=GradioClient --minify --platform=browser \
|
| 13 |
+
--external:fs/promises --external:path --external:fs --external:url --external:stream \
|
| 14 |
+
--external:crypto --external:http --external:https --external:os --external:child_process \
|
| 15 |
+
--outfile=../static/gradio-client.js
|
| 16 |
+
curl -sL "https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js" -o ../static/mermaid.min.js
|
| 17 |
+
echo "Rebuilt static/{cm.bundle.js, gradio-client.js, mermaid.min.js}. (Fonts are vendored separately.)"
|
build/cm-entry.mjs
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export { EditorState, Compartment, StateField, StateEffect } from "@codemirror/state";
|
| 2 |
+
export { EditorView, keymap, placeholder, lineNumbers, highlightActiveLine,
|
| 3 |
+
highlightActiveLineGutter, drawSelection, dropCursor, Decoration } from "@codemirror/view";
|
| 4 |
+
export { history, defaultKeymap, historyKeymap, indentWithTab } from "@codemirror/commands";
|
| 5 |
+
export { indentOnInput, bracketMatching, syntaxHighlighting, HighlightStyle } from "@codemirror/language";
|
| 6 |
+
export { tags } from "@lezer/highlight";
|
| 7 |
+
export { python } from "@codemirror/lang-python";
|
| 8 |
+
export { javascript } from "@codemirror/lang-javascript";
|
| 9 |
+
export { java } from "@codemirror/lang-java";
|
| 10 |
+
export { cpp } from "@codemirror/lang-cpp";
|
build/gradio-entry.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
export { Client } from "@gradio/client";
|
build/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"name":"cf-vendor-build","private":true,"type":"module","dependencies":{"@codemirror/commands":"^6.10.3","@codemirror/lang-cpp":"^6.0.3","@codemirror/lang-java":"^6.0.2","@codemirror/lang-javascript":"^6.2.5","@codemirror/lang-python":"^6.2.1","@codemirror/language":"^6.12.3","@codemirror/state":"^6.6.0","@codemirror/view":"^6.43.1","@gradio/client":"^1.19.1","@lezer/highlight":"^1.2.3","esbuild":"^0.28.0"}}
|
frontend.html
CHANGED
|
@@ -4,9 +4,8 @@
|
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
<title>CodeFlow — Code to Flowchart</title>
|
| 7 |
-
<
|
| 8 |
-
<link rel="
|
| 9 |
-
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,500;9..144,600;9..144,700&family=Hanken+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
| 10 |
<style>
|
| 11 |
/* ============================================================
|
| 12 |
PINE & SAGE — the CodeFlow theme (green + light).
|
|
@@ -500,13 +499,14 @@
|
|
| 500 |
textarea::-webkit-scrollbar-thumb:hover { background: var(--scroll-hi); }
|
| 501 |
#flowchart-target::-webkit-scrollbar-corner,
|
| 502 |
textarea::-webkit-scrollbar-corner { background: var(--bg-inset); }
|
| 503 |
-
/* Render the SVG
|
| 504 |
-
|
|
|
|
| 505 |
#flowchart-target svg {
|
| 506 |
-
width: calc(
|
| 507 |
max-width: none !important; /* override Mermaid's inline max-width so zoom can grow it */
|
| 508 |
height: auto !important;
|
| 509 |
-
min-height:
|
| 510 |
flex: 0 0 auto;
|
| 511 |
}
|
| 512 |
/* Empty state: the lone Start anchor renders small + centred — not stretched
|
|
@@ -711,10 +711,17 @@
|
|
| 711 |
</div>
|
| 712 |
</div>
|
| 713 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 714 |
<script type="module">
|
| 715 |
-
|
| 716 |
-
// CodeMirror is
|
| 717 |
-
//
|
| 718 |
// take down the rest of the page (examples, Generate). See initEditor().
|
| 719 |
|
| 720 |
// Per-palette, per-theme Mermaid palettes. Keyed [PALETTE][theme] so the
|
|
@@ -851,27 +858,18 @@ print(total)`,
|
|
| 851 |
a working textarea instead of a broken page. getCode()/setCode() below
|
| 852 |
hide which input is live, so the preset + submit logic never branches. */
|
| 853 |
|
| 854 |
-
//
|
| 855 |
-
//
|
| 856 |
-
//
|
| 857 |
-
//
|
| 858 |
-
// the @6 / @1 majors (not micro-versions) so esm.sh resolves one mutually
|
| 859 |
-
// compatible current set. (Verified in a headless Chrome harness.)
|
| 860 |
-
const D = {
|
| 861 |
-
state: "@codemirror/state@6",
|
| 862 |
-
view: "@codemirror/state@6,@codemirror/view@6",
|
| 863 |
-
lang: "@codemirror/state@6,@codemirror/view@6,@codemirror/language@6,@lezer/highlight@1",
|
| 864 |
-
};
|
| 865 |
-
|
| 866 |
-
// Lazy grammar loaders — only the picked language's parser is fetched.
|
| 867 |
const LANG_LOADERS = {
|
| 868 |
-
python: () =>
|
| 869 |
-
javascript: () =>
|
| 870 |
-
java: () =>
|
| 871 |
-
cpp: () =>
|
| 872 |
};
|
| 873 |
async function makeLangExt(name) {
|
| 874 |
-
try { return
|
| 875 |
}
|
| 876 |
|
| 877 |
let cmView = null;
|
|
@@ -911,24 +909,17 @@ print(total)`,
|
|
| 911 |
|
| 912 |
async function initEditor() {
|
| 913 |
try {
|
| 914 |
-
//
|
| 915 |
-
//
|
| 916 |
-
//
|
| 917 |
-
//
|
| 918 |
-
|
| 919 |
-
const
|
| 920 |
-
import("https://esm.sh/@codemirror/state@6"),
|
| 921 |
-
import("https://esm.sh/@codemirror/view@6?deps=" + D.state),
|
| 922 |
-
import("https://esm.sh/@codemirror/commands@6?deps=" + D.view),
|
| 923 |
-
import("https://esm.sh/@codemirror/language@6?deps=" + D.lang),
|
| 924 |
-
import("https://esm.sh/@lezer/highlight@1"),
|
| 925 |
-
]);
|
| 926 |
-
const { EditorState, Compartment, StateField, StateEffect } = stateMod;
|
| 927 |
const { EditorView, keymap, placeholder, lineNumbers, highlightActiveLine,
|
| 928 |
-
highlightActiveLineGutter, drawSelection, dropCursor, Decoration } =
|
| 929 |
-
const { history, defaultKeymap, historyKeymap, indentWithTab } =
|
| 930 |
-
const { indentOnInput, bracketMatching, syntaxHighlighting, HighlightStyle } =
|
| 931 |
-
const tg =
|
| 932 |
|
| 933 |
// Lean "basic setup" — line numbers, active line, history/undo,
|
| 934 |
// indent-on-input, bracket matching. (No autocomplete/search/lint;
|
|
@@ -1424,13 +1415,13 @@ print(total)`,
|
|
| 1424 |
}
|
| 1425 |
|
| 1426 |
/* ----- Live generation (server only) -----
|
| 1427 |
-
|
| 1428 |
-
|
| 1429 |
-
|
| 1430 |
let clientPromise = null;
|
| 1431 |
async function getClient() {
|
| 1432 |
if (!clientPromise) {
|
| 1433 |
-
const { Client } =
|
| 1434 |
clientPromise = Client.connect(window.location.origin);
|
| 1435 |
}
|
| 1436 |
return clientPromise;
|
|
|
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
<title>CodeFlow — Code to Flowchart</title>
|
| 7 |
+
<!-- All assets are vendored locally (see static/) — no external CDN/API at runtime. -->
|
| 8 |
+
<link rel="stylesheet" href="static/fonts.css">
|
|
|
|
| 9 |
<style>
|
| 10 |
/* ============================================================
|
| 11 |
PINE & SAGE — the CodeFlow theme (green + light).
|
|
|
|
| 499 |
textarea::-webkit-scrollbar-thumb:hover { background: var(--scroll-hi); }
|
| 500 |
#flowchart-target::-webkit-scrollbar-corner,
|
| 501 |
textarea::-webkit-scrollbar-corner { background: var(--bg-inset); }
|
| 502 |
+
/* Render the SVG a bit under full panel width (centred) so it reads at a
|
| 503 |
+
comfortable size; long charts still grow + scroll instead of shrinking.
|
| 504 |
+
--fit is the default "fit" scale; the zoom control multiplies it. */
|
| 505 |
#flowchart-target svg {
|
| 506 |
+
width: calc(72% * var(--zoom, 1)) !important; /* fit-to-width, slightly inset; zoom scales it */
|
| 507 |
max-width: none !important; /* override Mermaid's inline max-width so zoom can grow it */
|
| 508 |
height: auto !important;
|
| 509 |
+
min-height: 320px;
|
| 510 |
flex: 0 0 auto;
|
| 511 |
}
|
| 512 |
/* Empty state: the lone Start anchor renders small + centred — not stretched
|
|
|
|
| 711 |
</div>
|
| 712 |
</div>
|
| 713 |
|
| 714 |
+
<!-- Vendored libraries (classic scripts → globals): Mermaid (window.mermaid),
|
| 715 |
+
CodeMirror bundle (window.CM6), Gradio client (window.GradioClient).
|
| 716 |
+
Loaded before the module below so the module can use the globals. -->
|
| 717 |
+
<script src="static/mermaid.min.js"></script>
|
| 718 |
+
<script src="static/cm.bundle.js"></script>
|
| 719 |
+
<script src="static/gradio-client.js"></script>
|
| 720 |
+
|
| 721 |
<script type="module">
|
| 722 |
+
// `mermaid` is the global from static/mermaid.min.js (vendored, no CDN).
|
| 723 |
+
// CodeMirror is read from the window.CM6 global inside initEditor() — kept in
|
| 724 |
+
// a try/catch so any editor failure is contained and falls back to a textarea.
|
| 725 |
// take down the rest of the page (examples, Generate). See initEditor().
|
| 726 |
|
| 727 |
// Per-palette, per-theme Mermaid palettes. Keyed [PALETTE][theme] so the
|
|
|
|
| 858 |
a working textarea instead of a broken page. getCode()/setCode() below
|
| 859 |
hide which input is live, so the preset + submit logic never branches. */
|
| 860 |
|
| 861 |
+
// CodeMirror is vendored as a single IIFE bundle (static/cm.bundle.js → the
|
| 862 |
+
// CM6 global), so every package shares ONE @codemirror/state/view/@lezer
|
| 863 |
+
// instance by construction — no ?deps= juggling, no CDN. Grammars come from
|
| 864 |
+
// the same bundle (CM6.python / .javascript / .java / .cpp).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 865 |
const LANG_LOADERS = {
|
| 866 |
+
python: () => CM6.python(),
|
| 867 |
+
javascript: () => CM6.javascript(),
|
| 868 |
+
java: () => CM6.java(),
|
| 869 |
+
cpp: () => CM6.cpp(),
|
| 870 |
};
|
| 871 |
async function makeLangExt(name) {
|
| 872 |
+
try { return (LANG_LOADERS[name] || LANG_LOADERS.python)(); } catch { return []; }
|
| 873 |
}
|
| 874 |
|
| 875 |
let cmView = null;
|
|
|
|
| 909 |
|
| 910 |
async function initEditor() {
|
| 911 |
try {
|
| 912 |
+
// Everything comes from the vendored CM6 global (static/cm.bundle.js).
|
| 913 |
+
// Wrapped in try/catch so any editor failure is contained to the
|
| 914 |
+
// editor and falls back to the plain textarea — the rest of the page
|
| 915 |
+
// (mermaid, examples, Generate) keeps working.
|
| 916 |
+
if (!window.CM6) throw new Error('CodeMirror bundle not loaded');
|
| 917 |
+
const { EditorState, Compartment, StateField, StateEffect } = CM6;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 918 |
const { EditorView, keymap, placeholder, lineNumbers, highlightActiveLine,
|
| 919 |
+
highlightActiveLineGutter, drawSelection, dropCursor, Decoration } = CM6;
|
| 920 |
+
const { history, defaultKeymap, historyKeymap, indentWithTab } = CM6;
|
| 921 |
+
const { indentOnInput, bracketMatching, syntaxHighlighting, HighlightStyle } = CM6;
|
| 922 |
+
const tg = CM6.tags;
|
| 923 |
|
| 924 |
// Lean "basic setup" — line numbers, active line, history/undo,
|
| 925 |
// indent-on-input, bracket matching. (No autocomplete/search/lint;
|
|
|
|
| 1415 |
}
|
| 1416 |
|
| 1417 |
/* ----- Live generation (server only) -----
|
| 1418 |
+
Uses the vendored Gradio client (static/gradio-client.js → the
|
| 1419 |
+
GradioClient global). Connected lazily on first Generate; presets still
|
| 1420 |
+
render with no backend. */
|
| 1421 |
let clientPromise = null;
|
| 1422 |
async function getClient() {
|
| 1423 |
if (!clientPromise) {
|
| 1424 |
+
const { Client } = window.GradioClient;
|
| 1425 |
clientPromise = Client.connect(window.location.origin);
|
| 1426 |
}
|
| 1427 |
return clientPromise;
|
static/cm.bundle.js
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
static/fonts.css
ADDED
|
@@ -0,0 +1,333 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* vietnamese */
|
| 2 |
+
@font-face {
|
| 3 |
+
font-family: 'Fraunces';
|
| 4 |
+
font-style: normal;
|
| 5 |
+
font-weight: 500;
|
| 6 |
+
font-display: swap;
|
| 7 |
+
src: url(fonts/6NU78FyLNQOQZAnv9bYEvDiIdE9Ea92uemAk_WBq8U_9v0c2Wa0KxCBTeP2Xz5fU8w.woff2) format('woff2');
|
| 8 |
+
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
| 9 |
+
}
|
| 10 |
+
/* latin-ext */
|
| 11 |
+
@font-face {
|
| 12 |
+
font-family: 'Fraunces';
|
| 13 |
+
font-style: normal;
|
| 14 |
+
font-weight: 500;
|
| 15 |
+
font-display: swap;
|
| 16 |
+
src: url(fonts/6NU78FyLNQOQZAnv9bYEvDiIdE9Ea92uemAk_WBq8U_9v0c2Wa0KxCFTeP2Xz5fU8w.woff2) format('woff2');
|
| 17 |
+
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
| 18 |
+
}
|
| 19 |
+
/* latin */
|
| 20 |
+
@font-face {
|
| 21 |
+
font-family: 'Fraunces';
|
| 22 |
+
font-style: normal;
|
| 23 |
+
font-weight: 500;
|
| 24 |
+
font-display: swap;
|
| 25 |
+
src: url(fonts/6NU78FyLNQOQZAnv9bYEvDiIdE9Ea92uemAk_WBq8U_9v0c2Wa0KxC9TeP2Xz5c.woff2) format('woff2');
|
| 26 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
| 27 |
+
}
|
| 28 |
+
/* vietnamese */
|
| 29 |
+
@font-face {
|
| 30 |
+
font-family: 'Fraunces';
|
| 31 |
+
font-style: normal;
|
| 32 |
+
font-weight: 600;
|
| 33 |
+
font-display: swap;
|
| 34 |
+
src: url(fonts/6NU78FyLNQOQZAnv9bYEvDiIdE9Ea92uemAk_WBq8U_9v0c2Wa0KxCBTeP2Xz5fU8w.woff2) format('woff2');
|
| 35 |
+
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
| 36 |
+
}
|
| 37 |
+
/* latin-ext */
|
| 38 |
+
@font-face {
|
| 39 |
+
font-family: 'Fraunces';
|
| 40 |
+
font-style: normal;
|
| 41 |
+
font-weight: 600;
|
| 42 |
+
font-display: swap;
|
| 43 |
+
src: url(fonts/6NU78FyLNQOQZAnv9bYEvDiIdE9Ea92uemAk_WBq8U_9v0c2Wa0KxCFTeP2Xz5fU8w.woff2) format('woff2');
|
| 44 |
+
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
| 45 |
+
}
|
| 46 |
+
/* latin */
|
| 47 |
+
@font-face {
|
| 48 |
+
font-family: 'Fraunces';
|
| 49 |
+
font-style: normal;
|
| 50 |
+
font-weight: 600;
|
| 51 |
+
font-display: swap;
|
| 52 |
+
src: url(fonts/6NU78FyLNQOQZAnv9bYEvDiIdE9Ea92uemAk_WBq8U_9v0c2Wa0KxC9TeP2Xz5c.woff2) format('woff2');
|
| 53 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
| 54 |
+
}
|
| 55 |
+
/* vietnamese */
|
| 56 |
+
@font-face {
|
| 57 |
+
font-family: 'Fraunces';
|
| 58 |
+
font-style: normal;
|
| 59 |
+
font-weight: 700;
|
| 60 |
+
font-display: swap;
|
| 61 |
+
src: url(fonts/6NU78FyLNQOQZAnv9bYEvDiIdE9Ea92uemAk_WBq8U_9v0c2Wa0KxCBTeP2Xz5fU8w.woff2) format('woff2');
|
| 62 |
+
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
| 63 |
+
}
|
| 64 |
+
/* latin-ext */
|
| 65 |
+
@font-face {
|
| 66 |
+
font-family: 'Fraunces';
|
| 67 |
+
font-style: normal;
|
| 68 |
+
font-weight: 700;
|
| 69 |
+
font-display: swap;
|
| 70 |
+
src: url(fonts/6NU78FyLNQOQZAnv9bYEvDiIdE9Ea92uemAk_WBq8U_9v0c2Wa0KxCFTeP2Xz5fU8w.woff2) format('woff2');
|
| 71 |
+
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
| 72 |
+
}
|
| 73 |
+
/* latin */
|
| 74 |
+
@font-face {
|
| 75 |
+
font-family: 'Fraunces';
|
| 76 |
+
font-style: normal;
|
| 77 |
+
font-weight: 700;
|
| 78 |
+
font-display: swap;
|
| 79 |
+
src: url(fonts/6NU78FyLNQOQZAnv9bYEvDiIdE9Ea92uemAk_WBq8U_9v0c2Wa0KxC9TeP2Xz5c.woff2) format('woff2');
|
| 80 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
| 81 |
+
}
|
| 82 |
+
/* cyrillic-ext */
|
| 83 |
+
@font-face {
|
| 84 |
+
font-family: 'Hanken Grotesk';
|
| 85 |
+
font-style: normal;
|
| 86 |
+
font-weight: 400;
|
| 87 |
+
font-display: swap;
|
| 88 |
+
src: url(fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpQ59CxCis4UvI.woff2) format('woff2');
|
| 89 |
+
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
| 90 |
+
}
|
| 91 |
+
/* vietnamese */
|
| 92 |
+
@font-face {
|
| 93 |
+
font-family: 'Hanken Grotesk';
|
| 94 |
+
font-style: normal;
|
| 95 |
+
font-weight: 400;
|
| 96 |
+
font-display: swap;
|
| 97 |
+
src: url(fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpS59CxCis4UvI.woff2) format('woff2');
|
| 98 |
+
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
| 99 |
+
}
|
| 100 |
+
/* latin-ext */
|
| 101 |
+
@font-face {
|
| 102 |
+
font-family: 'Hanken Grotesk';
|
| 103 |
+
font-style: normal;
|
| 104 |
+
font-weight: 400;
|
| 105 |
+
font-display: swap;
|
| 106 |
+
src: url(fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpT59CxCis4UvI.woff2) format('woff2');
|
| 107 |
+
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
| 108 |
+
}
|
| 109 |
+
/* latin */
|
| 110 |
+
@font-face {
|
| 111 |
+
font-family: 'Hanken Grotesk';
|
| 112 |
+
font-style: normal;
|
| 113 |
+
font-weight: 400;
|
| 114 |
+
font-display: swap;
|
| 115 |
+
src: url(fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpd59CxCis4.woff2) format('woff2');
|
| 116 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
| 117 |
+
}
|
| 118 |
+
/* cyrillic-ext */
|
| 119 |
+
@font-face {
|
| 120 |
+
font-family: 'Hanken Grotesk';
|
| 121 |
+
font-style: normal;
|
| 122 |
+
font-weight: 500;
|
| 123 |
+
font-display: swap;
|
| 124 |
+
src: url(fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpQ59CxCis4UvI.woff2) format('woff2');
|
| 125 |
+
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
| 126 |
+
}
|
| 127 |
+
/* vietnamese */
|
| 128 |
+
@font-face {
|
| 129 |
+
font-family: 'Hanken Grotesk';
|
| 130 |
+
font-style: normal;
|
| 131 |
+
font-weight: 500;
|
| 132 |
+
font-display: swap;
|
| 133 |
+
src: url(fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpS59CxCis4UvI.woff2) format('woff2');
|
| 134 |
+
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
| 135 |
+
}
|
| 136 |
+
/* latin-ext */
|
| 137 |
+
@font-face {
|
| 138 |
+
font-family: 'Hanken Grotesk';
|
| 139 |
+
font-style: normal;
|
| 140 |
+
font-weight: 500;
|
| 141 |
+
font-display: swap;
|
| 142 |
+
src: url(fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpT59CxCis4UvI.woff2) format('woff2');
|
| 143 |
+
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
| 144 |
+
}
|
| 145 |
+
/* latin */
|
| 146 |
+
@font-face {
|
| 147 |
+
font-family: 'Hanken Grotesk';
|
| 148 |
+
font-style: normal;
|
| 149 |
+
font-weight: 500;
|
| 150 |
+
font-display: swap;
|
| 151 |
+
src: url(fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpd59CxCis4.woff2) format('woff2');
|
| 152 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
| 153 |
+
}
|
| 154 |
+
/* cyrillic-ext */
|
| 155 |
+
@font-face {
|
| 156 |
+
font-family: 'Hanken Grotesk';
|
| 157 |
+
font-style: normal;
|
| 158 |
+
font-weight: 600;
|
| 159 |
+
font-display: swap;
|
| 160 |
+
src: url(fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpQ59CxCis4UvI.woff2) format('woff2');
|
| 161 |
+
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
| 162 |
+
}
|
| 163 |
+
/* vietnamese */
|
| 164 |
+
@font-face {
|
| 165 |
+
font-family: 'Hanken Grotesk';
|
| 166 |
+
font-style: normal;
|
| 167 |
+
font-weight: 600;
|
| 168 |
+
font-display: swap;
|
| 169 |
+
src: url(fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpS59CxCis4UvI.woff2) format('woff2');
|
| 170 |
+
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
| 171 |
+
}
|
| 172 |
+
/* latin-ext */
|
| 173 |
+
@font-face {
|
| 174 |
+
font-family: 'Hanken Grotesk';
|
| 175 |
+
font-style: normal;
|
| 176 |
+
font-weight: 600;
|
| 177 |
+
font-display: swap;
|
| 178 |
+
src: url(fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpT59CxCis4UvI.woff2) format('woff2');
|
| 179 |
+
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
| 180 |
+
}
|
| 181 |
+
/* latin */
|
| 182 |
+
@font-face {
|
| 183 |
+
font-family: 'Hanken Grotesk';
|
| 184 |
+
font-style: normal;
|
| 185 |
+
font-weight: 600;
|
| 186 |
+
font-display: swap;
|
| 187 |
+
src: url(fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpd59CxCis4.woff2) format('woff2');
|
| 188 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
| 189 |
+
}
|
| 190 |
+
/* cyrillic-ext */
|
| 191 |
+
@font-face {
|
| 192 |
+
font-family: 'Hanken Grotesk';
|
| 193 |
+
font-style: normal;
|
| 194 |
+
font-weight: 700;
|
| 195 |
+
font-display: swap;
|
| 196 |
+
src: url(fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpQ59CxCis4UvI.woff2) format('woff2');
|
| 197 |
+
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
| 198 |
+
}
|
| 199 |
+
/* vietnamese */
|
| 200 |
+
@font-face {
|
| 201 |
+
font-family: 'Hanken Grotesk';
|
| 202 |
+
font-style: normal;
|
| 203 |
+
font-weight: 700;
|
| 204 |
+
font-display: swap;
|
| 205 |
+
src: url(fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpS59CxCis4UvI.woff2) format('woff2');
|
| 206 |
+
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
| 207 |
+
}
|
| 208 |
+
/* latin-ext */
|
| 209 |
+
@font-face {
|
| 210 |
+
font-family: 'Hanken Grotesk';
|
| 211 |
+
font-style: normal;
|
| 212 |
+
font-weight: 700;
|
| 213 |
+
font-display: swap;
|
| 214 |
+
src: url(fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpT59CxCis4UvI.woff2) format('woff2');
|
| 215 |
+
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
| 216 |
+
}
|
| 217 |
+
/* latin */
|
| 218 |
+
@font-face {
|
| 219 |
+
font-family: 'Hanken Grotesk';
|
| 220 |
+
font-style: normal;
|
| 221 |
+
font-weight: 700;
|
| 222 |
+
font-display: swap;
|
| 223 |
+
src: url(fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpd59CxCis4.woff2) format('woff2');
|
| 224 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
| 225 |
+
}
|
| 226 |
+
/* cyrillic-ext */
|
| 227 |
+
@font-face {
|
| 228 |
+
font-family: 'JetBrains Mono';
|
| 229 |
+
font-style: normal;
|
| 230 |
+
font-weight: 400;
|
| 231 |
+
font-display: swap;
|
| 232 |
+
src: url(fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx3cwgknk-6nFg.woff2) format('woff2');
|
| 233 |
+
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
| 234 |
+
}
|
| 235 |
+
/* cyrillic */
|
| 236 |
+
@font-face {
|
| 237 |
+
font-family: 'JetBrains Mono';
|
| 238 |
+
font-style: normal;
|
| 239 |
+
font-weight: 400;
|
| 240 |
+
font-display: swap;
|
| 241 |
+
src: url(fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxTcwgknk-6nFg.woff2) format('woff2');
|
| 242 |
+
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
| 243 |
+
}
|
| 244 |
+
/* greek */
|
| 245 |
+
@font-face {
|
| 246 |
+
font-family: 'JetBrains Mono';
|
| 247 |
+
font-style: normal;
|
| 248 |
+
font-weight: 400;
|
| 249 |
+
font-display: swap;
|
| 250 |
+
src: url(fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxPcwgknk-6nFg.woff2) format('woff2');
|
| 251 |
+
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
|
| 252 |
+
}
|
| 253 |
+
/* vietnamese */
|
| 254 |
+
@font-face {
|
| 255 |
+
font-family: 'JetBrains Mono';
|
| 256 |
+
font-style: normal;
|
| 257 |
+
font-weight: 400;
|
| 258 |
+
font-display: swap;
|
| 259 |
+
src: url(fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx_cwgknk-6nFg.woff2) format('woff2');
|
| 260 |
+
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
| 261 |
+
}
|
| 262 |
+
/* latin-ext */
|
| 263 |
+
@font-face {
|
| 264 |
+
font-family: 'JetBrains Mono';
|
| 265 |
+
font-style: normal;
|
| 266 |
+
font-weight: 400;
|
| 267 |
+
font-display: swap;
|
| 268 |
+
src: url(fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx7cwgknk-6nFg.woff2) format('woff2');
|
| 269 |
+
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
| 270 |
+
}
|
| 271 |
+
/* latin */
|
| 272 |
+
@font-face {
|
| 273 |
+
font-family: 'JetBrains Mono';
|
| 274 |
+
font-style: normal;
|
| 275 |
+
font-weight: 400;
|
| 276 |
+
font-display: swap;
|
| 277 |
+
src: url(fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxDcwgknk-4.woff2) format('woff2');
|
| 278 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
| 279 |
+
}
|
| 280 |
+
/* cyrillic-ext */
|
| 281 |
+
@font-face {
|
| 282 |
+
font-family: 'JetBrains Mono';
|
| 283 |
+
font-style: normal;
|
| 284 |
+
font-weight: 500;
|
| 285 |
+
font-display: swap;
|
| 286 |
+
src: url(fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx3cwgknk-6nFg.woff2) format('woff2');
|
| 287 |
+
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
| 288 |
+
}
|
| 289 |
+
/* cyrillic */
|
| 290 |
+
@font-face {
|
| 291 |
+
font-family: 'JetBrains Mono';
|
| 292 |
+
font-style: normal;
|
| 293 |
+
font-weight: 500;
|
| 294 |
+
font-display: swap;
|
| 295 |
+
src: url(fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxTcwgknk-6nFg.woff2) format('woff2');
|
| 296 |
+
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
| 297 |
+
}
|
| 298 |
+
/* greek */
|
| 299 |
+
@font-face {
|
| 300 |
+
font-family: 'JetBrains Mono';
|
| 301 |
+
font-style: normal;
|
| 302 |
+
font-weight: 500;
|
| 303 |
+
font-display: swap;
|
| 304 |
+
src: url(fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxPcwgknk-6nFg.woff2) format('woff2');
|
| 305 |
+
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
|
| 306 |
+
}
|
| 307 |
+
/* vietnamese */
|
| 308 |
+
@font-face {
|
| 309 |
+
font-family: 'JetBrains Mono';
|
| 310 |
+
font-style: normal;
|
| 311 |
+
font-weight: 500;
|
| 312 |
+
font-display: swap;
|
| 313 |
+
src: url(fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx_cwgknk-6nFg.woff2) format('woff2');
|
| 314 |
+
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
| 315 |
+
}
|
| 316 |
+
/* latin-ext */
|
| 317 |
+
@font-face {
|
| 318 |
+
font-family: 'JetBrains Mono';
|
| 319 |
+
font-style: normal;
|
| 320 |
+
font-weight: 500;
|
| 321 |
+
font-display: swap;
|
| 322 |
+
src: url(fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx7cwgknk-6nFg.woff2) format('woff2');
|
| 323 |
+
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
| 324 |
+
}
|
| 325 |
+
/* latin */
|
| 326 |
+
@font-face {
|
| 327 |
+
font-family: 'JetBrains Mono';
|
| 328 |
+
font-style: normal;
|
| 329 |
+
font-weight: 500;
|
| 330 |
+
font-display: swap;
|
| 331 |
+
src: url(fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxDcwgknk-4.woff2) format('woff2');
|
| 332 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
| 333 |
+
}
|
static/fonts/6NU78FyLNQOQZAnv9bYEvDiIdE9Ea92uemAk_WBq8U_9v0c2Wa0KxC9TeP2Xz5c.woff2
ADDED
|
Binary file (67.4 kB). View file
|
|
|
static/fonts/6NU78FyLNQOQZAnv9bYEvDiIdE9Ea92uemAk_WBq8U_9v0c2Wa0KxCBTeP2Xz5fU8w.woff2
ADDED
|
Binary file (19.7 kB). View file
|
|
|
static/fonts/6NU78FyLNQOQZAnv9bYEvDiIdE9Ea92uemAk_WBq8U_9v0c2Wa0KxCFTeP2Xz5fU8w.woff2
ADDED
|
Binary file (59.5 kB). View file
|
|
|
static/fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpQ59CxCis4UvI.woff2
ADDED
|
Binary file (1.64 kB). View file
|
|
|
static/fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpS59CxCis4UvI.woff2
ADDED
|
Binary file (9.36 kB). View file
|
|
|
static/fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpT59CxCis4UvI.woff2
ADDED
|
Binary file (19.6 kB). View file
|
|
|
static/fonts/ieVn2YZDLWuGJpnzaiwFXS9tYtpd59CxCis4.woff2
ADDED
|
Binary file (34.7 kB). View file
|
|
|
static/fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx3cwgknk-6nFg.woff2
ADDED
|
Binary file (1.66 kB). View file
|
|
|
static/fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx7cwgknk-6nFg.woff2
ADDED
|
Binary file (11.6 kB). View file
|
|
|
static/fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxDcwgknk-4.woff2
ADDED
|
Binary file (31.3 kB). View file
|
|
|
static/fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxPcwgknk-6nFg.woff2
ADDED
|
Binary file (6.8 kB). View file
|
|
|
static/fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxTcwgknk-6nFg.woff2
ADDED
|
Binary file (8.89 kB). View file
|
|
|
static/fonts/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx_cwgknk-6nFg.woff2
ADDED
|
Binary file (5.87 kB). View file
|
|
|
static/gradio-client.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
var GradioClient=(()=>{var ce=Object.defineProperty;var et=Object.getOwnPropertyDescriptor;var tt=Object.getOwnPropertyNames;var nt=Object.prototype.hasOwnProperty;var st=(e,t)=>()=>(e&&(t=e(e=0)),t);var Se=(e,t)=>{for(var n in t)ce(e,n,{get:t[n],enumerable:!0})},it=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of tt(t))!nt.call(e,i)&&i!==n&&ce(e,i,{get:()=>t[i],enumerable:!(s=et(t,i))||s.enumerable});return e};var ot=e=>it(ce({},"__esModule",{value:!0}),e);var le={};Se(le,{default:()=>at});var at,ue=st(()=>{at={}});var hn={};Se(hn,{Client:()=>G});var rt=Object.defineProperty,Ne=e=>{throw TypeError(e)},ct=(e,t,n)=>t in e?rt(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,u=(e,t,n)=>ct(e,typeof t!="symbol"?t+"":t,n),Pe=(e,t,n)=>t.has(e)||Ne("Cannot "+n),Z=(e,t,n)=>(Pe(e,t,"read from private field"),n?n.call(e):t.get(e)),lt=(e,t,n)=>t.has(e)?Ne("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,n),ut=(e,t,n,s)=>(Pe(e,t,"write to private field"),s?s.call(e,n):t.set(e,n),n),pe=new Intl.Collator(0,{numeric:1}).compare;function ze(e,t,n){return e=e.split("."),t=t.split("."),pe(e[0],t[0])||pe(e[1],t[1])||(t[2]=t.slice(2).join("."),n=/[.-]/.test(e[2]=e.slice(2).join(".")),n==/[.-]/.test(t[2])?pe(e[2],t[2]):n?-1:1)}var pt="host",Ae="queue/data",dt="queue/join",xe="upload",ht="login",X="config",ft="info",_t="runtime",gt="sleeptime",mt="heartbeat",wt="component_server",yt="reset",vt="cancel",bt="app_id",$t="https://gradio-space-api-fetcher-v2.hf.space/api",Be="This application is currently busy. Please try again. ",W="Connection errored out. ",L="Could not resolve app config. ",kt="Could not get space status. ",Et="Could not get API info. ",we="Space metadata could not be loaded. ",St="Invalid URL. A full URL path is required.",xt="Not authorized to access this space. ",Le="Invalid credentials. Could not login. ",jt="Login credentials are required to access this space.",Ct="File system access is only available in Node.js environments",Ue="Root URL not found in client config",qt="Error uploading file";function Dt(e,t,n){return t.startsWith("http://")||t.startsWith("https://")?n?e:t:e+t}async function je(e,t,n){try{return(await(await fetch(`https://huggingface.co/api/spaces/${e}/jwt`,{headers:{Authorization:`Bearer ${t}`,...n?{Cookie:n}:{}}})).json()).token||!1}catch{return!1}}function Ot(e){let t={};return e.forEach(({api_name:n,id:s})=>{n&&(t[n]=s)}),t}async function Tt(e){let t=this.options.hf_token?{Authorization:`Bearer ${this.options.hf_token}`}:{};if(t["Content-Type"]="application/json",typeof window<"u"&&window.gradio_config&&location.origin!=="http://localhost:9876"){if(window.gradio_config.current_page&&(e=e.substring(0,e.lastIndexOf("/"))),window.gradio_config.dev_mode){let n=fe(e,this.deep_link?X+"?deep_link="+this.deep_link:X),s=await this.fetch(n,{headers:t,credentials:"include"}),i=await Ce(s,e,!!this.options.auth);window.gradio_config={...i,current_page:window.gradio_config.current_page}}return window.gradio_config.root=e,{...window.gradio_config}}else if(e){let n=fe(e,this.deep_link?X+"?deep_link="+this.deep_link:X),s=await this.fetch(n,{headers:t,credentials:"include"});return Ce(s,e,!!this.options.auth)}throw new Error(L)}async function Ce(e,t,n){var s,i;if(e?.status===401&&!n){let a=await e.json(),o=(s=a?.detail)==null?void 0:s.auth_message;throw new Error(o||jt)}else if(e?.status===401&&n)throw new Error(Le);if(e?.status===200){let a=await e.json();return a.root=t,(i=a.dependencies)==null||i.forEach((o,r)=>{o.id===void 0&&(o.id=r)}),a}else if(e?.status===401)throw new Error(xt);throw new Error(L)}async function Nt(){let{http_protocol:e,host:t}=await V(this.app_reference,this.options.hf_token);try{if(this.options.auth){let n=await Ie(e,t,this.options.auth,this.fetch,this.options.hf_token);n&&this.set_cookies(n)}}catch(n){throw Error(n.message)}}async function Ie(e,t,n,s,i){let a=new FormData;a.append("username",n?.[0]),a.append("password",n?.[1]);let o={};i&&(o.Authorization=`Bearer ${i}`);let r=await s(`${e}//${t}/${ht}`,{headers:o,method:"POST",body:a,credentials:"include"});if(r.status===200)return r.headers.get("set-cookie");throw r.status===401?new Error(Le):new Error(we)}function de(e){if(e.startsWith("http")){let{protocol:t,host:n,pathname:s}=new URL(e);return{ws_protocol:t==="https:"?"wss":"ws",http_protocol:t,host:n+(s!=="/"?s:"")}}return{ws_protocol:"wss",http_protocol:"https:",host:new URL(e).host}}var Re=e=>{let t=[];return e.split(/,(?=\s*[^\s=;]+=[^\s=;]+)/).forEach(n=>{let[s,i]=n.split(";")[0].split("=");s&&i&&t.push(`${s.trim()}=${i.trim()}`)}),t},ye=/^[a-zA-Z0-9_\-\.]+\/[a-zA-Z0-9_\-\.]+$/,Pt=/.*hf\.space\/{0,1}.*$/;async function V(e,t){let n={};t&&(n.Authorization=`Bearer ${t}`);let s=e.trim().replace(/\/$/,"");if(ye.test(s))try{let i=(await(await fetch(`https://huggingface.co/api/spaces/${s}/${pt}`,{headers:n})).json()).host;return{space_id:e,...de(i)}}catch{throw new Error(we)}if(Pt.test(s)){let{ws_protocol:i,http_protocol:a,host:o}=de(s);return{space_id:o.split("/")[0].replace(".hf.space",""),ws_protocol:i,http_protocol:a,host:o}}return{space_id:!1,...de(s)}}var fe=(...e)=>{try{return e.reduce((t,n)=>(t=t.replace(/\/+$/,""),n=n.replace(/^\/+/,""),new URL(n,t+"/").toString()))}catch{throw new Error(St)}};function zt(e,t,n){let s={named_endpoints:{},unnamed_endpoints:{}};return Object.keys(e).forEach(i=>{(i==="named_endpoints"||i==="unnamed_endpoints")&&(s[i]={},Object.entries(e[i]).forEach(([a,{parameters:o,returns:r}])=>{var l,_,m,p;let g=((l=t.dependencies.find(c=>c.api_name===a||c.api_name===a.replace("/","")))==null?void 0:l.id)||n[a.replace("/","")]||-1,C=g!==-1?(_=t.dependencies.find(c=>c.id==g))==null?void 0:_.types:{generator:!1,cancel:!1};if(g!==-1&&((p=(m=t.dependencies.find(c=>c.id==g))==null?void 0:m.inputs)==null?void 0:p.length)!==o.length){let c=t.dependencies.find(f=>f.id==g).inputs.map(f=>{var D;return(D=t.components.find(P=>P.id===f))==null?void 0:D.type});try{c.forEach((f,D)=>{if(f==="state"){let P={component:"state",example:null,parameter_default:null,parameter_has_default:!0,parameter_name:null,hidden:!0};o.splice(D,0,P)}})}catch(f){console.error(f)}}let U=(c,f,D,P)=>({...c,description:Bt(c?.type,D),type:At(c?.type,f,D,P)||""});s[i][a]={parameters:o.map(c=>U(c,c?.component,c?.serializer,"parameter")),returns:r.map(c=>U(c,c?.component,c?.serializer,"return")),type:C}}))}),s}function At(e,t,n,s){if(t==="Api")return e.type;switch(e?.type){case"string":return"string";case"boolean":return"boolean";case"number":return"number"}if(n==="JSONSerializable"||n==="StringSerializable")return"any";if(n==="ListStringSerializable")return"string[]";if(t==="Image")return s==="parameter"?"Blob | File | Buffer":"string";if(n==="FileSerializable")return e?.type==="array"?s==="parameter"?"(Blob | File | Buffer)[]":"{ name: string; data: string; size?: number; is_file?: boolean; orig_name?: string}[]":s==="parameter"?"Blob | File | Buffer":"{ name: string; data: string; size?: number; is_file?: boolean; orig_name?: string}";if(n==="GallerySerializable")return s==="parameter"?"[(Blob | File | Buffer), (string | null)][]":"[{ name: string; data: string; size?: number; is_file?: boolean; orig_name?: string}, (string | null))][]"}function Bt(e,t){return t==="GallerySerializable"?"array of [file, label] tuples":t==="ListStringSerializable"?"array of strings":t==="FileSerializable"?"array of files or single file":e?.description}function he(e,t){switch(e.msg){case"send_data":return{type:"data"};case"send_hash":return{type:"hash"};case"queue_full":return{type:"update",status:{queue:!0,message:Be,stage:"error",code:e.code,success:e.success}};case"heartbeat":return{type:"heartbeat"};case"unexpected_error":return{type:"unexpected_error",status:{queue:!0,message:e.message,session_not_found:e.session_not_found,stage:"error",success:!1}};case"broken_connection":return{type:"broken_connection",status:{queue:!0,message:e.message,stage:"error",success:!1}};case"estimation":return{type:"update",status:{queue:!0,stage:t||"pending",code:e.code,size:e.queue_size,position:e.rank,eta:e.rank_eta,success:e.success}};case"progress":return{type:"update",status:{queue:!0,stage:"pending",code:e.code,progress_data:e.progress_data,success:e.success}};case"log":return{type:"log",data:e};case"process_generating":return{type:"generating",status:{queue:!0,message:e.success?null:e.output.error,stage:e.success?"generating":"error",code:e.code,progress_data:e.progress_data,eta:e.average_duration,changed_state_ids:e.success?e.output.changed_state_ids:void 0},data:e.success?e.output:null};case"process_streaming":return{type:"streaming",status:{queue:!0,message:e.output.error,stage:"streaming",time_limit:e.time_limit,code:e.code,progress_data:e.progress_data,eta:e.eta},data:e.output};case"process_completed":return"error"in e.output?{type:"update",status:{queue:!0,title:e.output.title,message:e.output.error,visible:e.output.visible,duration:e.output.duration,stage:"error",code:e.code,success:e.success}}:{type:"complete",status:{queue:!0,message:e.success?void 0:e.output.error,stage:e.success?"complete":"error",code:e.code,progress_data:e.progress_data,changed_state_ids:e.success?e.output.changed_state_ids:void 0},data:e.success?e.output:null};case"process_starts":return{type:"update",status:{queue:!0,stage:"pending",code:e.code,size:e.rank,position:0,success:e.success,eta:e.eta},original_msg:"process_starts"}}return{type:"none",status:{stage:"error",queue:!0}}}var Lt=(e=[],t)=>{let n=t?t.parameters:[];if(Array.isArray(e))return t&&n.length>0&&e.length>n.length&&console.warn("Too many arguments provided for the endpoint."),e;let s=[],i=Object.keys(e);return n.forEach((a,o)=>{if(e.hasOwnProperty(a.parameter_name))s[o]=e[a.parameter_name];else if(a.parameter_has_default)s[o]=a.parameter_default;else throw new Error(`No value provided for required parameter: ${a.parameter_name}`)}),i.forEach(a=>{if(!n.some(o=>o.parameter_name===a))throw new Error(`Parameter \`${a}\` is not a valid keyword argument. Please refer to the API for usage.`)}),s.forEach((a,o)=>{if(a===void 0&&!n[o].parameter_has_default)throw new Error(`No value provided for required parameter: ${n[o].parameter_name}`)}),s};async function Ut(){if(this.api_info)return this.api_info;let{hf_token:e}=this.options,{config:t}=this,n={"Content-Type":"application/json"};if(e&&(n.Authorization=`Bearer ${e}`),!!t)try{let s,i;if(typeof window<"u"&&window.gradio_api_info)i=window.gradio_api_info;else{if(ze(t?.version||"2.0.0","3.30")<0)s=await this.fetch($t,{method:"POST",body:JSON.stringify({serialize:!1,config:JSON.stringify(t)}),headers:n,credentials:"include"});else{let a=fe(t.root,this.api_prefix,ft);s=await this.fetch(a,{headers:n,credentials:"include"})}if(!s.ok)throw new Error(W);i=await s.json()}return"api"in i&&(i=i.api),i.named_endpoints["/predict"]&&!i.unnamed_endpoints[0]&&(i.unnamed_endpoints[0]=i.named_endpoints["/predict"]),zt(i,t,this.api_map)}catch(s){throw new Error("Could not get API info. "+s.message)}}async function It(e,t,n){var s;let i={};(s=this==null?void 0:this.options)!=null&&s.hf_token&&(i.Authorization=`Bearer ${this.options.hf_token}`);let a=1e3,o=[],r;for(let l=0;l<t.length;l+=a){let _=t.slice(l,l+a),m=new FormData;_.forEach(g=>{m.append("files",g)});try{let g=n?`${e}${this.api_prefix}/${xe}?upload_id=${n}`:`${e}${this.api_prefix}/${xe}`;r=await this.fetch(g,{method:"POST",body:m,headers:i,credentials:"include"})}catch(g){throw new Error(W+g.message)}if(!r.ok){let g=await r.text();return{error:`HTTP ${r.status}: ${g}`}}let p=await r.json();p&&o.push(...p)}return{files:o}}async function Rt(e,t,n,s){let i=(Array.isArray(e)?e:[e]).map(o=>o.blob),a=i.filter(o=>o.size>(s??1/0));if(a.length)throw new Error(`File size exceeds the maximum allowed size of ${s} bytes: ${a.map(o=>o.name).join(", ")}`);return await Promise.all(await this.upload_files(t,i,n).then(async o=>{if(o.error)throw new Error(o.error);return o.files?o.files.map((r,l)=>new Q({...e[l],path:r,url:`${t}${this.api_prefix}/file=${r}`})):[]}))}var Q=class{constructor({path:t,url:n,orig_name:s,size:i,blob:a,is_stream:o,mime_type:r,alt_text:l,b64:_}){u(this,"path"),u(this,"url"),u(this,"orig_name"),u(this,"size"),u(this,"blob"),u(this,"is_stream"),u(this,"mime_type"),u(this,"alt_text"),u(this,"b64"),u(this,"meta",{_type:"gradio.FileData"}),this.path=t,this.url=n,this.orig_name=s,this.size=i,this.blob=n?void 0:a,this.is_stream=o,this.mime_type=r,this.alt_text=l,this.b64=_}},_e=class{constructor(t,n){u(this,"type"),u(this,"command"),u(this,"meta"),u(this,"fileData"),this.type="command",this.command=t,this.meta=n}},_n=typeof process<"u"&&process.versions&&process.versions.node;function qe(e,t,n){for(;n.length>1;){let i=n.shift();if(typeof i=="string"||typeof i=="number")e=e[i];else throw new Error("Invalid key type")}let s=n.shift();if(typeof s=="string"||typeof s=="number")e[s]=t;else throw new Error("Invalid key type")}async function ge(e,t=void 0,n=[],s=!1,i=void 0){if(Array.isArray(e)){let a=[];return await Promise.all(e.map(async(o,r)=>{var l;let _=n.slice();_.push(String(r));let m=await ge(e[r],s?((l=i?.parameters[r])==null?void 0:l.component)||void 0:t,_,!1,i);a=a.concat(m)})),a}else{if(globalThis.Buffer&&e instanceof globalThis.Buffer||e instanceof Blob)return[{path:n,blob:new Blob([e]),type:t}];if(typeof e=="object"&&e!==null){let a=[];for(let o of Object.keys(e)){let r=[...n,o],l=e[o];a=a.concat(await ge(l,void 0,r,!1,i))}return a}}return[]}function Ft(e,t){var n,s;let i=(s=(n=t?.dependencies)==null?void 0:n.find(a=>a.id==e))==null?void 0:s.queue;return i!=null?!i:!t.enable_queue}function Jt(e,t){return new Promise((n,s)=>{let i=new MessageChannel;i.port1.onmessage=({data:a})=>{i.port1.close(),n(a)},window.parent.postMessage(e,t,[i.port2])})}function K(e,t,n,s,i=!1){if(s==="input"&&!i)throw new Error("Invalid code path. Cannot skip state inputs for input.");if(s==="output"&&i)return e;let a=[],o=0,r=s==="input"?t.inputs:t.outputs;for(let l=0;l<r.length;l++){let _=r[l],m=n.find(p=>p.id===_);if(m?.type==="state"){if(i)if(e.length===r.length){let p=e[o];a.push(p),o++}else a.push(null);else{o++;continue}continue}else{let p=e[o];a.push(p),o++}}return a}async function Wt(e,t,n){let s=this;await Gt(s,t);let i=await ge(t,void 0,[],!0,n);return(await Promise.all(i.map(async({path:a,blob:o,type:r})=>{if(!o)return{path:a,type:r};let l=await s.upload_files(e,[o]),_=l.files&&l.files[0];return{path:a,file_url:_,type:r,name:typeof File<"u"&&o instanceof File?o?.name:void 0}}))).forEach(({path:a,file_url:o,type:r,name:l})=>{if(r==="Gallery")qe(t,o,a);else if(o){let _=new Q({path:o,orig_name:l});qe(t,_,a)}}),t}async function Gt(e,t){var n,s;if(!((n=e.config)!=null&&n.root||(s=e.config)!=null&&s.root_url))throw new Error(Ue);await Fe(e,t)}async function Fe(e,t,n=[]){for(let s in t)t[s]instanceof _e?await Mt(e,t,s):typeof t[s]=="object"&&t[s]!==null&&await Fe(e,t[s],[...n,s])}async function Mt(e,t,n){var s,i;let a=t[n],o=((s=e.config)==null?void 0:s.root)||((i=e.config)==null?void 0:i.root_url);if(!o)throw new Error(Ue);try{let r,l;if(typeof process<"u"&&process.versions&&process.versions.node){let g=await Promise.resolve().then(()=>(ue(),le));l=(await Promise.resolve().then(()=>(ue(),le))).resolve(process.cwd(),a.meta.path),r=await g.readFile(l)}else throw new Error(Ct);let _=new Blob([r],{type:"application/octet-stream"}),m=await e.upload_files(o,[_]),p=m.files&&m.files[0];if(p){let g=new Q({path:p,orig_name:a.meta.name||""});t[n]=g}}catch(r){console.error(qt,r)}}async function Ht(e,t,n){let s={"Content-Type":"application/json"};this.options.hf_token&&(s.Authorization=`Bearer ${this.options.hf_token}`);try{var i=await this.fetch(e,{method:"POST",body:JSON.stringify(t),headers:{...s,...n},credentials:"include"})}catch{return[{error:W},500]}let a,o;try{a=await i.json(),o=i.status}catch(r){a={error:`Could not parse server response: ${r}`},o=500}return[a,o]}async function Zt(e,t={}){let n=!1,s=!1;if(!this.config)throw new Error("Could not resolve app config");if(typeof e=="number")this.config.dependencies.find(i=>i.id==e);else{let i=e.replace(/^\//,"");this.config.dependencies.find(a=>a.id==this.api_map[i])}return new Promise(async(i,a)=>{let o=this.submit(e,t,null,null,!0),r;for await(let l of o)l.type==="data"&&(s&&i(r),n=!0,r=l),l.type==="status"&&(l.stage==="error"&&a(l),l.stage==="complete"&&(s=!0,n&&i(r)))})}async function Y(e,t,n){let s=t==="subdomain"?`https://huggingface.co/api/spaces/by-subdomain/${e}`:`https://huggingface.co/api/spaces/${e}`,i,a;try{if(i=await fetch(s),a=i.status,a!==200)throw new Error;i=await i.json()}catch{n({status:"error",load_status:"error",message:kt,detail:"NOT_FOUND"});return}if(!i||a!==200)return;let{runtime:{stage:o},id:r}=i;switch(o){case"STOPPED":case"SLEEPING":n({status:"sleeping",load_status:"pending",message:"Space is asleep. Waking it up...",detail:o}),setTimeout(()=>{Y(e,t,n)},1e3);break;case"PAUSED":n({status:"paused",load_status:"error",message:"This space has been paused by the author. If you would like to try this demo, consider duplicating the space.",detail:o,discussions_enabled:await De(r)});break;case"RUNNING":case"RUNNING_BUILDING":n({status:"running",load_status:"complete",message:"Space is running.",detail:o});break;case"BUILDING":n({status:"building",load_status:"pending",message:"Space is building...",detail:o}),setTimeout(()=>{Y(e,t,n)},1e3);break;case"APP_STARTING":n({status:"starting",load_status:"pending",message:"Space is starting...",detail:o}),setTimeout(()=>{Y(e,t,n)},1e3);break;default:n({status:"space_error",load_status:"error",message:"This space is experiencing an issue.",detail:o,discussions_enabled:await De(r)});break}}var Je=async(e,t)=>{let n=0,s=12,i=5e3;return new Promise(a=>{Y(e,ye.test(e)?"space_name":"subdomain",o=>{t(o),o.status==="running"||o.status==="error"||o.status==="paused"||o.status==="space_error"?a():(o.status==="sleeping"||o.status==="building")&&(n<s?(n++,setTimeout(()=>{Je(e,t).then(a)},i)):a())})})},Kt=/^(?=[^]*\b[dD]iscussions{0,1}\b)(?=[^]*\b[dD]isabled\b)[^]*$/;async function De(e){try{let t=await fetch(`https://huggingface.co/api/spaces/${e}/discussions`,{method:"HEAD"}),n=t.headers.get("x-error-message");return!(!t.ok||n&&Kt.test(n))}catch{return!1}}async function Yt(e,t){let n={};t&&(n.Authorization=`Bearer ${t}`);try{let s=await fetch(`https://huggingface.co/api/spaces/${e}/${_t}`,{headers:n});if(s.status!==200)throw new Error("Space hardware could not be obtained.");let{hardware:i}=await s.json();return i.current}catch(s){throw new Error(s.message)}}async function Qt(e,t,n){let s={};n&&(s.Authorization=`Bearer ${n}`);let i={seconds:t};try{let a=await fetch(`https://huggingface.co/api/spaces/${e}/${gt}`,{method:"POST",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(i)});if(a.status!==200)throw new Error("Could not set sleep timeout on duplicated Space. Please visit *ADD HF LINK TO SETTINGS* to set a timeout manually to reduce billing charges.");return await a.json()}catch(a){throw new Error(a.message)}}var Oe=["cpu-basic","cpu-upgrade","cpu-xl","t4-small","t4-medium","a10g-small","a10g-large","a10g-largex2","a10g-largex4","a100-large","zero-a10g","h100","h100x8"];async function Xt(e,t){let{hf_token:n,private:s,hardware:i,timeout:a,auth:o}=t;if(i&&!Oe.includes(i))throw new Error(`Invalid hardware type provided. Valid types are: ${Oe.map(f=>`"${f}"`).join(",")}.`);let{http_protocol:r,host:l}=await V(e,n),_=null;if(o){let f=await Ie(r,l,o,fetch);f&&(_=Re(f))}let m={Authorization:`Bearer ${n}`,"Content-Type":"application/json",..._?{Cookie:_.join("; ")}:{}},p=(await(await fetch("https://huggingface.co/api/whoami-v2",{headers:m})).json()).name,g=e.split("/")[1],C={repository:`${p}/${g}`};s&&(C.private=!0);let U;try{i||(U=await Yt(e,n))}catch(f){throw Error(we+f.message)}let c=i||U||"cpu-basic";C.hardware=c;try{let f=await fetch(`https://huggingface.co/api/spaces/${e}/duplicate`,{method:"POST",headers:m,body:JSON.stringify(C)});if(f.status===409)try{return await G.connect(`${p}/${g}`,t)}catch(P){throw console.error("Failed to connect Client instance:",P),P}else if(f.status!==200)throw new Error(f.statusText);let D=await f.json();return await Qt(`${p}/${g}`,a||300,n),await G.connect(Vt(D.url),t)}catch(f){throw new Error(f)}}function Vt(e){let t=/https:\/\/huggingface.co\/spaces\/([^/]+\/[^/]+)/,n=e.match(t);if(n)return n[1]}var B,me=class extends TransformStream{constructor(t={allowCR:!1}){super({transform:(n,s)=>{for(n=Z(this,B)+n;;){let i=n.indexOf(`
|
| 2 |
+
`),a=t.allowCR?n.indexOf("\r"):-1;if(a!==-1&&a!==n.length-1&&(i===-1||i-1>a)){s.enqueue(n.slice(0,a)),n=n.slice(a+1);continue}if(i===-1)break;let o=n[i-1]==="\r"?i-1:i;s.enqueue(n.slice(0,o)),n=n.slice(i+1)}ut(this,B,n)},flush:n=>{if(Z(this,B)==="")return;let s=t.allowCR&&Z(this,B).endsWith("\r")?Z(this,B).slice(0,-1):Z(this,B);n.enqueue(s)}}),lt(this,B,"")}};B=new WeakMap;function en(e){let t=new TextDecoderStream,n=new me({allowCR:!0});return e.pipeThrough(t).pipeThrough(n)}function tn(e){let t=/[:]\s*/.exec(e),n=t&&t.index;if(n)return[e.substring(0,n),e.substring(n+t[0].length)]}function Te(e,t,n){e.get(t)||e.set(t,n)}async function*nn(e,t){if(!e.body)return;let n=en(e.body),s,i=n.getReader(),a;for(;;){if(t&&t.aborted)return i.cancel();if(s=await i.read(),s.done)return;if(!s.value){a&&(yield a),a=void 0;continue}let[o,r]=tn(s.value)||[];o&&(o==="data"?(a||(a={}),a[o]=a[o]?a[o]+`
|
| 3 |
+
`+r:r):o==="event"?(a||(a={}),a[o]=r):o==="id"?(a||(a={}),a[o]=+r||r):o==="retry"&&(a||(a={}),a[o]=+r||void 0))}}async function sn(e,t){let n=new Request(e,t);Te(n.headers,"Accept","text/event-stream"),Te(n.headers,"Content-Type","application/json");let s=await fetch(n);if(!s.ok)throw s;return nn(s,n.signal)}async function on(){let{event_callbacks:e,unclosed_events:t,pending_stream_messages:n,stream_status:s,config:i,jwt:a}=this,o=this;if(!i)throw new Error("Could not resolve app config");s.open=!0;let r=null,l=new URLSearchParams({session_hash:this.session_hash}).toString(),_=new URL(`${i.root}${this.api_prefix}/${Ae}?${l}`);if(a&&_.searchParams.set("__sign",a),r=this.stream(_),!r){console.warn("Cannot connect to SSE endpoint: "+_.toString());return}r.onmessage=async function(m){let p=JSON.parse(m.data);if(p.msg==="close_stream"){ve(s,o.abort_controller);return}let g=p.event_id;if(!g)await Promise.all(Object.keys(e).map(C=>e[C](p)));else if(e[g]&&i){p.msg==="process_completed"&&["sse","sse_v1","sse_v2","sse_v2.1","sse_v3"].includes(i.protocol)&&t.delete(g);let C=e[g];typeof window<"u"&&typeof document<"u"?setTimeout(C,0,p):C(p)}else n[g]||(n[g]=[]),n[g].push(p)},r.onerror=async function(m){console.error(m),await Promise.all(Object.keys(e).map(p=>e[p]({msg:"broken_connection",message:W})))}}function ve(e,t){e&&(e.open=!1,t?.abort())}function an(e,t,n){e[t]?n.data.forEach((s,i)=>{let a=rn(e[t][i],s);e[t][i]=a,n.data[i]=a}):(e[t]=[],n.data.forEach((s,i)=>{e[t][i]=s}))}function rn(e,t){return t.forEach(([n,s,i])=>{e=cn(e,s,n,i)}),e}function cn(e,t,n,s){if(t.length===0){if(n==="replace")return s;if(n==="append")return e+s;throw new Error(`Unsupported action: ${n}`)}let i=e;for(let o=0;o<t.length-1;o++)i=i[t[o]];let a=t[t.length-1];switch(n){case"replace":i[a]=s;break;case"append":i[a]+=s;break;case"add":Array.isArray(i)?i.splice(Number(a),0,s):i[a]=s;break;case"delete":Array.isArray(i)?i.splice(Number(a),1):delete i[a];break;default:throw new Error(`Unknown action: ${n}`)}return e}function ln(e,t={}){let n={close:()=>{console.warn("Method not implemented.")},onerror:null,onmessage:null,onopen:null,readyState:0,url:e.toString(),withCredentials:!1,CONNECTING:0,OPEN:1,CLOSED:2,addEventListener:()=>{throw new Error("Method not implemented.")},dispatchEvent:()=>{throw new Error("Method not implemented.")},removeEventListener:()=>{throw new Error("Method not implemented.")}};return sn(e,t).then(async s=>{n.readyState=n.OPEN;try{for await(let i of s)n.onmessage&&n.onmessage(i);n.readyState=n.CLOSED}catch(i){n.onerror&&n.onerror(i),n.readyState=n.CLOSED}}).catch(s=>{console.error(s),n.onerror&&n.onerror(s),n.readyState=n.CLOSED}),n}function un(e,t={},n,s,i){var a;try{let o=function(w){(i||Ze[w.type])&&m(w)},r=function(){for(Qe=!0;H.length>0;)H.shift()({value:void 0,done:!0})},l=function(w){H.length>0?H.shift()(w):ae.push(w)},_=function(w){l(pn(w)),r()},m=function(w){l({value:w,done:!1})},p=function(){return ae.length>0?Promise.resolve(ae.shift()):new Promise(w=>H.push(w))},{hf_token:g}=this.options,{fetch:C,app_reference:U,config:c,session_hash:f,api_info:D,api_map:P,stream_status:ee,pending_stream_messages:te,pending_diff_streams:ne,event_callbacks:se,unclosed_events:We,post_data:ie,options:R,api_prefix:F}=this,Ge=this;if(!D)throw new Error("No API found");if(!c)throw new Error("Could not resolve app config");let{fn_index:d,endpoint_info:be,dependency:J}=dn(D,e,P,c),Me=Lt(t,be),q,z,A=c.protocol??"ws",$e="",He=()=>$e,h=typeof e=="number"?"/predict":e,M,k=null,O=!1,oe={},I=typeof window<"u"&&typeof document<"u"?new URLSearchParams(window.location.search).toString():"",Ze=((a=R?.events)==null?void 0:a.reduce((w,T)=>(w[T]=!0,w),{}))||{};async function Ke(){let w={},T={};A==="ws"?(q&&q.readyState===0?q.addEventListener("open",()=>{q.close()}):q.close(),w={fn_index:d,session_hash:f}):(w={event_id:k},T={event_id:k,session_hash:f,fn_index:d});try{if(!c)throw new Error("Could not resolve app config");"event_id"in T&&await C(`${c.root}${F}/${vt}`,{headers:{"Content-Type":"application/json"},method:"POST",body:JSON.stringify(T)}),await C(`${c.root}${F}/${yt}`,{headers:{"Content-Type":"application/json"},method:"POST",body:JSON.stringify(w)})}catch{console.warn("The `/reset` endpoint could not be called. Subsequent endpoint results may be unreliable.")}}let Ye=async w=>{await this._resolve_heartbeat(w)};async function ke(w){if(!c)return;let T=w.render_id;c.components=[...c.components.filter(E=>E.props.rendered_in!==T),...w.components],c.dependencies=[...c.dependencies.filter(E=>E.rendered_in!==T),...w.dependencies];let re=c.components.some(E=>E.type==="state"),b=c.dependencies.some(E=>E.targets.some(S=>S[1]==="unload"));c.connect_heartbeat=re||b,await Ye(c),o({type:"render",data:w,endpoint:h,fn_index:d})}this.handle_blob(c.root,Me,be).then(async w=>{var T;if(M={data:K(w,J,c.components,"input",!0)||[],event_data:n,fn_index:d,trigger_id:s},Ft(d,c))o({type:"status",endpoint:h,stage:"pending",queue:!1,fn_index:d,time:new Date}),ie(`${c.root}${F}/run${h.startsWith("/")?h:`/${h}`}${I?"?"+I:""}`,{...M,session_hash:f}).then(([b,E])=>{let S=b.data;E==200?(o({type:"data",endpoint:h,fn_index:d,data:K(S,J,c.components,"output",R.with_null_state),time:new Date,event_data:n,trigger_id:s}),b.render_config&&ke(b.render_config),o({type:"status",endpoint:h,fn_index:d,stage:"complete",eta:b.average_duration,queue:!1,time:new Date})):o({type:"status",stage:"error",endpoint:h,fn_index:d,message:b.error,queue:!1,time:new Date})}).catch(b=>{o({type:"status",stage:"error",message:b.message,endpoint:h,fn_index:d,queue:!1,time:new Date})});else if(A=="ws"){let{ws_protocol:b,host:E}=await V(U,g);o({type:"status",stage:"pending",queue:!0,endpoint:h,fn_index:d,time:new Date});let S=new URL(`${b}://${Dt(E,c.root,!0)}/queue/join${I?"?"+I:""}`);this.jwt&&S.searchParams.set("__sign",this.jwt),q=new WebSocket(S),q.onclose=x=>{x.wasClean||o({type:"status",stage:"error",broken:!0,message:W,queue:!0,endpoint:h,fn_index:d,time:new Date})},q.onmessage=function(x){let j=JSON.parse(x.data),{type:$,status:v,data:y}=he(j,oe[d]);if($==="update"&&v&&!O)o({type:"status",endpoint:h,fn_index:d,time:new Date,...v}),v.stage==="error"&&q.close();else if($==="hash"){q.send(JSON.stringify({fn_index:d,session_hash:f}));return}else $==="data"?q.send(JSON.stringify({...M,session_hash:f})):$==="complete"?O=v:$==="log"?o({type:"log",title:y.title,log:y.log,level:y.level,endpoint:h,duration:y.duration,visible:y.visible,fn_index:d}):$==="generating"&&o({type:"status",time:new Date,...v,stage:v?.stage,queue:!0,endpoint:h,fn_index:d});y&&(o({type:"data",time:new Date,data:K(y.data,J,c.components,"output",R.with_null_state),endpoint:h,fn_index:d,event_data:n,trigger_id:s}),O&&(o({type:"status",time:new Date,...O,stage:v?.stage,queue:!0,endpoint:h,fn_index:d}),q.close()))},ze(c.version||"2.0.0","3.6")<0&&addEventListener("open",()=>q.send(JSON.stringify({hash:f})))}else if(A=="sse"){o({type:"status",stage:"pending",queue:!0,endpoint:h,fn_index:d,time:new Date});var re=new URLSearchParams({fn_index:d.toString(),session_hash:f}).toString();let b=new URL(`${c.root}${F}/${Ae}?${I?I+"&":""}${re}`);if(this.jwt&&b.searchParams.set("__sign",this.jwt),z=this.stream(b),!z)return Promise.reject(new Error("Cannot connect to SSE endpoint: "+b.toString()));z.onmessage=async function(E){let S=JSON.parse(E.data),{type:x,status:j,data:$}=he(S,oe[d]);if(x==="update"&&j&&!O)o({type:"status",endpoint:h,fn_index:d,time:new Date,...j}),j.stage==="error"&&(z?.close(),r());else if(x==="data"){let[v,y]=await ie(`${c.root}${F}/queue/data`,{...M,session_hash:f,event_id:k});y!==200&&(o({type:"status",stage:"error",message:W,queue:!0,endpoint:h,fn_index:d,time:new Date}),z?.close(),r())}else x==="complete"?O=j:x==="log"?o({type:"log",title:$.title,log:$.log,level:$.level,endpoint:h,duration:$.duration,visible:$.visible,fn_index:d}):(x==="generating"||x==="streaming")&&o({type:"status",time:new Date,...j,stage:j?.stage,queue:!0,endpoint:h,fn_index:d});$&&(o({type:"data",time:new Date,data:K($.data,J,c.components,"output",R.with_null_state),endpoint:h,fn_index:d,event_data:n,trigger_id:s}),O&&(o({type:"status",time:new Date,...O,stage:j?.stage,queue:!0,endpoint:h,fn_index:d}),z?.close(),r()))}}else if(A=="sse_v1"||A=="sse_v2"||A=="sse_v2.1"||A=="sse_v3"){o({type:"status",stage:"pending",queue:!0,endpoint:h,fn_index:d,time:new Date});let b="";typeof window<"u"&&typeof document<"u"&&(b=(T=window?.location)==null?void 0:T.hostname);let E=b.includes(".dev.")?`https://moon-${b.split(".")[1]}.dev.spaces.huggingface.tech`:"https://huggingface.co";(typeof window<"u"&&typeof document<"u"&&window.parent!=window&&window.supports_zerogpu_headers?Jt("zerogpu-headers",E):Promise.resolve(null)).then(S=>ie(`${c.root}${F}/${dt}?${I}`,{...M,session_hash:f},S)).then(async([S,x])=>{if(x===503)o({type:"status",stage:"error",message:Be,queue:!0,endpoint:h,fn_index:d,time:new Date});else if(x===422)o({type:"status",stage:"error",message:S.detail,queue:!0,endpoint:h,fn_index:d,code:"validation_error",time:new Date}),r();else if(x!==200)o({type:"status",stage:"error",broken:!1,message:S.detail,queue:!0,endpoint:h,fn_index:d,time:new Date});else{k=S.event_id,$e=k;let j=async function($){try{let{type:v,status:y,data:N,original_msg:Xe}=he($,oe[d]);if(v=="heartbeat")return;if(v==="update"&&y&&!O)o({type:"status",endpoint:h,fn_index:d,time:new Date,original_msg:Xe,...y});else if(v==="complete")O=y;else if(v=="unexpected_error"||v=="broken_connection"){console.error("Unexpected error",y?.message);let Ve=v==="broken_connection";o({type:"status",stage:"error",message:y?.message||"An Unexpected Error Occurred!",queue:!0,endpoint:h,broken:Ve,session_not_found:y?.session_not_found,fn_index:d,time:new Date})}else if(v==="log"){o({type:"log",title:N.title,log:N.log,level:N.level,endpoint:h,duration:N.duration,visible:N.visible,fn_index:d});return}else(v==="generating"||v==="streaming")&&(o({type:"status",time:new Date,...y,stage:y?.stage,queue:!0,endpoint:h,fn_index:d}),N&&J.connection!=="stream"&&["sse_v2","sse_v2.1","sse_v3"].includes(A)&&an(ne,k,N));N&&(o({type:"data",time:new Date,data:K(N.data,J,c.components,"output",R.with_null_state),endpoint:h,fn_index:d}),N.render_config&&await ke(N.render_config),O&&(o({type:"status",time:new Date,...O,stage:y?.stage,queue:!0,endpoint:h,fn_index:d}),r())),(y?.stage==="complete"||y?.stage==="error")&&(se[k]&&delete se[k],k in ne&&delete ne[k])}catch(v){console.error("Unexpected client exception",v),o({type:"status",stage:"error",message:"An Unexpected Error Occurred!",queue:!0,endpoint:h,fn_index:d,time:new Date}),["sse_v2","sse_v2.1","sse_v3"].includes(A)&&(ve(ee,Ge.abort_controller),ee.open=!1,r())}};k in te&&(te[k].forEach($=>j($)),delete te[k]),se[k]=j,We.add(k),ee.open||await this.open_stream()}})}});let Qe=!1,ae=[],H=[],Ee={[Symbol.asyncIterator]:()=>Ee,next:p,throw:async w=>(_(w),p()),return:async()=>(r(),p()),cancel:Ke,event_id:He};return Ee}catch(o){throw console.error("Submit function encountered an error:",o),o}}function pn(e){return{then:(t,n)=>n(e)}}function dn(e,t,n,s){let i,a,o;if(typeof t=="number")i=t,a=e.unnamed_endpoints[i],o=s.dependencies.find(r=>r.id==t);else{let r=t.replace(/^\//,"");i=n[r],a=e.named_endpoints[t.trim()],o=s.dependencies.find(l=>l.id==n[r])}if(typeof i!="number")throw new Error("There is no endpoint matching that name of fn_index matching that number.");return{fn_index:i,endpoint_info:a,dependency:o}}var G=class{constructor(t,n={events:["data"]}){u(this,"app_reference"),u(this,"options"),u(this,"deep_link",null),u(this,"config"),u(this,"api_prefix",""),u(this,"api_info"),u(this,"api_map",{}),u(this,"session_hash",Math.random().toString(36).substring(2)),u(this,"jwt",!1),u(this,"last_status",{}),u(this,"cookies",null),u(this,"stream_status",{open:!1}),u(this,"closed",!1),u(this,"pending_stream_messages",{}),u(this,"pending_diff_streams",{}),u(this,"event_callbacks",{}),u(this,"unclosed_events",new Set),u(this,"heartbeat_event",null),u(this,"abort_controller",null),u(this,"stream_instance",null),u(this,"current_payload"),u(this,"ws_map",{}),u(this,"view_api"),u(this,"upload_files"),u(this,"upload"),u(this,"handle_blob"),u(this,"post_data"),u(this,"submit"),u(this,"predict"),u(this,"open_stream"),u(this,"resolve_config"),u(this,"resolve_cookies");var s;this.app_reference=t,this.deep_link=((s=n.query_params)==null?void 0:s.deep_link)||null,n.events||(n.events=["data"]),this.options=n,this.current_payload={},this.view_api=Ut.bind(this),this.upload_files=It.bind(this),this.handle_blob=Wt.bind(this),this.post_data=Ht.bind(this),this.submit=un.bind(this),this.predict=Zt.bind(this),this.open_stream=on.bind(this),this.resolve_config=Tt.bind(this),this.resolve_cookies=Nt.bind(this),this.upload=Rt.bind(this),this.fetch=this.fetch.bind(this),this.handle_space_success=this.handle_space_success.bind(this),this.stream=this.stream.bind(this)}get_url_config(t=null){if(!this.config)throw new Error(L);t===null&&(t=window.location.href);let n=o=>o.replace(/^\/+|\/+$/g,""),s=n(new URL(this.config.root).pathname),i=n(new URL(t).pathname),a;return i.startsWith(s)?a=n(i.substring(s.length)):a="",this.get_page_config(a)}get_page_config(t){if(!this.config)throw new Error(L);let n=this.config;return t in n.page||(t=""),{...n,current_page:t,layout:n.page[t].layout,components:n.components.filter(s=>n.page[t].components.includes(s.id)),dependencies:this.config.dependencies.filter(s=>n.page[t].dependencies.includes(s.id))}}fetch(t,n){let s=new Headers(n?.headers||{});if(this&&this.cookies&&s.append("Cookie",this.cookies),this&&this.options.headers)for(let i in this.options.headers)s.append(i,this.options.headers[i]);return fetch(t,{...n,headers:s})}stream(t){let n=new Headers;if(this&&this.cookies&&n.append("Cookie",this.cookies),this&&this.options.headers)for(let s in this.options.headers)n.append(s,this.options.headers[s]);return this&&this.options.hf_token&&n.append("Authorization",`Bearer ${this.options.hf_token}`),this.abort_controller=new AbortController,this.stream_instance=ln(t.toString(),{credentials:"include",headers:n,signal:this.abort_controller.signal}),this.stream_instance}async init(){var t;this.options.auth&&await this.resolve_cookies(),await this._resolve_config().then(({config:n})=>this._resolve_heartbeat(n)),this.api_info=await this.view_api(),this.api_map=Ot(((t=this.config)==null?void 0:t.dependencies)||[])}async _resolve_heartbeat(t){if(t&&(this.config=t,this.api_prefix=t.api_prefix||"",this.config&&this.config.connect_heartbeat&&this.config.space_id&&this.options.hf_token&&(this.jwt=await je(this.config.space_id,this.options.hf_token,this.cookies))),t.space_id&&this.options.hf_token&&(this.jwt=await je(t.space_id,this.options.hf_token)),this.config&&this.config.connect_heartbeat){let n=new URL(`${this.config.root}${this.api_prefix}/${mt}/${this.session_hash}`);this.jwt&&n.searchParams.set("__sign",this.jwt),this.heartbeat_event||(this.heartbeat_event=this.stream(n))}}static async connect(t,n={events:["data"]}){let s=new this(t,n);return n.session_hash&&(s.session_hash=n.session_hash),await s.init(),s}async reconnect(){let t=new URL(`${this.config.root}${this.api_prefix}/${bt}`),n;try{let s=await this.fetch(t);if(!s.ok)throw new Error;n=(await s.json()).app_id}catch{return"broken"}return n!==this.config.app_id?"changed":"connected"}close(){this.closed=!0,ve(this.stream_status,this.abort_controller)}set_current_payload(t){this.current_payload=t}static async duplicate(t,n={events:["data"]}){return Xt(t,n)}async _resolve_config(){let{http_protocol:t,host:n,space_id:s}=await V(this.app_reference,this.options.hf_token),{status_callback:i}=this.options;s&&i&&await Je(s,i);let a;try{let o=`${t}//${n}`;if(a=await this.resolve_config(o),!a)throw new Error(L);return this.config_success(a)}catch(o){if(s&&i)Y(s,ye.test(s)?"space_name":"subdomain",this.handle_space_success);else throw i&&i({status:"error",message:"Could not load this space.",load_status:"error",detail:"NOT_FOUND"}),Error(o)}}async config_success(t){if(this.config=t,this.api_prefix=t.api_prefix||"",this.config.auth_required)return this.prepare_return_obj();try{this.api_info=await this.view_api()}catch(n){console.error(Et+n.message)}return this.prepare_return_obj()}async handle_space_success(t){var n;if(!this)throw new Error(L);let{status_callback:s}=this.options;if(s&&s(t),t.status==="running")try{if(this.config=await this._resolve_config(),this.api_prefix=((n=this==null?void 0:this.config)==null?void 0:n.api_prefix)||"",!this.config)throw new Error(L);return await this.config_success(this.config)}catch(i){throw s&&s({status:"error",message:"Could not load this space.",load_status:"error",detail:"NOT_FOUND"}),i}}async component_server(t,n,s){var i;if(!this.config)throw new Error(L);let a={},{hf_token:o}=this.options,{session_hash:r}=this;o&&(a.Authorization=`Bearer ${this.options.hf_token}`);let l,_=this.config.components.find(p=>p.id===t);(i=_?.props)!=null&&i.root_url?l=_.props.root_url:l=this.config.root;let m;if("binary"in s){m=new FormData;for(let p in s.data)p!=="binary"&&m.append(p,s.data[p]);m.set("component_id",t.toString()),m.set("fn_name",n),m.set("session_hash",r)}else m=JSON.stringify({data:s,component_id:t,fn_name:n,session_hash:r}),a["Content-Type"]="application/json";o&&(a.Authorization=`Bearer ${o}`);try{let p=await this.fetch(`${l}${this.api_prefix}/${wt}/`,{method:"POST",body:m,headers:a,credentials:"include"});if(!p.ok)throw new Error("Could not connect to component server: "+p.statusText);return await p.json()}catch(p){console.warn(p)}}set_cookies(t){this.cookies=Re(t).join("; ")}prepare_return_obj(){return{config:this.config,predict:this.predict,submit:this.submit,view_api:this.view_api,component_server:this.component_server}}async connect_ws(t){return new Promise((n,s)=>{let i;try{i=new WebSocket(t)}catch{this.ws_map[t]="failed";return}this.ws_map[t]="pending",i.onopen=()=>{this.ws_map[t]=i,n()},i.onerror=a=>{console.error("WebSocket error:",a),this.close_ws(t),this.ws_map[t]="failed",n()},i.onclose=()=>{this.ws_map[t]="closed"},i.onmessage=a=>{}})}async send_ws_message(t,n){if(!(t in this.ws_map))await this.connect_ws(t);else if(this.ws_map[t]==="pending"||this.ws_map[t]==="closed"||this.ws_map[t]==="failed")return;let s=this.ws_map[t];s instanceof WebSocket?s.send(JSON.stringify(n)):this.post_data(t,n)}async close_ws(t){if(t in this.ws_map){let n=this.ws_map[t];n instanceof WebSocket&&(n.close(),delete this.ws_map[t])}}};return ot(hn);})();
|
static/mermaid.min.js
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|