Spaces:
Running
Running
Anurag commited on
Commit Β·
afd41e0
1
Parent(s): c808e75
Fix startup/env-builder provider mapping and rendering regressions
Browse files- env-builder.html +0 -15
- env-builder.js +62 -50
- health-server.js +7 -3
- 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": "
|
| 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": "
|
| 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": "
|
| 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 => {
|
|
|
|
|
|
|
|
|
|
| 2422 |
|
| 2423 |
const wrap = $('sections');
|
|
|
|
| 2424 |
wrap.innerHTML = '';
|
| 2425 |
Object.entries(grouped).forEach(([grp, items]) => {
|
| 2426 |
-
|
| 2427 |
-
|
| 2428 |
-
|
| 2429 |
-
|
| 2430 |
-
|
| 2431 |
-
<
|
| 2432 |
-
|
| 2433 |
-
|
| 2434 |
-
|
| 2435 |
-
|
| 2436 |
-
|
| 2437 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2438 |
});
|
| 2439 |
bindFieldEvents();
|
| 2440 |
}
|
|
@@ -2457,11 +2463,17 @@ function copyText(text) {
|
|
| 2457 |
}
|
| 2458 |
|
| 2459 |
// ββ Init ββ
|
| 2460 |
-
|
| 2461 |
-
|
| 2462 |
-
|
| 2463 |
-
|
| 2464 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 28 |
-
|
|
|
|
|
|
|
|
|
|
| 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
|
| 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"
|