Spaces:
Running on Zero
Running on Zero
Web agent view (Qwen3.6-27B-FP8 planner + DeskForge-Qwen3.5-4B) on top of the live desktop duel
bf47338 verified Download setup_bar.py from docling-project/DeskForge: direct link, hf CLI and curl.
- Browser
- Download file 13.2 kB
-
https://huggingface.co/spaces/docling-project/DeskForge/resolve/main/setup_bar.py
- Command line
-
hf download hf://spaces/docling-project/DeskForge/setup_bar.py
-
curl -L -o setup_bar.py https://huggingface.co/spaces/docling-project/DeskForge/resolve/main/setup_bar.py
13.2 kB
| """The numbered setup bar above the desktop: 1 model, 2 look, 3 task, then Start. | |
| It is one gr.HTML component with its own markup, styles and script, so it can use | |
| the Docling Agent design's elements (bordered pills, mono captions, popover cards) | |
| instead of stock Gradio widgets. Each pill opens a popover with the full options, | |
| including the advanced ones. The script sends its state to Python as event data: | |
| "change" whenever a choice changes, "input" when a look should be applied now, | |
| "submit" for Start and "stop" for Stop. | |
| """ | |
| LOOK_SHUFFLE = "🎲 Shuffle" | |
| RANDOM_TASK = "🎲 Random task" | |
| MODEL_NOTES = { # mean grounding accuracy on DeskForge-1M held-out conditions, from the model cards | |
| "Gemma4-E4B": "DeskForge 85% vs base 12% grounding accuracy", | |
| "Qwen3.5-4B": "DeskForge 88% vs base 76% grounding accuracy", | |
| } | |
| LOOK_SWATCHES = { | |
| "Xfce default": "#9aa5b1", "Windows-like": "#3B6A9E", "macOS-like": "#D9D9D4", | |
| "Dark": "#2E333F", "Big text": "#C9B79A", | |
| } | |
| def default_state(models, tasks): | |
| return {"model": models[0], "look": LOOK_SHUFFLE, "roulette": False, "tokens": 128, | |
| "task": tasks[0], "random": False} | |
| def props(models, looks, tasks_by_name): | |
| """Option lists the script renders from.""" | |
| return dict( | |
| models=[{"id": m, "sub": MODEL_NOTES.get(m, "")} for m in models], | |
| looks=[{"id": LOOK_SHUFFLE, "swatch": ""}] + [{"id": l, "swatch": LOOK_SWATCHES.get(l, "#ccc")} for l in looks], | |
| tasks=[{"id": name, "app": app, "steps": steps} for name, (app, steps) in tasks_by_name.items()], | |
| ) | |
| TEMPLATE = '<div class="dfs"></div>' | |
| SCRIPT = r""" | |
| const S = Object.assign({}, props.value || {}); | |
| const M = props.models || [], L = props.looks || [], T = props.tasks || []; | |
| let open = null; | |
| const root = element.querySelector('.dfs') || element; | |
| const esc = s => String(s).replace(/[&<>"]/g, c => ({'&': '&', '<': '<', '>': '>', '"': '"'}[c])); | |
| function pill(key, n, cap, val) { | |
| return `<button type="button" class="dfs-pill ${open === key ? 'is-open' : ''}" data-open="${key}"> | |
| <span class="dfs-txt"><span class="dfs-cap">Step ${n} · ${cap}</span><span class="dfs-val">${esc(val)}</span></span> | |
| <span class="dfs-caret">▾</span></button>`; | |
| } | |
| function card(title, body, adv) { | |
| return `<div class="dfs-pop"><div class="dfs-pop-head">${title}</div><div class="dfs-pop-body">${body}</div> | |
| ${adv ? `<div class="dfs-adv"><div class="dfs-adv-title">Advanced</div>${adv}</div>` : ''}</div>`; | |
| } | |
| function opt(set, id, label, sub, on, lead) { | |
| return `<button type="button" class="dfs-opt ${on ? 'on' : ''}" data-set="${set}" data-val="${esc(id)}"> | |
| ${lead || '<span class="dfs-radio"></span>'}<span class="dfs-opt-txt"><span class="dfs-opt-main">${esc(label)}</span> | |
| ${sub ? `<span class="dfs-opt-sub">${esc(sub)}</span>` : ''}</span></button>`; | |
| } | |
| function popModel() { | |
| const body = M.map(m => opt('model', m.id, m.id, m.sub, S.model === m.id)).join(''); | |
| const adv = `<div class="dfs-row"><span>Max new tokens</span><span class="dfs-seg">${[64, 128, 256].map(t => | |
| `<button type="button" data-set="tokens" data-val="${t}" class="${S.tokens == t ? 'on' : ''}">${t}</button>`).join('')}</span></div>`; | |
| return card('Model pair · DeskForge vs its base', body, adv); | |
| } | |
| function popLook() { | |
| const body = L.map(l => opt('look', l.id, l.id, l.swatch ? '' : 'A new random theme, font, DPI and panel', | |
| S.look === l.id, l.swatch ? `<span class="dfs-swatch" style="background:${l.swatch}"></span>` : '<span class="dfs-swatch dfs-dice">🎲</span>')).join(''); | |
| const adv = `<button type="button" class="dfs-toggle ${S.roulette ? 'on' : ''}" data-toggle="roulette"> | |
| <span class="dfs-switch"></span><span class="dfs-opt-txt"><span class="dfs-opt-main">Theme roulette</span> | |
| <span class="dfs-opt-sub">A new random look before every step</span></span></button>`; | |
| return card('Desktop look · applies now', body, adv); | |
| } | |
| function popTask() { | |
| let body = opt('task', '__random', '🎲 Random task', 'Surprise me', S.random, '<span class="dfs-radio"></span>'); | |
| let app = null; | |
| for (const t of T) { | |
| if (t.app !== app) { app = t.app; body += `<div class="dfs-group">${esc(app)}</div>`; } | |
| body += opt('task', t.id, t.id.split(' · ').slice(1).join(' · ') || t.id, `${t.steps} steps`, !S.random && S.task === t.id); | |
| } | |
| const adv = `<div class="dfs-own"><div class="dfs-row"><span>Or write your own</span><span class="dfs-hint">one per line · not scored</span></div> | |
| <textarea class="dfs-own-text" rows="3" placeholder="Open the Edit menu. Click Preferences.">${esc(S.own || '')}</textarea> | |
| <div class="dfs-own-foot"><span class="dfs-hint">Runs on the app of the task picked above</span> | |
| <button type="button" class="dfs-own-run" data-act="own">Run mine ↑</button></div></div>`; | |
| return card('Task · scored step by step', body, adv); | |
| } | |
| function render() { | |
| const lookVal = S.look + (S.roulette ? ' + roulette' : ''); | |
| root.innerHTML = `<div class="dfs-bar"> | |
| <div class="dfs-slot">${pill('model', 1, 'Model', S.model)}${open === 'model' ? popModel() : ''}</div> | |
| <div class="dfs-slot">${pill('look', 2, 'Look', lookVal)}${open === 'look' ? popLook() : ''}</div> | |
| <div class="dfs-slot dfs-grow">${pill('task', 3, 'Task', S.random ? '🎲 Random task' : S.task)}${open === 'task' ? popTask() : ''}</div> | |
| <button type="button" class="dfs-start" data-act="start">Start ↑</button> | |
| <button type="button" class="dfs-stop" data-act="stop">Stop</button></div>`; | |
| } | |
| element.addEventListener('input', e => { if (e.target.classList.contains('dfs-own-text')) S.own = e.target.value; }); | |
| element.addEventListener('click', e => { | |
| const t = e.target.closest('[data-open],[data-set],[data-toggle],[data-act]'); | |
| if (!t) return; | |
| e.stopPropagation(); | |
| if (t.dataset.open) { open = open === t.dataset.open ? null : t.dataset.open; render(); return; } | |
| if (t.dataset.set) { | |
| const k = t.dataset.set, v = t.dataset.val; | |
| if (k === 'tokens') S.tokens = +v; | |
| else if (k === 'task') { S.random = v === '__random'; if (!S.random) S.task = v; open = null; } | |
| else { S[k] = v; open = null; } | |
| render(); trigger('change', {...S}); | |
| if (k === 'look') trigger('input', {...S}); | |
| return; | |
| } | |
| if (t.dataset.toggle) { S[t.dataset.toggle] = !S[t.dataset.toggle]; render(); trigger('change', {...S}); return; } | |
| if (t.dataset.act === 'start') { open = null; render(); trigger('submit', {...S, own: ''}); } | |
| if (t.dataset.act === 'own') { | |
| const box = element.querySelector('.dfs-own-text'); S.own = box ? box.value : ''; | |
| if (!S.own.trim()) { box && box.focus(); return; } | |
| open = null; render(); trigger('submit', {...S}); | |
| } | |
| if (t.dataset.act === 'stop') trigger('stop'); | |
| }); | |
| document.addEventListener('click', e => { if (open && !element.contains(e.target)) { open = null; render(); } }); | |
| document.addEventListener('keydown', e => { if (e.key === 'Escape' && open) { open = null; render(); } }); | |
| render(); | |
| """ | |
| CSS = """ | |
| #df-setup { background: #FFFDF8; border-bottom: 1px solid #E6E3DF; padding: 12px 16px; position: relative; z-index: 20; overflow: visible !important; } | |
| #df-setup .dfs-bar { display: flex; align-items: stretch; gap: 8px; flex-wrap: wrap; font-family: 'Hanken Grotesk', system-ui, sans-serif; } | |
| #df-setup .dfs-slot { position: relative; flex: 0 1 220px; min-width: 170px; } | |
| #df-setup .dfs-grow { flex: 1 1 280px; } | |
| #df-setup .dfs-pill { width: 100%; height: 100%; display: flex; align-items: center; gap: 10px; text-align: left; cursor: pointer; | |
| background: #fff; border: 1px solid #E6E3DF; border-radius: 10px; padding: 8px 12px; font: inherit; color: #2B2722; | |
| box-shadow: 0 1px 2px rgba(40,30,20,.04); } | |
| #df-setup .dfs-pill:hover { border-color: #D6D1CA; } | |
| #df-setup .dfs-pill.is-open { border-color: #D2603A; box-shadow: 0 0 0 3px rgba(210,96,58,.10); } | |
| #df-setup .dfs-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; } | |
| #df-setup .dfs-cap { font: 500 10px 'JetBrains Mono', monospace; letter-spacing: .06em; text-transform: uppercase; color: #9a9389; } | |
| #df-setup .dfs-val { font-size: 14px; font-weight: 600; color: #2B2722; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } | |
| #df-setup .dfs-caret { color: #a39d94; font-size: 11px; } | |
| #df-setup .dfs-start { flex: none; font: 600 14px 'Hanken Grotesk', system-ui, sans-serif; color: #fff; background: #D2603A; border: 1px solid #C0552F; | |
| border-radius: 10px; padding: 0 20px; cursor: pointer; } | |
| #df-setup .dfs-start:hover { background: #C0552F; } | |
| #df-setup .dfs-stop { flex: none; font: 500 14px 'Hanken Grotesk', system-ui, sans-serif; color: #5a5142; background: #fff; border: 1px solid #E6E3DF; | |
| border-radius: 10px; padding: 0 16px; cursor: pointer; } | |
| #df-setup .dfs-stop:hover { border-color: #D6D1CA; } | |
| #df-setup .dfs-pop { position: absolute; top: calc(100% + 6px); left: 0; width: 360px; max-width: 88vw; z-index: 50; background: #fff; | |
| border: 1px solid #E6E3DF; border-radius: 12px; box-shadow: 0 18px 40px -14px rgba(60,40,20,.35); overflow: hidden; | |
| animation: dfs-in .12s ease-out; font-family: 'Hanken Grotesk', system-ui, sans-serif; } | |
| @keyframes dfs-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } } | |
| #df-setup .dfs-pop-head { padding: 10px 14px; border-bottom: 1px solid #EEECE8; font: 500 10px 'JetBrains Mono', monospace; | |
| letter-spacing: .06em; text-transform: uppercase; color: #9a9389; } | |
| #df-setup .dfs-pop-body { padding: 6px; max-height: 320px; overflow-y: auto; } | |
| #df-setup .dfs-opt { width: 100%; display: flex; align-items: center; gap: 11px; padding: 9px 10px; border-radius: 8px; border: 1px solid transparent; | |
| background: transparent; text-align: left; cursor: pointer; font: inherit; color: #2B2722; } | |
| #df-setup .dfs-opt:hover { background: #F7F6F4; } | |
| #df-setup .dfs-opt.on { background: #FBF3EC; border-color: #F1DDCD; } | |
| #df-setup .dfs-radio { flex: none; width: 14px; height: 14px; border-radius: 50%; border: 1.5px solid #CFCAC3; background: #fff; } | |
| #df-setup .dfs-opt.on .dfs-radio { border: 4.5px solid #D2603A; } | |
| #df-setup .dfs-opt-txt { display: flex; flex-direction: column; min-width: 0; } | |
| #df-setup .dfs-opt-main { font-size: 14px; font-weight: 500; color: #2B2722; } | |
| #df-setup .dfs-opt-sub { font-size: 12.5px; color: #8a8378; margin-top: 1px; } | |
| #df-setup .dfs-swatch { flex: none; width: 18px; height: 18px; border-radius: 5px; border: 1px solid #E6E3DF; display: inline-flex; | |
| align-items: center; justify-content: center; font-size: 11px; } | |
| #df-setup .dfs-dice { background: #F7F6F4; } | |
| #df-setup .dfs-group { font: 500 10px 'JetBrains Mono', monospace; letter-spacing: .06em; text-transform: uppercase; color: #a39d94; padding: 10px 10px 3px; } | |
| #df-setup .dfs-adv { border-top: 1px solid #EEECE8; background: #FAF9F7; padding: 11px 14px 13px; } | |
| #df-setup .dfs-adv-title { font: 500 10px 'JetBrains Mono', monospace; letter-spacing: .06em; text-transform: uppercase; color: #a39d94; margin-bottom: 8px; } | |
| #df-setup .dfs-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 13.5px; color: #3a332b; } | |
| #df-setup .dfs-seg { display: inline-flex; border: 1px solid #E6E3DF; border-radius: 8px; overflow: hidden; background: #fff; } | |
| #df-setup .dfs-seg button { font: 500 12px 'JetBrains Mono', monospace; color: #6f6a62; background: transparent; border: none; padding: 5px 10px; cursor: pointer; } | |
| #df-setup .dfs-seg button + button { border-left: 1px solid #E6E3DF; } | |
| #df-setup .dfs-seg button.on { background: #D2603A; color: #fff; } | |
| #df-setup .dfs-toggle { width: 100%; display: flex; align-items: center; gap: 11px; background: transparent; border: none; text-align: left; cursor: pointer; padding: 0; font: inherit; } | |
| #df-setup .dfs-switch { flex: none; width: 32px; height: 18px; border-radius: 9px; background: #DCD8D2; position: relative; transition: background .15s; } | |
| #df-setup .dfs-switch::after { content: ""; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: #fff; | |
| box-shadow: 0 1px 2px rgba(0,0,0,.15); transition: left .15s; } | |
| #df-setup .dfs-toggle.on .dfs-switch { background: #D2603A; } | |
| #df-setup .dfs-toggle.on .dfs-switch::after { left: 16px; } | |
| #df-setup .dfs-own { display: flex; flex-direction: column; gap: 7px; } | |
| #df-setup .dfs-hint { font-size: 12px; color: #9a9389; } | |
| #df-setup .dfs-own-text { width: 100%; box-sizing: border-box; resize: vertical; font: 14px/1.45 'Hanken Grotesk', system-ui, sans-serif; color: #2B2722; | |
| background: #fff; border: 1px solid #E6E3DF; border-radius: 9px; padding: 8px 10px; outline: none; } | |
| #df-setup .dfs-own-text:focus { border-color: #D2603A; box-shadow: 0 0 0 3px rgba(210,96,58,.10); } | |
| #df-setup .dfs-own-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; } | |
| #df-setup .dfs-own-run { font: 600 13px 'Hanken Grotesk', system-ui, sans-serif; color: #fff; background: #D2603A; border: 1px solid #C0552F; | |
| border-radius: 8px; padding: 6px 12px; cursor: pointer; white-space: nowrap; } | |
| """ | |