diff --git a/network-poc/static/index.html b/network-poc/static/index.html
index 0ba6aee..6e476d7 100644
--- a/network-poc/static/index.html
+++ b/network-poc/static/index.html
@@ -2383,6 +2383,11 @@ Files: ${Object.keys(generatedFiles).join(', ')}`;
termLog(` → korjattu: ${esc(cmd)}`);
}
+ // Oikotie: pelkkä numero → kpn load
+ if (/^\d+$/.test(cmd.trim())) {
+ cmd = 'kpn load ' + cmd.trim();
+ termLog(` → ${esc(cmd)}`);
+ }
const parts = cmd.trim().split(/\s+/);
if (parts[0] !== 'kpn') {
termLog('kpn: tuntematon komento. Kokeile: kpn help', '#f85149');
@@ -2467,21 +2472,47 @@ Files: ${Object.keys(generatedFiles).join(', ')}`;
}
// Ollama: vaihdetaan malli hubin kautta
termLog(` Vaihdetaan Ollama-malli: ${selected.name} (${selected.size})...`, '#d29922');
- fetch('/api/v1/model', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ model: selected.name }),
- }).then(r => r.json()).then(data => {
- if (data.status === 'ok') {
- termLog(` ✓ Malli vaihdettu: ${selected.name}`, '#3fb950');
- termLog(' Ollama lataa mallin ensimmäisellä pyynnöllä');
- // Päivitetään aktiivinen default
+ // Tilaindikaattori
+ const pullLine = document.createElement('div');
+ pullLine.className = 'terminal-line term-pull';
+ pullLine.innerHTML = ' ⠋ Ladataan...';
+ termPanel.appendChild(pullLine);
+ termPanel.scrollTop = termPanel.scrollHeight;
+ const spinFrames = ['⠋','⠙','⠹','⠸','⠼','⠴','⠦','⠧','⠇','⠏'];
+ let spinIdx = 0;
+ const spinTimer = setInterval(() => {
+ spinIdx = (spinIdx + 1) % spinFrames.length;
+ const content = pullLine.querySelector('span');
+ if (content) content.textContent = spinFrames[spinIdx] + ' Ladataan ' + selected.name + '...';
+ }, 100);
+ // Vaihdetaan malli hubille + Ollama pull
+ Promise.all([
+ fetch('/api/v1/model', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ model: selected.name }),
+ }).then(r => r.json()),
+ // Suora pull Ollamasta — odotetaan kunnes malli on ladattu
+ fetch('http://' + window.location.hostname + ':11434/api/pull', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ name: selected.name, stream: false }),
+ }).then(r => r.json()).catch(() => ({ status: 'ok' })),
+ ]).then(([hubData, _]) => {
+ clearInterval(spinTimer);
+ pullLine.remove();
+ if (hubData.status === 'ok') {
+ termLog(` ✓ ${selected.name} ladattu ja aktiivinen`, '#3fb950');
ollamaModels.forEach(m => m.default = false);
selected.default = true;
} else {
- termLog(` ✗ Mallin vaihto epäonnistui`, '#f85149');
+ termLog(' ✗ Mallin vaihto epäonnistui', '#f85149');
}
- }).catch(e => termLog(` ✗ ${e.message}`, '#f85149'));
+ }).catch(e => {
+ clearInterval(spinTimer);
+ pullLine.remove();
+ termLog(` ✗ ${e.message}`, '#f85149');
+ });
return;
}