offgrid-ai 0.3.20 → 0.3.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "offgrid-ai",
3
- "version": "0.3.20",
3
+ "version": "0.3.21",
4
4
  "description": "Privacy-first CLI for running local LLMs — discover, configure, run, benchmark",
5
5
  "author": "Eeshan Srivastava (https://eeshans.com)",
6
6
  "type": "module",
package/src/backends.mjs CHANGED
@@ -72,16 +72,18 @@ async function scanOllamaModels() {
72
72
  if (!response.ok) return [];
73
73
  const body = await response.json();
74
74
  if (!Array.isArray(body?.models)) return [];
75
- return body.models.map((model) => ({
76
- id: model.name,
77
- label: ollamaLabel(model.name),
78
- aliasSuggestion: model.name,
79
- sizeBytes: model.size ?? 0,
80
- quant: model.details?.quantization_level,
81
- family: model.details?.family,
82
- backend: "ollama",
83
- source: "ollama",
84
- })).sort((a, b) => a.label.localeCompare(b.label));
75
+ return body.models
76
+ .filter((model) => isLocalOllamaModel(model))
77
+ .map((model) => ({
78
+ id: model.name,
79
+ label: ollamaLabel(model.name),
80
+ aliasSuggestion: model.name,
81
+ sizeBytes: model.size ?? 0,
82
+ quant: model.details?.quantization_level,
83
+ family: model.details?.family,
84
+ backend: "ollama",
85
+ source: "ollama",
86
+ })).sort((a, b) => a.label.localeCompare(b.label));
85
87
  } catch {
86
88
  return [];
87
89
  }
@@ -112,6 +114,13 @@ async function scanOmlxModels() {
112
114
 
113
115
  // ── Labels ──────────────────────────────────────────────────────────────
114
116
 
117
+ function isLocalOllamaModel(model) {
118
+ const name = String(model?.name ?? "");
119
+ if (/:cloud(?:$|\b)/i.test(name)) return false;
120
+ if (!Number.isFinite(model?.size) || model.size <= 0) return false;
121
+ return true;
122
+ }
123
+
115
124
  function ollamaLabel(name) {
116
125
  return name.replace(/[-_]/g, " ").replace(/^gemma\b/i, "Gemma").replace(/^qwen/i, "Qwen");
117
126
  }
package/src/cli.mjs CHANGED
@@ -280,7 +280,7 @@ async function printModelCatalog({ profiles, newModels, managedItems }, items =
280
280
  const backendItems = managedItems.filter((item) => item.backendId === backendId);
281
281
  if (backendItems.length === 0) continue;
282
282
  const be = BACKENDS[backendId];
283
- console.log("\n" + pc.bold(`Available from ${be.label}`));
283
+ console.log("\n" + pc.bold(`Local models via ${be.label}`));
284
284
  for (const { model } of backendItems.slice(0, 10)) {
285
285
  const num = itemNumber((item) => item.type === "managed" && item.backendId === backendId && item.model.id === model.id);
286
286
  console.log(managedModelCard(num, model, be));
@@ -307,13 +307,13 @@ function downloadedModelCard(num, model, caps) {
307
307
  ["Good for", humanCapabilitySummary(caps)],
308
308
  ["Size", formatBytes(model.sizeBytes)],
309
309
  ["When selected", "offgrid-ai will recommend safe local settings"],
310
- ]), { formatBorder: caps.mtp ? pc.blue : pc.yellow });
310
+ ]), { formatBorder: pc.yellow });
311
311
  }
312
312
 
313
313
  function managedModelCard(num, model, backend) {
314
314
  return renderCard(`${num}. ${model.label}`, renderRows([
315
- ["Status", statusText("info", "Available from another app")],
316
- ["App", backend.label],
315
+ ["Status", statusText("info", `Local model via ${backend.label}`)],
316
+ ["Runs with", backend.label],
317
317
  ["Model ID", pc.cyan(model.id)],
318
318
  ...(model.quant ? [["Size/type", model.quant]] : []),
319
319
  ]), { formatBorder: pc.magenta });
@@ -36,14 +36,14 @@ export async function configureLocalProfile(prompt, profile) {
36
36
  console.log(pc.dim("You can accept the recommended settings. Bigger conversation memory uses more RAM.\n"));
37
37
 
38
38
  if (caps.mtp) {
39
- console.log(renderSection("Speed boost available", "This model supports fast draft mode. It can make responses feel faster while keeping everything local.\n\nAdvanced: uses llama.cpp MTP on port 8081."));
40
- const useMtp = await prompt.yesNo("Use fast draft mode for this model?", true);
39
+ console.log(renderSection("MTP available", "This model supports multi-token prediction (MTP). offgrid-ai can run it with llama.cpp MTP on port 8081."));
40
+ const useMtp = await prompt.yesNo("Use MTP for this model?", true);
41
41
  configured = useMtp ? applyMtpDefaults(configured) : removeMtpDefaults(configured);
42
42
  }
43
43
 
44
44
  if (caps.qat) {
45
45
  console.log("");
46
- console.log(renderSection("Optimized model", "This model was trained to work well after compression. No extra runtime settings are needed."));
46
+ console.log(renderSection("QAT model", "This model is marked as quantization-aware trained (QAT). No extra runtime settings are needed."));
47
47
  }
48
48
 
49
49
  if (caps.thinking) {
package/src/ui.mjs CHANGED
@@ -83,8 +83,8 @@ export function humanCapabilitySummary(caps = {}) {
83
83
  const parts = [];
84
84
  if (caps.thinking) parts.push(pc.magenta("Reasoning"));
85
85
  if (caps.vision) parts.push(pc.cyan("Vision"));
86
- if (caps.mtp) parts.push(pc.blue("Fast draft mode"));
87
- if (caps.qat) parts.push(pc.green("Optimized quantization"));
86
+ if (caps.mtp) parts.push(pc.blue("MTP"));
87
+ if (caps.qat) parts.push(pc.green("QAT"));
88
88
  return parts.length > 0 ? parts.join(" · ") : "General chat";
89
89
  }
90
90