Anurag commited on
Commit
4db8e05
Β·
unverified Β·
2 Parent(s): c808e75afd41e0

Fix startup crash, provider key mapping, Jupyter gating, and ENV Builder rendering

Browse files
Files changed (4) hide show
  1. env-builder.html +0 -15
  2. env-builder.js +62 -50
  3. health-server.js +7 -3
  4. start.sh +12 -1
env-builder.html CHANGED
@@ -901,21 +901,6 @@ body {
901
  <aside class="right-panel">
902
  <div class="panel-scroll">
903
 
904
- <!-- Summary -->
905
- <div class="pblock">
906
- <div class="pblock-head">
907
- <span class="pblock-title">🧭 Quick Guide</span>
908
- </div>
909
- <div class="pblock-body">
910
- <ol class="quick-guide">
911
- <li>Click <strong>⚑ Required</strong> to select must-have vars.</li>
912
- <li>Fill values in selected cards (search works by key/tag/group).</li>
913
- <li>Click <strong># Generate Bundle</strong> and copy Bundle/Env line.</li>
914
- <li>Paste into HF Space variables or use <strong>↓ Import & Apply</strong>.</li>
915
- </ol>
916
- </div>
917
- </div>
918
-
919
  <div class="pblock">
920
  <div class="pblock-head">
921
  <span class="pblock-title">πŸ“Š Summary</span>
 
901
  <aside class="right-panel">
902
  <div class="panel-scroll">
903
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
904
  <div class="pblock">
905
  <div class="pblock-head">
906
  <span class="pblock-title">πŸ“Š Summary</span>
env-builder.js CHANGED
@@ -54,25 +54,25 @@ const MODEL_CATALOGS = {
54
  "Groq": [
55
  "groq/compound",
56
  "groq/compound-mini",
57
- "llama-3.1-8b-instant",
58
- "llama-3.1-70b-versatile",
59
- "llama-3.3-70b-versatile",
60
  "meta-llama/llama-4-scout-17b-16e-instruct",
61
  "openai/gpt-oss-20b",
62
  "openai/gpt-oss-120b",
63
  "qwen/qwen3-32b",
64
- "mixtral-8x7b-32768"
65
  ],
66
  "Mistral": [
67
- "mistral-large-latest",
68
- "mistral-large-2",
69
- "mistral-medium-3.5",
70
- "mistral-small-latest",
71
- "mistral-small-3.2",
72
- "devstral-2",
73
- "ocr-3-premier",
74
- "voxtral-mini-transcribe-realtime",
75
- "codestral-latest"
76
  ],
77
  "Cohere": [
78
  "command-a",
@@ -280,25 +280,25 @@ const MODEL_CATALOGS = {
280
  "GROQ_MODELS": [
281
  "groq/compound",
282
  "groq/compound-mini",
283
- "llama-3.1-8b-instant",
284
- "llama-3.1-70b-versatile",
285
- "llama-3.3-70b-versatile",
286
  "openai/gpt-oss-20b",
287
  "openai/gpt-oss-120b",
288
  "meta-llama/llama-4-scout-17b-16e-instruct",
289
  "qwen/qwen3-32b",
290
- "mixtral-8x7b-32768"
291
  ],
292
  "MISTRAL_MODELS": [
293
- "mistral-large-latest",
294
- "mistral-large-2",
295
- "mistral-medium-3.5",
296
- "mistral-small-latest",
297
- "mistral-small-3.2",
298
- "devstral-2",
299
- "ocr-3-premier",
300
- "voxtral-mini-transcribe-realtime",
301
- "codestral-latest"
302
  ],
303
  "XAI_MODELS": [
304
  "grok-4.3",
@@ -421,8 +421,7 @@ const FIELDS = [
421
  "icon": "⚑",
422
  "k": "LLM_MODEL",
423
  "lbl": "Default model ID",
424
- "type": "model",
425
- "options_key": "LLM_MODEL",
426
  "ph": "choose a provider model",
427
  "common": 1,
428
  "tag": "critical"
@@ -1680,8 +1679,7 @@ const FIELDS = [
1680
  "icon": "πŸ”Œ",
1681
  "k": "CUSTOM_MODEL_ID",
1682
  "lbl": "Model ID",
1683
- "type": "model",
1684
- "options_key": "LLM_MODEL",
1685
  "ph": "custom model id",
1686
  "tag": "feature"
1687
  },
@@ -1732,7 +1730,7 @@ const FIELDS = [
1732
  "k": "CUSTOM_MAX_TOKENS",
1733
  "lbl": "Max output tokens",
1734
  "type": "number",
1735
- "ph": "500",
1736
  "tag": "advanced"
1737
  },
1738
  {
@@ -2061,6 +2059,7 @@ function defaultValueFor(field) {
2061
  }
2062
 
2063
  function valueControlHTML(field) {
 
2064
  const key = esc(field.k);
2065
  const placeholder = esc(field.ph || field.lbl || '');
2066
  const isSecret = !!field.secret;
@@ -2100,7 +2099,6 @@ function valueControlHTML(field) {
2100
  ${control}
2101
  </div>`;
2102
 
2103
- return control;
2104
  }
2105
 
2106
  function cardHTML(f, origIdx = 0) {
@@ -2418,23 +2416,31 @@ function bindFieldEvents() {
2418
 
2419
  function renderSections() {
2420
  const grouped = {};
2421
- FIELDS.forEach(f => { (grouped[f.g] ||= []).push(f); });
 
 
 
2422
 
2423
  const wrap = $('sections');
 
2424
  wrap.innerHTML = '';
2425
  Object.entries(grouped).forEach(([grp, items]) => {
2426
- const sec = document.createElement('div');
2427
- sec.className = 'sec';
2428
- sec.dataset.section = grp;
2429
- sec.innerHTML = `
2430
- <div class="sec-header">
2431
- <span class="sec-icon">${ICONS[grp] || 'πŸ“'}</span>
2432
- <span class="sec-title">${esc(grp)}</span>
2433
- <span class="sec-count">${items.length}</span>
2434
- <div class="sec-line"></div>
2435
- </div>
2436
- <div class="cards">${items.map((f, i) => cardHTML(f, i)).join('')}</div>`;
2437
- wrap.appendChild(sec);
 
 
 
 
2438
  });
2439
  bindFieldEvents();
2440
  }
@@ -2457,11 +2463,17 @@ function copyText(text) {
2457
  }
2458
 
2459
  // ── Init ──
2460
- renderSidebar();
2461
- renderSections();
2462
- addCustomRow();
2463
- filter();
2464
- refresh();
 
 
 
 
 
 
2465
 
2466
  // ── Events ──
2467
  $('search').oninput = filter;
 
54
  "Groq": [
55
  "groq/compound",
56
  "groq/compound-mini",
57
+ "groq/llama-3.1-8b-instant",
58
+ "groq/llama-3.1-70b-versatile",
59
+ "groq/llama-3.3-70b-versatile",
60
  "meta-llama/llama-4-scout-17b-16e-instruct",
61
  "openai/gpt-oss-20b",
62
  "openai/gpt-oss-120b",
63
  "qwen/qwen3-32b",
64
+ "groq/mixtral-8x7b-32768"
65
  ],
66
  "Mistral": [
67
+ "mistral/mistral-large-latest",
68
+ "mistral/mistral-large-2",
69
+ "mistral/mistral-medium-3.5",
70
+ "mistral/mistral-small-latest",
71
+ "mistral/mistral-small-3.2",
72
+ "mistral/devstral-2",
73
+ "mistral/ocr-3-premier",
74
+ "mistral/voxtral-mini-transcribe-realtime",
75
+ "mistral/codestral-latest"
76
  ],
77
  "Cohere": [
78
  "command-a",
 
280
  "GROQ_MODELS": [
281
  "groq/compound",
282
  "groq/compound-mini",
283
+ "groq/llama-3.1-8b-instant",
284
+ "groq/llama-3.1-70b-versatile",
285
+ "groq/llama-3.3-70b-versatile",
286
  "openai/gpt-oss-20b",
287
  "openai/gpt-oss-120b",
288
  "meta-llama/llama-4-scout-17b-16e-instruct",
289
  "qwen/qwen3-32b",
290
+ "groq/mixtral-8x7b-32768"
291
  ],
292
  "MISTRAL_MODELS": [
293
+ "mistral/mistral-large-latest",
294
+ "mistral/mistral-large-2",
295
+ "mistral/mistral-medium-3.5",
296
+ "mistral/mistral-small-latest",
297
+ "mistral/mistral-small-3.2",
298
+ "mistral/devstral-2",
299
+ "mistral/ocr-3-premier",
300
+ "mistral/voxtral-mini-transcribe-realtime",
301
+ "mistral/codestral-latest"
302
  ],
303
  "XAI_MODELS": [
304
  "grok-4.3",
 
421
  "icon": "⚑",
422
  "k": "LLM_MODEL",
423
  "lbl": "Default model ID",
424
+ "type": "text",
 
425
  "ph": "choose a provider model",
426
  "common": 1,
427
  "tag": "critical"
 
1679
  "icon": "πŸ”Œ",
1680
  "k": "CUSTOM_MODEL_ID",
1681
  "lbl": "Model ID",
1682
+ "type": "text",
 
1683
  "ph": "custom model id",
1684
  "tag": "feature"
1685
  },
 
1730
  "k": "CUSTOM_MAX_TOKENS",
1731
  "lbl": "Max output tokens",
1732
  "type": "number",
1733
+ "ph": "8192",
1734
  "tag": "advanced"
1735
  },
1736
  {
 
2059
  }
2060
 
2061
  function valueControlHTML(field) {
2062
+ if (!field || !field.k) return '<span style="color:red">Invalid field</span>';
2063
  const key = esc(field.k);
2064
  const placeholder = esc(field.ph || field.lbl || '');
2065
  const isSecret = !!field.secret;
 
2099
  ${control}
2100
  </div>`;
2101
 
 
2102
  }
2103
 
2104
  function cardHTML(f, origIdx = 0) {
 
2416
 
2417
  function renderSections() {
2418
  const grouped = {};
2419
+ FIELDS.forEach(f => {
2420
+ if (!f || !f.g || !f.k) return;
2421
+ (grouped[f.g] ||= []).push(f);
2422
+ });
2423
 
2424
  const wrap = $('sections');
2425
+ if (!wrap) return;
2426
  wrap.innerHTML = '';
2427
  Object.entries(grouped).forEach(([grp, items]) => {
2428
+ try {
2429
+ const sec = document.createElement('div');
2430
+ sec.className = 'sec';
2431
+ sec.dataset.section = grp;
2432
+ sec.innerHTML = `
2433
+ <div class="sec-header">
2434
+ <span class="sec-icon">${ICONS[grp] || 'πŸ“'}</span>
2435
+ <span class="sec-title">${esc(grp)}</span>
2436
+ <span class="sec-count">${items.length}</span>
2437
+ <div class="sec-line"></div>
2438
+ </div>
2439
+ <div class="cards">${items.map((f, i) => { try { return cardHTML(f, i); } catch(e) { console.error('cardHTML error for field', f.k, e); return ''; } }).join('')}</div>`;
2440
+ wrap.appendChild(sec);
2441
+ } catch(e) {
2442
+ console.error('renderSections error for group', grp, e);
2443
+ }
2444
  });
2445
  bindFieldEvents();
2446
  }
 
2463
  }
2464
 
2465
  // ── Init ──
2466
+ try {
2467
+ renderSidebar();
2468
+ renderSections();
2469
+ addCustomRow();
2470
+ filter();
2471
+ refresh();
2472
+ } catch(e) {
2473
+ console.error('HuggingClaw ENV Builder init error:', e);
2474
+ const wrap = document.getElementById('sections');
2475
+ if (wrap) wrap.innerHTML = '<div style="color:red;padding:20px">ENV Builder failed to load. Open browser console for details. Error: ' + e.message + '</div>';
2476
+ }
2477
 
2478
  // ── Events ──
2479
  $('search').oninput = filter;
health-server.js CHANGED
@@ -23,9 +23,13 @@ const JUPYTER_BASE = normalizeBase(process.env.JUPYTER_BASE, "/terminal");
23
  const GATEWAY_TOKEN = (process.env.GATEWAY_TOKEN || "").trim();
24
  const DEV_MODE_ENABLED = isTrue(process.env.DEV_MODE);
25
  // Default true. Only false when DEV_MODE=false or HUGGINGCLAW_JUPYTER_ENABLED=false is explicitly set.
 
26
  const JUPYTER_ENABLED =
27
- !/^(false|0|no|off)$/i.test(String(process.env.DEV_MODE || "").trim()) &&
28
- !/^(false|0|no|off)$/i.test(String(process.env.HUGGINGCLAW_JUPYTER_ENABLED || "").trim());
 
 
 
29
  const startTime = Date.now();
30
  const LLM_MODEL = process.env.LLM_MODEL || "Not Set";
31
  const LLM_PROVIDER = LLM_MODEL.includes("/") ? LLM_MODEL.split("/")[0] : "";
@@ -100,7 +104,7 @@ async function detectSpacePrivacy() {
100
  return;
101
  }
102
 
103
- const token = (process.env.HF_TOKEN || "").trim();
104
  const reqOptions = {
105
  hostname: "huggingface.co",
106
  path: `/api/spaces/${SPACE_ID}`,
 
23
  const GATEWAY_TOKEN = (process.env.GATEWAY_TOKEN || "").trim();
24
  const DEV_MODE_ENABLED = isTrue(process.env.DEV_MODE);
25
  // Default true. Only false when DEV_MODE=false or HUGGINGCLAW_JUPYTER_ENABLED=false is explicitly set.
26
+ // HUGGINGCLAW_JUPYTER_ENABLED=true is the explicit user override and always wins.
27
  const JUPYTER_ENABLED =
28
+ /^(true|1|yes|on)$/i.test(String(process.env.HUGGINGCLAW_JUPYTER_ENABLED || "").trim()) ||
29
+ (
30
+ !/^(false|0|no|off)$/i.test(String(process.env.DEV_MODE || "").trim()) &&
31
+ !/^(false|0|no|off)$/i.test(String(process.env.HUGGINGCLAW_JUPYTER_ENABLED || "").trim())
32
+ );
33
  const startTime = Date.now();
34
  const LLM_MODEL = process.env.LLM_MODEL || "Not Set";
35
  const LLM_PROVIDER = LLM_MODEL.includes("/") ? LLM_MODEL.split("/")[0] : "";
 
104
  return;
105
  }
106
 
107
+ const token = (process.env.HF_TOKEN || process.env.HUGGINGFACE_HUB_TOKEN || "").trim();
108
  const reqOptions = {
109
  hostname: "huggingface.co",
110
  path: `/api/spaces/${SPACE_ID}`,
start.sh CHANGED
@@ -214,8 +214,18 @@ case "$LLM_PROVIDER" in
214
  venice) export VENICE_API_KEY="$LLM_API_KEY" ;;
215
  synthetic) export SYNTHETIC_API_KEY="$LLM_API_KEY" ;;
216
  github-copilot) export COPILOT_GITHUB_TOKEN="$LLM_API_KEY" ;;
 
 
 
 
 
 
 
 
 
217
  # ── Fallback: Anthropic (default) ──
218
  *)
 
219
  export ANTHROPIC_API_KEY="$LLM_API_KEY"
220
  ;;
221
  esac
@@ -553,6 +563,7 @@ ensure_chromium_for_browser_plugin() {
553
  echo "ERROR: Browser plugin is enabled, but Chromium install failed. Disable browser plugin or rebuild image with Chromium preinstalled." >&2
554
  return 1
555
  }
 
556
  ensure_chromium_for_browser_plugin || HC_STARTUP_FAILURES=$((HC_STARTUP_FAILURES + 1))
557
 
558
  # On Debian/Ubuntu, /usr/bin/chromium is often a shell wrapper while the real
@@ -1374,7 +1385,7 @@ fi
1374
  # Runs user-provided boot commands one by one so failures are visible in logs.
1375
  # By default failures are logged and boot continues; set
1376
  # HUGGINGCLAW_STARTUP_STRICT=true to fail the Space startup on any error.
1377
- HC_STARTUP_FAILURES=0
1378
  HC_STARTUP_STRICT_NORMALIZED=$(printf '%s' "${HUGGINGCLAW_STARTUP_STRICT:-false}" | tr '[:upper:]' '[:lower:]')
1379
  hc_run_startup_command() {
1380
  local source_label="$1"
 
214
  venice) export VENICE_API_KEY="$LLM_API_KEY" ;;
215
  synthetic) export SYNTHETIC_API_KEY="$LLM_API_KEY" ;;
216
  github-copilot) export COPILOT_GITHUB_TOKEN="$LLM_API_KEY" ;;
217
+ llama-3.*|llama-4.*|mixtral-*|gemma-*)
218
+ export GROQ_API_KEY="$LLM_API_KEY"
219
+ echo "Note: bare Groq model '$LLM_MODEL' detected; mapped LLM_API_KEY β†’ GROQ_API_KEY. Use 'groq/${LLM_MODEL}' prefix to be explicit." ;;
220
+ mistral-*|codestral-*|devstral-*|voxtral-*)
221
+ export MISTRAL_API_KEY="$LLM_API_KEY"
222
+ echo "Note: bare Mistral model '$LLM_MODEL' detected; mapped LLM_API_KEY β†’ MISTRAL_API_KEY. Use 'mistral/${LLM_MODEL}' prefix to be explicit." ;;
223
+ moonshotai|meta-llama|deepseek-ai|MiniMaxAI|minimax-ai|Qwen|zai-org|mistralai|google)
224
+ echo "Warning: LLM_MODEL='$LLM_MODEL' uses sub-provider prefix '$LLM_PROVIDER'. This is a router-namespaced model (Together/OpenRouter). Mapping LLM_API_KEY β†’ TOGETHER_API_KEY. If using OpenRouter, also set OPENROUTER_API_KEY as a separate secret."
225
+ export TOGETHER_API_KEY="${TOGETHER_API_KEY:-$LLM_API_KEY}" ;;
226
  # ── Fallback: Anthropic (default) ──
