Anurag commited on
Commit
61ba0b8
·
unverified ·
2 Parent(s): b28ea514cf3613

env-builder UX, gateway configurability, and HF Spaces runtime robustness

Browse files

Improve Jupyter security, env-builder UX, gateway configurability, and HF Spaces runtime robustness

Files changed (3) hide show
  1. env-builder.html +2 -1
  2. env-builder.js +21 -6
  3. start.sh +2 -2
env-builder.html CHANGED
@@ -908,7 +908,8 @@ body {
908
  <span class="pblock-title">📦 Bundle Output</span>
909
  </div>
910
  <div class="pblock-body">
911
- <textarea id="bundleOut" placeholder="Your encoded bundle will appear here…" readonly spellcheck="false"></textarea>
 
912
  <input type="text" id="envLineOut" placeholder="HUGGINGCLAW_ENV_BUNDLE=…" readonly spellcheck="false">
913
  <div class="row-btns">
914
  <button id="copyBundle" class="btn btn-amber">⎘ Bundle</button>
 
908
  <span class="pblock-title">📦 Bundle Output</span>
909
  </div>
910
  <div class="pblock-body">
911
+ <button id="generateBundle" class="btn btn-amber" style="width:100%;font-size:12.5px;"># Generate Bundle</button>
912
+ <textarea id="bundleOut" placeholder="Click # Generate to build your bundle…" readonly spellcheck="false"></textarea>
913
  <input type="text" id="envLineOut" placeholder="HUGGINGCLAW_ENV_BUNDLE=…" readonly spellcheck="false">
914
  <div class="row-btns">
915
  <button id="copyBundle" class="btn btn-amber">⎘ Bundle</button>
env-builder.js CHANGED
@@ -2104,7 +2104,7 @@ function valueControlHTML(field) {
2104
  return control;
2105
  }
2106
 
2107
- function cardHTML(f) {
2108
  const TAG_META = {
2109
  critical: { cls: 'badge-critical', lbl: 'critical' },
2110
  credential: { cls: 'badge-credential', lbl: 'credential' },
@@ -2116,7 +2116,7 @@ function cardHTML(f) {
2116
  const tm = TAG_META[f.tag] || TAG_META.optional;
2117
  const badge = `<span class="badge ${tm.cls}">${tm.lbl}</span>`;
2118
 
2119
- return `<div class="env-card" data-row data-group="${esc(f.g)}" data-search="${esc((f.g + ' ' + f.k + ' ' + (f.lbl || '') + ' ' + (f.tag || '')).toLowerCase())}">
2120
  <div class="card-top">
2121
  <input type="checkbox" class="card-check" data-check="${esc(f.k)}" ${f.common ? 'data-common="1"' : ''}>
2122
  <div class="card-info">
@@ -2194,14 +2194,17 @@ function collect() {
2194
  return obj;
2195
  }
2196
 
2197
- function refresh() {
2198
  const obj = collect();
2199
  const keys = Object.keys(obj).sort();
2200
  const bundle = keys.length ? encodeBundle(Object.fromEntries(keys.map(k => [k, obj[k]]))) : '';
2201
-
2202
  $('bundleOut').value = bundle;
2203
  $('envLineOut').value = bundle ? `HUGGINGCLAW_ENV_BUNDLE=${bundle}` : '';
 
2204
 
 
 
 
2205
  const s = $('summary');
2206
  if (keys.length) {
2207
  s.innerHTML = `<strong>${keys.length}</strong> variable${keys.length > 1 ? 's' : ''} selected<div class="sum-keys">${keys.map(k => `<span class="sum-key">${esc(k)}</span>`).join('')}</div>`;
@@ -2379,13 +2382,24 @@ function toggleField(key) {
2379
  const chk = document.querySelector(`[data-check="${CSS.escape(key)}"]`);
2380
  if (chk) {
2381
  chk.checked = on;
 
2382
  markSelected();
2383
  }
2384
  refresh();
2385
  }
2386
 
 
 
 
 
 
 
 
 
 
 
2387
  function bindFieldEvents() {
2388
- document.querySelectorAll('[data-check]').forEach(el => el.addEventListener('change', () => { markSelected(); refresh(); }));
2389
  document.querySelectorAll('[data-key]').forEach(el => el.addEventListener('input', refresh));
2390
  document.querySelectorAll('[data-toggle]').forEach(btn => btn.addEventListener('click', () => toggleField(btn.dataset.toggle)));
2391
  document.querySelectorAll('[data-pick-for]').forEach(sel => sel.addEventListener('change', () => handlePickerChange(sel)));
@@ -2410,7 +2424,7 @@ function renderSections() {
2410
  <span class="sec-count">${items.length}</span>
2411
  <div class="sec-line"></div>
2412
  </div>
2413
- <div class="cards">${items.map(cardHTML).join('')}</div>`;
2414
  wrap.appendChild(sec);
2415
  });
2416
  bindFieldEvents();
@@ -2503,6 +2517,7 @@ $('applyBundle').onclick = () => {
2503
  showToast('Invalid bundle');
2504
  }
2505
  };
 
2506
  $('copyBundle').onclick = () => copyText($('bundleOut').value);
2507
  $('copyEnvLine').onclick = () => copyText($('envLineOut').value);
2508
  $('copyJson').onclick = () => copyText(JSON.stringify(collect(), null, 2));
 
2104
  return control;
2105
  }
2106
 
