Fix HF dataset import internal error and training SQLite readiness.

Wrap AssistentImportHfDataset in try/catch, batch inserts in a transaction, clearer HF rows errors for gated datasets, EnsureTrainingReady with actionable message, and friendlier training UI errors instead of generic internal error.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Leonid Pershin
2026-08-23 20:11:18 +03:00
co-authored by Cursor
parent b0f2736f65
commit 63538fe738
9 changed files with 323 additions and 155 deletions
+25 -12
View File
@@ -10708,7 +10708,7 @@ ${HELP_TEXT}`);
setAgentHeardStats(state.agentLinked);
} catch (e) {
const msg = String(e.message || e);
setTrainStatus(isSqliteError(msg) ? `${msg} \u2014 ${sqliteHint()}` : msg);
setTrainStatus(formatTrainError(msg));
console.warn("loadAgentHeardSettings", e);
}
}
@@ -10723,7 +10723,7 @@ ${HELP_TEXT}`);
state.agentSettings = data?.settings || settings;
setTrainStatus("\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438 \xAB\u0443\u0441\u043B\u044B\u0448\u0430\u043D\u043D\u043E\u0433\u043E\xBB \u0441\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u044B");
} catch (e) {
setTrainStatus(String(e.message || e));
setTrainStatus(formatTrainError(e.message || e));
}
}
async function syncAllToAgent() {
@@ -10736,7 +10736,7 @@ ${HELP_TEXT}`);
setTrainStatus(`\u041F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u043E: +${data?.linked_now ?? 0}, \u0432\u0441\u0435\u0433\u043E ${data?.total_linked ?? "\u2014"}`);
await refreshSamples();
} catch (e) {
setTrainStatus(String(e.message || e));
setTrainStatus(formatTrainError(e.message || e));
}
}
function setTrainStatus(msg) {
@@ -10745,7 +10745,20 @@ ${HELP_TEXT}`);
}
function isSqliteError(msg) {
const s = String(msg || "").toLowerCase();
return s.includes("sqlite") || s.includes("sqlconnection");
return s.includes("sqlite") || s.includes("sqlconnection") || s.includes("train_samples") || s.includes("training database unavailable");
}
function isGenericServerError(msg) {
return /internal error occurred/i.test(String(msg || ""));
}
function formatTrainError(msg) {
const s = String(msg || "");
if (isSqliteError(s)) {
return `${s} \u2014 ${sqliteHint()}`;
}
if (isGenericServerError(s)) {
return `${s} \u2014 \u0447\u0430\u0441\u0442\u043E SQLite/\u0438\u043C\u043F\u043E\u0440\u0442 HF: gpu-rent seed-extensions, restart SwarmUI, HF token \u0434\u043B\u044F gated.`;
}
return s;
}
function sqliteHint() {
return "\u0411\u0430\u0437\u0430 Assistent (SQLite) \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0430 \u2014 gpu-rent seed-extensions + restart SwarmUI (\u22650.15.6).";
@@ -10816,7 +10829,7 @@ ${HELP_TEXT}`);
const data = await SA2.request("AssistentListTrainSamples", { status, persona, limit: 300 });
if (data?.error) {
const msg = data.error;
setTrainStatus(isSqliteError(msg) ? `${msg} \u2014 ${sqliteHint()}` : msg);
setTrainStatus(formatTrainError(msg));
const stats2 = $("sa_train_stats");
if (stats2) stats2.textContent = "\u0414\u0430\u0442\u0430\u0441\u0435\u0442 \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D (SQLite)";
state.samples = [];
@@ -10845,7 +10858,7 @@ ${HELP_TEXT}`);
}
renderSamples();
} catch (e) {
setTrainStatus(String(e.message || e));
setTrainStatus(formatTrainError(e.message || e));
}
}
function renderSamples() {
@@ -11073,7 +11086,7 @@ ${HELP_TEXT}`);
renderHfList();
setTrainStatus(`\u041D\u0430\u0439\u0434\u0435\u043D\u043E: ${state.hfResults.length}`);
} catch (e) {
setTrainStatus(String(e.message || e));
setTrainStatus(formatTrainError(e.message || e));
}
}
async function checkHfLink() {
@@ -11148,7 +11161,7 @@ ${HELP_TEXT}`);
$("sa_train_samples")?.scrollIntoView({ behavior: "smooth", block: "nearest" });
} catch (e) {
const err = String(e.message || e);
const show = isSqliteError(err) ? `${err} \u2014 ${sqliteHint()}` : err;
const show = formatTrainError(err);
setTrainStatus(show);
if (hfSt) hfSt.textContent = show;
} finally {
@@ -11203,7 +11216,7 @@ ${HELP_TEXT}`);
setTrainStatus(`\u0413\u043E\u0442\u043E\u0432\u043E: ${data.name}`);
SA2.app?.refreshModels?.();
} catch (e) {
setTrainStatus(String(e.message || e));
setTrainStatus(formatTrainError(e.message || e));
} finally {
btn?.removeAttribute("disabled");
}
@@ -11328,7 +11341,7 @@ ${HELP_TEXT}`);
setTrainingTab("train");
setTrainStatus("QLoRA \u0437\u0430\u043F\u0443\u0449\u0435\u043D\u0430 \u2014 \u043F\u0440\u043E\u0433\u0440\u0435\u0441\u0441 \u043D\u0438\u0436\u0435");
} catch (e) {
setTrainStatus(String(e.message || e));
setTrainStatus(formatTrainError(e.message || e));
}
}
async function cancelQlora() {
@@ -11337,7 +11350,7 @@ ${HELP_TEXT}`);
setTrainingLock(false);
setTrainStatus("\u041E\u0442\u043C\u0435\u043D\u0435\u043D\u043E");
} catch (e) {
setTrainStatus(String(e.message || e));
setTrainStatus(formatTrainError(e.message || e));
}
}
async function refreshTrainModels() {
@@ -11371,7 +11384,7 @@ ${HELP_TEXT}`);
});
setTrainStatus("\u0420\u0430\u043D\u043D\u0435\u0440 \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D");
} catch (e) {
setTrainStatus(String(e.message || e));
setTrainStatus(formatTrainError(e.message || e));
}
}
async function loadRunner() {