Spaces:
Running on Zero
Running on Zero
update UI [toastify NCII]
Browse files- index.html +36 -3
index.html
CHANGED
|
@@ -1317,6 +1317,21 @@ function setRunningUI(on) {
|
|
| 1317 |
cancelBtn.style.display = on ? 'flex' : 'none';
|
| 1318 |
}
|
| 1319 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1320 |
async function runEdit() {
|
| 1321 |
if (running) return;
|
| 1322 |
if (!client) { showToast('Backend not connected', 'error'); return; }
|
|
@@ -1324,10 +1339,23 @@ async function runEdit() {
|
|
| 1324 |
|
| 1325 |
setRunningUI(true);
|
| 1326 |
setViewMode('result');
|
| 1327 |
-
showLoader('
|
| 1328 |
|
| 1329 |
-
const beforeB64 = images[0] ? images[0].b64 : null;
|
| 1330 |
const usedPrompt = promptInput.value;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1331 |
const usedLora = loraSelect.value;
|
| 1332 |
|
| 1333 |
const payload = {
|
|
@@ -1379,6 +1407,11 @@ async function runEdit() {
|
|
| 1379 |
}
|
| 1380 |
hideLoader('Done', 'done');
|
| 1381 |
showToast('Image edited successfully', 'info');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1382 |
} else {
|
| 1383 |
hideLoader('Done', 'done');
|
| 1384 |
}
|
|
@@ -1420,4 +1453,4 @@ updateCounts();
|
|
| 1420 |
renderCanvas();
|
| 1421 |
</script>
|
| 1422 |
</body>
|
| 1423 |
-
</html>
|
|
|
|
| 1317 |
cancelBtn.style.display = on ? 'flex' : 'none';
|
| 1318 |
}
|
| 1319 |
|
| 1320 |
+
/* Pre-flight: ask the pure-CPU endpoint whether the prompt is safe.
|
| 1321 |
+
This happens BEFORE submitting to /edit_image, so no GPU resource
|
| 1322 |
+
is ever queued for an unsafe prompt. */
|
| 1323 |
+
async function checkPromptSafety(prompt) {
|
| 1324 |
+
if (!client) return { status: 'ok' };
|
| 1325 |
+
try {
|
| 1326 |
+
const result = await client.predict('/check_safety', { prompt });
|
| 1327 |
+
const data = result.data && result.data[0];
|
| 1328 |
+
return data || { status: 'ok' };
|
| 1329 |
+
} catch (e) {
|
| 1330 |
+
console.warn('Safety check failed, proceeding optimistically:', e);
|
| 1331 |
+
return { status: 'ok' };
|
| 1332 |
+
}
|
| 1333 |
+
}
|
| 1334 |
+
|
| 1335 |
async function runEdit() {
|
| 1336 |
if (running) return;
|
| 1337 |
if (!client) { showToast('Backend not connected', 'error'); return; }
|
|
|
|
| 1339 |
|
| 1340 |
setRunningUI(true);
|
| 1341 |
setViewMode('result');
|
| 1342 |
+
showLoader('Checking prompt safety…');
|
| 1343 |
|
|
|
|
| 1344 |
const usedPrompt = promptInput.value;
|
| 1345 |
+
|
| 1346 |
+
/* ── Step 1: CPU-only safety gate (no GPU requested yet) ── */
|
| 1347 |
+
const safety = await checkPromptSafety(usedPrompt);
|
| 1348 |
+
if (safety && safety.status === 'blocked') {
|
| 1349 |
+
hideLoader('Blocked', 'error');
|
| 1350 |
+
showToast(safety.message || 'Request blocked by safety guard', 'warning');
|
| 1351 |
+
flashPromptError();
|
| 1352 |
+
setRunningUI(false);
|
| 1353 |
+
return;
|
| 1354 |
+
}
|
| 1355 |
+
|
| 1356 |
+
/* ── Step 2: Only now do we ask the GPU worker to run ── */
|
| 1357 |
+
showLoader('Submitting to queue…');
|
| 1358 |
+
const beforeB64 = images[0] ? images[0].b64 : null;
|
| 1359 |
const usedLora = loraSelect.value;
|
| 1360 |
|
| 1361 |
const payload = {
|
|
|
|
| 1407 |
}
|
| 1408 |
hideLoader('Done', 'done');
|
| 1409 |
showToast('Image edited successfully', 'info');
|
| 1410 |
+
} else if (out && out.status === 'blocked') {
|
| 1411 |
+
/* Defense-in-depth re-check inside the GPU worker triggered */
|
| 1412 |
+
hideLoader('Blocked', 'error');
|
| 1413 |
+
showToast(out.message || 'Request blocked by safety guard', 'warning');
|
| 1414 |
+
flashPromptError();
|
| 1415 |
} else {
|
| 1416 |
hideLoader('Done', 'done');
|
| 1417 |
}
|
|
|
|
| 1453 |
renderCanvas();
|
| 1454 |
</script>
|
| 1455 |
</body>
|
| 1456 |
+
</html>
|