2107
+ function cardHTML(f, origIdx = 0) {
2108
  const TAG_META = {
2109
  critical: { cls: 'badge-critical', lbl: 'critical' },
2110
  credential: { cls: 'badge-credential', lbl: 'credential' },
 
2116
  const tm = TAG_META[f.tag] || TAG_META.optional;
2117
  const badge = `<span class="badge ${tm.cls}">${tm.lbl}</span>`;
2118
 
2119
+ return `<div class="env-card" data-row data-orig-idx="${origIdx}" data-group="${esc(f.g)}" data-search="${esc((f.g + ' ' + f.k + ' ' + (f.lbl || '') + ' ' + (f.tag || '')).toLowerCase())}">
2120
  <div class="card-top">
2121
  <input type="checkbox" class="card-check" data-check="${esc(f.k)}" ${f.common ? 'data-common="1"' : ''}>
2122
  <div class="card-info">
 
2194
  return obj;
2195
  }
2196
 
2197
+ function generateBundle() {
2198
  const obj = collect();
2199
  const keys = Object.keys(obj).sort();
2200
  const bundle = keys.length ? encodeBundle(Object.fromEntries(keys.map(k => [k, obj[k]]))) : '';
 
2201
  $('bundleOut').value = bundle;
2202
  $('envLineOut').value = bundle ? `HUGGINGCLAW_ENV_BUNDLE=${bundle}` : '';
2203
+ }
2204
 
2205
+ function refresh() {
2206
+ const obj = collect();
2207
+ const keys = Object.keys(obj).sort();
2208
  const s = $('summary');
2209
  if (keys.length) {
2210
  s.innerHTML = `<strong>${keys.length}</strong> variable${keys.length > 1 ? 's' : ''} selected<div class="sum-keys">${keys.map(k => `<span class="sum-key">${esc(k)}</span>`).join('')}</div>`;
 
2382
  const chk = document.querySelector(`[data-check="${CSS.escape(key)}"]`);
2383
  if (chk) {
2384
  chk.checked = on;
2385
+ sortSection(inp.closest('[data-row]'));
2386
  markSelected();
2387
  }
2388
  refresh();
2389
  }
2390
 
2391
+ function sortSection(cardEl) {
2392
+ const cards = cardEl && cardEl.closest('.cards');
2393
+ if (!cards) return;
2394
+ const all = [...cards.querySelectorAll('[data-row]')];
2395
+ const checked = all.filter(c => c.querySelector('[data-check]')?.checked);
2396
+ const rest = all.filter(c => !c.querySelector('[data-check]')?.checked);
2397
+ rest.sort((a, b) => Number(a.dataset.origIdx) - Number(b.dataset.origIdx));
2398
+ [...checked, ...rest].forEach(c => cards.appendChild(c));
2399
+ }
2400
+
2401
  function bindFieldEvents() {
2402
+ document.querySelectorAll('[data-check]').forEach(el => el.addEventListener('change', () => { sortSection(el.closest('[data-row]')); markSelected(); refresh(); }));
2403
  document.querySelectorAll('[data-key]').forEach(el => el.addEventListener('input', refresh));
2404
  document.querySelectorAll('[data-toggle]').forEach(btn => btn.addEventListener('click', () => toggleField(btn.dataset.toggle)));
2405
  document.querySelectorAll('[data-pick-for]').forEach(sel => sel.addEventListener('change', () => handlePickerChange(sel)));
 
2424
  <span class="sec-count">${items.length}</span>
2425
  <div class="sec-line"></div>
2426
  </div>
2427
+ <div class="cards">${items.map((f, i) => cardHTML(f, i)).join('')}</div>`;
2428
  wrap.appendChild(sec);
2429
  });
2430
  bindFieldEvents();
 
2517
  showToast('Invalid bundle');
2518
  }
2519
  };
2520
+ $('generateBundle').onclick = () => generateBundle();
2521
  $('copyBundle').onclick = () => copyText($('bundleOut').value);
2522
  $('copyEnvLine').onclick = () => copyText($('envLineOut').value);
2523
  $('copyJson').onclick = () => copyText(JSON.stringify(collect(), null, 2));
start.sh CHANGED
@@ -323,7 +323,7 @@ CONFIG_JSON=$(cat <<'CONFIGEOF'
323
  {
324
  "gateway": {
325
  "mode": "local",
326
- "port": 7860,
327
  "bind": "lan",
328
  "auth": {
329
  "token": ""
@@ -1653,7 +1653,7 @@ while true; do
1653
  stdbuf -oL -eL openclaw "${GATEWAY_ARGS[@]}" 2>&1 | tee -a /home/node/.openclaw/gateway.log &
1654
  GATEWAY_PID=$!
1655
 
1656
- # Poll for the gateway to start listening on 7860. OpenClaw can take 20-30s
1657
  # on cold start (plugin install + auto-restore). Bail out early if the
1658
  # pipeline died.
1659
  GATEWAY_READY_TIMEOUT="${GATEWAY_READY_TIMEOUT:-90}"
 
323
  {
324
  "gateway": {
325
  "mode": "local",
326
+ "port": "${GATEWAY_PORT}",
327
  "bind": "lan",
328
  "auth": {
329
  "token": ""
 
1653
  stdbuf -oL -eL openclaw "${GATEWAY_ARGS[@]}" 2>&1 | tee -a /home/node/.openclaw/gateway.log &
1654
  GATEWAY_PID=$!
1655
 
1656
+ # Poll for the gateway to start listening on ${GATEWAY_PORT}. OpenClaw can take 20-30s
1657
  # on cold start (plugin install + auto-restore). Bail out early if the
1658
  # pipeline died.
1659
  GATEWAY_READY_TIMEOUT="${GATEWAY_READY_TIMEOUT:-90}"