Ferrell Synthetic Intelligence commited on
Commit
05d169b
·
1 Parent(s): 2d4ed0b

Add local model pack import manager

Browse files
Files changed (2) hide show
  1. app.js +21 -1
  2. index.html +1 -0
app.js CHANGED
@@ -57,11 +57,14 @@ function renderModels() {
57
  list.innerHTML = '';
58
  lanes.innerHTML = '';
59
  state.manifest.models.forEach(model => {
 
 
60
  const roles = model.roles.join(' / ');
61
  const item = document.createElement('button');
62
  item.className = 'model-item';
63
- item.innerHTML = `<span class="status ${model.status}"></span><span>${esc(model.name)}</span><small>${esc(model.format)} | ${esc(model.status)}</small>`;
64
  item.onclick = () => selectModel(model);
 
65
  list.appendChild(item);
66
  const lane = document.createElement('button');
67
  lane.className = `lane ${model.status}`;
@@ -71,6 +74,23 @@ function renderModels() {
71
  });
72
  }
73
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  function selectModel(model) {
75
  state.selected = model;
76
  $('#selected-model').textContent = model.name;
 
57
  list.innerHTML = '';
58
  lanes.innerHTML = '';
59
  state.manifest.models.forEach(model => {
60
+ const installed = JSON.parse(localStorage.getItem(`aide.model.${model.id}`) || 'null');
61
+ const visibleStatus = installed ? 'imported' : model.status;
62
  const roles = model.roles.join(' / ');
63
  const item = document.createElement('button');
64
  item.className = 'model-item';
65
+ item.innerHTML = `<span class="status ${visibleStatus}"></span><span>${esc(model.name)}</span><small>${esc(model.format)} | ${esc(visibleStatus)} | ${esc(roles)}</small><strong class="pack-action">${installed ? 'REPLACE' : 'IMPORT'}</strong>`;
66
  item.onclick = () => selectModel(model);
67
+ item.querySelector('.pack-action').onclick = event => { event.stopPropagation(); importModel(model); };
68
  list.appendChild(item);
69
  const lane = document.createElement('button');
70
  lane.className = `lane ${model.status}`;
 
74
  });
75
  }
76
 
77
+ async function importModel(model) {
78
+ const input = $('#model-file-input');
79
+ input.value = '';
80
+ input.onchange = async () => {
81
+ const file = input.files?.[0];
82
+ if (!file) return;
83
+ const digest = await crypto.subtle.digest('SHA-256', await file.arrayBuffer());
84
+ const hash = [...new Uint8Array(digest)].map(byte => byte.toString(16).padStart(2, '0')).join('');
85
+ const record = { id: model.id, name: file.name, bytes: file.size, sha256: hash, imported_at: new Date().toISOString(), source_repo: model.source_revision };
86
+ localStorage.setItem(`aide.model.${model.id}`, JSON.stringify(record));
87
+ appendLog('MODEL PACK', `${model.name} imported locally. SHA-256: ${hash}. Runtime attachment is still required before inference.`);
88
+ renderModels();
89
+ selectModel(model);
90
+ };
91
+ input.click();
92
+ }
93
+
94
  function selectModel(model) {
95
  state.selected = model;
96
  $('#selected-model').textContent = model.name;
index.html CHANGED
@@ -85,5 +85,6 @@
85
  </aside>
86
  </main>
87
  <script src="app.js"></script>
 
88
  </body>
89
  </html>
 
85
  </aside>
86
  </main>
87
  <script src="app.js"></script>
88
+ <input id="model-file-input" type="file" accept=".gguf,.safetensors" hidden>
89
  </body>
90
  </html>