diff --git a/packages/dashboard/index.html b/packages/dashboard/index.html
index b98b52d..b82a8f3 100644
--- a/packages/dashboard/index.html
+++ b/packages/dashboard/index.html
@@ -1691,7 +1691,7 @@
-
+
@@ -1704,7 +1704,7 @@
-
+
@@ -6602,14 +6602,16 @@ async function loadSelflearning() {
var manifest = d.manifest || null;
renderSelflearningLane('tip_llm', manifest && manifest.lanes && manifest.lanes.tip_llm, d.lanes && d.lanes.tip_llm);
renderSelflearningLane('blog_llm', manifest && manifest.lanes && manifest.lanes.blog_llm, d.lanes && d.lanes.blog_llm);
+ var localReady = !!(d.local && d.local.ready);
+ _updateLocalTrainButtons(localReady);
if (banner) {
var parts = [
- 'RunPod Endpoint: ' + (d.runpod && d.runpod.endpoint_configured ? 'ok' : 'fehlt'),
- 'RunPod API: ' + (d.runpod && d.runpod.api_key_configured ? 'ok' : 'fehlt'),
- 'HF Token: ' + (d.huggingface && d.huggingface.token_configured ? 'ok' : 'fehlt'),
- 'Local: ' + (d.local && d.local.ready ? 'konfiguriert' : 'noch kein TIP_LOCAL_TRAIN_COMMAND')
+ 'RunPod Endpoint: ' + (d.runpod && d.runpod.endpoint_configured ? '✓ ok' : '✗ fehlt'),
+ 'RunPod API: ' + (d.runpod && d.runpod.api_key_configured ? '✓ ok' : '✗ fehlt'),
+ 'HF Token: ' + (d.huggingface && d.huggingface.token_configured ? '✓ ok' : '✗ fehlt'),
+ 'Local: ' + (localReady ? '✓ konfiguriert' : '✗ kein TIP_LOCAL_TRAIN_COMMAND')
];
- banner.innerHTML = 'Status: ' + parts.map(esc).join(' · ')
+ banner.innerHTML = 'Status: ' + parts.join(' · ')
+ (manifest ? '
Manifest: ' + esc(manifest.version || '-') + ' · ' + esc(manifest.generated_at || '-') + '' : '
Noch kein Manifest vorhanden.');
}
} catch(e) {
@@ -6648,9 +6650,44 @@ async function publishSelflearningHF() {
}
}
+var _slLocalReady = false;
+
+function _updateLocalTrainButtons(ready) {
+ _slLocalReady = ready;
+ ['tip', 'blog'].forEach(function(lane) {
+ var btn = el('sl-local-btn-' + lane);
+ if (!btn) return;
+ if (ready) {
+ btn.disabled = false;
+ btn.style.cursor = 'pointer';
+ btn.style.opacity = '1';
+ btn.style.color = 'var(--text)';
+ btn.title = 'Lokales Training starten';
+ } else {
+ btn.disabled = true;
+ btn.style.cursor = 'not-allowed';
+ btn.style.opacity = '0.45';
+ btn.style.color = 'var(--text-dim)';
+ btn.title = 'Nicht konfiguriert — setze TIP_LOCAL_TRAIN_COMMAND in ecosystem.config.js';
+ }
+ });
+}
+
async function startSelflearningTrain(lane, provider, seedOnly) {
+ if (provider === 'local' && !_slLocalReady) {
+ setSelflearningLog(
+ 'Lokales Training ist nicht konfiguriert.\n\n' +
+ 'Setze TIP_LOCAL_TRAIN_COMMAND in /opt/tip/ecosystem.config.js:\n' +
+ ' TIP_LOCAL_TRAIN_COMMAND: \'/opt/tip/scripts/local-train.sh\'\n\n' +
+ 'Das Script wird aufgerufen als:\n' +
+ ' /opt/tip/scripts/local-train.sh tip_llm\n' +
+ ' /opt/tip/scripts/local-train.sh blog_llm'
+ );
+ showToast('Local Train nicht aktiv', 'TIP_LOCAL_TRAIN_COMMAND ist nicht konfiguriert.', true);
+ return;
+ }
var label = lane + ' / ' + provider + (seedOnly ? ' / seed' : ' / full');
- setSelflearningLog('Training Start: ' + label);
+ setSelflearningLog('Training Start: ' + label + ' …');
try {
var d = await api('/api/selflearning/train', {
method: 'POST',