227
  *)
228
+ echo "Warning: Unknown provider prefix '$LLM_PROVIDER' in LLM_MODEL='$LLM_MODEL'. Defaulting to ANTHROPIC_API_KEY. If using a router-namespaced model (e.g. moonshotai/Kimi-K2.5), set TOGETHER_API_KEY or OPENROUTER_API_KEY as a separate secret."
229
  export ANTHROPIC_API_KEY="$LLM_API_KEY"
230
  ;;
231
  esac
 
563
  echo "ERROR: Browser plugin is enabled, but Chromium install failed. Disable browser plugin or rebuild image with Chromium preinstalled." >&2
564
  return 1
565
  }
566
+ HC_STARTUP_FAILURES=0
567
  ensure_chromium_for_browser_plugin || HC_STARTUP_FAILURES=$((HC_STARTUP_FAILURES + 1))
568
 
569
  # On Debian/Ubuntu, /usr/bin/chromium is often a shell wrapper while the real
 
1385
  # Runs user-provided boot commands one by one so failures are visible in logs.
1386
  # By default failures are logged and boot continues; set
1387
  # HUGGINGCLAW_STARTUP_STRICT=true to fail the Space startup on any error.
1388
+ # HC_STARTUP_FAILURES initialized earlier (before Chromium ensure check)
1389
  HC_STARTUP_STRICT_NORMALIZED=$(printf '%s' "${HUGGINGCLAW_STARTUP_STRICT:-false}" | tr '[:upper:]' '[:lower:]')
1390
  hc_run_startup_command() {
1391
  local source_label="$1"